mirror of
				https://github.com/RangeNetworks/openbts.git
				synced 2025-11-04 05:43:14 +00:00 
			
		
		
		
	transceiver: separate I/O portion of radio interface implementation
Move push and pull of buffers into a dedicated file. This will allow us to swap out resampling, non-resampling, and possibly floating point device interfaces while presenting a single floating point abstration in the interface itself. Signed-off-by: Thomas Tsou <ttsou@vt.edu> git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@2670 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
		@@ -46,7 +46,8 @@ COMMON_SOURCES = \
 | 
				
			|||||||
	DummyLoad.cpp
 | 
						DummyLoad.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
libtransceiver_la_SOURCES = \
 | 
					libtransceiver_la_SOURCES = \
 | 
				
			||||||
	$(COMMON_SOURCES)
 | 
						$(COMMON_SOURCES) \
 | 
				
			||||||
 | 
						radioIO.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
noinst_PROGRAMS = \
 | 
					noinst_PROGRAMS = \
 | 
				
			||||||
	USRPping \
 | 
						USRPping \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										91
									
								
								Transceiver52M/radioIO.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								Transceiver52M/radioIO.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Radio device I/O interface
 | 
				
			||||||
 | 
					 * Written by Thomas Tsou <ttsou@vt.edu>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright 2011 Free Software Foundation, Inc.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 * See the COPYING file in the main directory for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <radioInterface.h>
 | 
				
			||||||
 | 
					#include <Logger.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Device side buffers */
 | 
				
			||||||
 | 
					static short rx_buf[OUTCHUNK * 2 * 2];
 | 
				
			||||||
 | 
					static short tx_buf[INCHUNK * 2 * 2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Complex float to short conversion */
 | 
				
			||||||
 | 
					static int float_to_short(short *shrt_out, float *flt_in, int num)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < num; i++) {
 | 
				
			||||||
 | 
							shrt_out[2 * i + 0] = flt_in[2 * i + 0];
 | 
				
			||||||
 | 
							shrt_out[2 * i + 1] = flt_in[2 * i + 1];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Comlpex short to float conversion */
 | 
				
			||||||
 | 
					static int short_to_float(float *flt_out, short *shrt_in, int num)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < num; i++) {
 | 
				
			||||||
 | 
							flt_out[2 * i + 0] = shrt_in[2 * i + 0];
 | 
				
			||||||
 | 
							flt_out[2 * i + 1] = shrt_in[2 * i + 1];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Receive a timestamped chunk from the device */ 
 | 
				
			||||||
 | 
					void RadioInterface::pullBuffer()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool local_underrun;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Read samples. Fail if we don't get what we want. */
 | 
				
			||||||
 | 
						int num_rd = mRadio->readSamples(rx_buf, OUTCHUNK, &overrun,
 | 
				
			||||||
 | 
										    readTimestamp, &local_underrun);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOG(DEBUG) << "Rx read " << num_rd << " samples from device";
 | 
				
			||||||
 | 
						assert(num_rd == OUTCHUNK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						underrun |= local_underrun;
 | 
				
			||||||
 | 
						readTimestamp += (TIMESTAMP) num_rd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						short_to_float(rcvBuffer + 2 * rcvCursor, rx_buf, num_rd);
 | 
				
			||||||
 | 
						rcvCursor += num_rd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Send timestamped chunk to the device with arbitrary size */ 
 | 
				
			||||||
 | 
					void RadioInterface::pushBuffer()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (sendCursor < INCHUNK)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						float_to_short(tx_buf, sendBuffer, sendCursor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Write samples. Fail if we don't get what we want. */
 | 
				
			||||||
 | 
						int num_smpls = mRadio->writeSamples(tx_buf,
 | 
				
			||||||
 | 
										     sendCursor,
 | 
				
			||||||
 | 
										     &underrun,
 | 
				
			||||||
 | 
										     writeTimestamp);
 | 
				
			||||||
 | 
						assert(num_smpls == sendCursor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						writeTimestamp += (TIMESTAMP) num_smpls;
 | 
				
			||||||
 | 
						sendCursor = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -25,6 +25,8 @@
 | 
				
			|||||||
#include "radioInterface.h"
 | 
					#include "radioInterface.h"
 | 
				
			||||||
#include <Logger.h>
 | 
					#include <Logger.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool started = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RadioInterface::RadioInterface(RadioDevice *wRadio,
 | 
					RadioInterface::RadioInterface(RadioDevice *wRadio,
 | 
				
			||||||
                               int wReceiveOffset,
 | 
					                               int wReceiveOffset,
 | 
				
			||||||
			       int wRadioOversampling,
 | 
								       int wRadioOversampling,
 | 
				
			||||||
@@ -73,94 +75,40 @@ void RadioInterface::setPowerAttenuation(double atten)
 | 
				
			|||||||
    powerScaling = 1.0/sqrt(pow(10, (digAtten/10.0)));
 | 
					    powerScaling = 1.0/sqrt(pow(10, (digAtten/10.0)));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
short *RadioInterface::radioifyVector(signalVector &wVector,
 | 
					int RadioInterface::radioifyVector(signalVector &wVector,
 | 
				
			||||||
                                      short *retVector,
 | 
									   float *retVector,
 | 
				
			||||||
                                      float scale,
 | 
									   float scale,
 | 
				
			||||||
                                      bool zeroOut)
 | 
									   bool zero)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					  int i;
 | 
				
			||||||
  signalVector::iterator itr = wVector.begin();
 | 
					  signalVector::iterator itr = wVector.begin();
 | 
				
			||||||
  short *shortItr = retVector;
 | 
					
 | 
				
			||||||
  if (zeroOut) {
 | 
					  if (zero) {
 | 
				
			||||||
    while (itr < wVector.end()) {
 | 
					    memset(retVector, 0, wVector.size() * 2 * sizeof(float));
 | 
				
			||||||
      *shortItr++ = 0;
 | 
					    return wVector.size();
 | 
				
			||||||
      *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;
 | 
					  for (i = 0; i < wVector.size(); i++) {
 | 
				
			||||||
 | 
					    retVector[2 * i + 0] = itr->real() * scale;
 | 
				
			||||||
 | 
					    retVector[2 * i + 1] = itr->imag() * scale;
 | 
				
			||||||
 | 
					    itr++;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return wVector.size();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RadioInterface::unRadioifyVector(short *shortVector, signalVector& newVector)
 | 
					int RadioInterface::unRadioifyVector(float *floatVector,
 | 
				
			||||||
 | 
									     signalVector& newVector)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  
 | 
					  int i;
 | 
				
			||||||
  signalVector::iterator itr = newVector.begin();
 | 
					  signalVector::iterator itr = newVector.begin();
 | 
				
			||||||
  short *shortItr = shortVector;
 | 
					
 | 
				
			||||||
  while (itr < newVector.end()) {
 | 
					  for (i = 0; i < newVector.size(); i++) {
 | 
				
			||||||
    *itr++ = Complex<float>(*shortItr,*(shortItr+1));
 | 
					    *itr++ = Complex<float>(floatVector[2 * i + 0],
 | 
				
			||||||
    shortItr += 2;
 | 
								    floatVector[2 * i + 1]);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					  return newVector.size();
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool started = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void RadioInterface::pushBuffer(void) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (sendCursor < 2*INCHUNK*samplesPerSymbol) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // send resampleVector
 | 
					 | 
				
			||||||
  int samplesWritten = mRadio->writeSamples(sendBuffer,
 | 
					 | 
				
			||||||
					  INCHUNK*samplesPerSymbol,
 | 
					 | 
				
			||||||
					  &underrun,
 | 
					 | 
				
			||||||
					  writeTimestamp); 
 | 
					 | 
				
			||||||
   
 | 
					 | 
				
			||||||
  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)
 | 
					bool RadioInterface::tuneTx(double freq)
 | 
				
			||||||
@@ -186,8 +134,8 @@ void RadioInterface::start()
 | 
				
			|||||||
  mRadio->updateAlignment(writeTimestamp-10000); 
 | 
					  mRadio->updateAlignment(writeTimestamp-10000); 
 | 
				
			||||||
  mRadio->updateAlignment(writeTimestamp-10000);
 | 
					  mRadio->updateAlignment(writeTimestamp-10000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  sendBuffer = new short[2*2*INCHUNK*samplesPerSymbol];
 | 
					  sendBuffer = new float[2*2*INCHUNK*samplesPerSymbol];
 | 
				
			||||||
  rcvBuffer = new short[2*2*OUTCHUNK*samplesPerSymbol];
 | 
					  rcvBuffer = new float[2*2*OUTCHUNK*samplesPerSymbol];
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
  mOn = true;
 | 
					  mOn = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -211,9 +159,9 @@ void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (!mOn) return;
 | 
					  if (!mOn) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  radioifyVector(radioBurst, sendBuffer+sendCursor, powerScaling, zeroBurst);
 | 
					  radioifyVector(radioBurst, sendBuffer + 2 * sendCursor, powerScaling, zeroBurst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  sendCursor += (radioBurst.size()*2);
 | 
					  sendCursor += radioBurst.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pushBuffer();
 | 
					  pushBuffer();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -229,7 +177,7 @@ void RadioInterface::driveReceiveRadio() {
 | 
				
			|||||||
  GSM::Time rcvClock = mClock.get();
 | 
					  GSM::Time rcvClock = mClock.get();
 | 
				
			||||||
  rcvClock.decTN(receiveOffset);
 | 
					  rcvClock.decTN(receiveOffset);
 | 
				
			||||||
  unsigned tN = rcvClock.TN();
 | 
					  unsigned tN = rcvClock.TN();
 | 
				
			||||||
  int rcvSz = rcvCursor/2;
 | 
					  int rcvSz = rcvCursor;
 | 
				
			||||||
  int readSz = 0;
 | 
					  int readSz = 0;
 | 
				
			||||||
  const int symbolsPerSlot = gSlotLen + 8;
 | 
					  const int symbolsPerSlot = gSlotLen + 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -264,8 +212,8 @@ void RadioInterface::driveReceiveRadio() {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (readSz > 0) {
 | 
					  if (readSz > 0) {
 | 
				
			||||||
    memcpy(rcvBuffer,rcvBuffer+2*readSz,sizeof(short)*2*(rcvCursor-readSz));
 | 
					    rcvCursor -= readSz;
 | 
				
			||||||
    rcvCursor = rcvCursor-2*readSz;
 | 
					    memmove(rcvBuffer,rcvBuffer+2*readSz,sizeof(float) * 2 * rcvCursor);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
} 
 | 
					} 
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,10 +37,10 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  RadioDevice *mRadio;			      ///< the USRP object
 | 
					  RadioDevice *mRadio;			      ///< the USRP object
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
  short *sendBuffer; //[2*2*INCHUNK];
 | 
					  float *sendBuffer;
 | 
				
			||||||
  unsigned sendCursor;
 | 
					  unsigned sendCursor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  short *rcvBuffer; //[2*2*OUTCHUNK];
 | 
					  float *rcvBuffer;
 | 
				
			||||||
  unsigned rcvCursor;
 | 
					  unsigned rcvCursor;
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
  bool underrun;			      ///< indicates writes to USRP are too slow
 | 
					  bool underrun;			      ///< indicates writes to USRP are too slow
 | 
				
			||||||
@@ -64,13 +64,13 @@ private:
 | 
				
			|||||||
  signalVector *finalVec, *finalVec9;
 | 
					  signalVector *finalVec, *finalVec9;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** format samples to USRP */ 
 | 
					  /** format samples to USRP */ 
 | 
				
			||||||
  short *radioifyVector(signalVector &wVector,
 | 
					  int radioifyVector(signalVector &wVector,
 | 
				
			||||||
                        short *shortVector,
 | 
					                     float *floatVector,
 | 
				
			||||||
                        float scale,
 | 
					                     float scale,
 | 
				
			||||||
                        bool zeroOut);
 | 
					                     bool zero);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** format samples from USRP */
 | 
					  /** format samples from USRP */
 | 
				
			||||||
  void unRadioifyVector(short *shortVector, signalVector &wVector);
 | 
					  int unRadioifyVector(float *floatVector, signalVector &wVector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** push GSM bursts into the transmit buffer */
 | 
					  /** push GSM bursts into the transmit buffer */
 | 
				
			||||||
  void pushBuffer(void);
 | 
					  void pushBuffer(void);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user