mirror of
				https://github.com/RangeNetworks/openbts.git
				synced 2025-11-03 21:33:15 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			308 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			308 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
* Copyright 2014 Range Networks, Inc.
 | 
						|
*
 | 
						|
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribution.
 | 
						|
*
 | 
						|
* This use of this software may be subject to additional restrictions.
 | 
						|
* See the LEGAL file in the main directory for details.
 | 
						|
 | 
						|
    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.
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
#include "rnrad1.h"
 | 
						|
 | 
						|
using namespace ad9862;
 | 
						|
 | 
						|
rnrad1Rx::rnrad1Rx (int whichBoard,
 | 
						|
		    unsigned int wDecimRate,
 | 
						|
		    const std::string fpgaFilename = "",
 | 
						|
		    const std::string firmwareFilename = "")
 | 
						|
  : rnrad1Core(whichBoard,RAD1_RX_INTERFACE,RAD1_RX_ALTINTERFACE,fpgaFilename,firmwareFilename,false)
 | 
						|
{
 | 
						|
 | 
						|
  mDevHandle = 0;
 | 
						|
  mEndptHandle = 0;
 | 
						|
  mBytesSeen = 0;
 | 
						|
  mEnabled = false;
 | 
						|
  mDecimRate = wDecimRate;
 | 
						|
 | 
						|
  // initialize rx specific registers
 | 
						|
  // initialize registers that are common to rx and tx
 | 
						|
  bool result=true;
 | 
						|
  result &= write9862(REG_RX_PWR_DN,0);
 | 
						|
  result &= write9862(REG_RX_A,0);      // minimum gain = 0x00 (max gain = 0x14)
 | 
						|
  result &= write9862(REG_RX_B,0);      // minimum gain = 0x00 (max gain = 0x14)
 | 
						|
  result &= write9862(REG_RX_MISC,RX_MISC_HS_DUTY_CYCLE | RX_MISC_CLK_DUTY);
 | 
						|
  result &= write9862(REG_RX_IF,RX_IF_USE_CLKOUT1 | RX_IF_2S_COMP);
 | 
						|
  result &= write9862(REG_RX_DIGITAL,RX_DIGITAL_2_CHAN);
 | 
						|
  if (!result) {
 | 
						|
    LOG(ERR) << "Failed to init AD9862 RX regs";
 | 
						|
    exit(1);
 | 
						|
  }
 | 
						|
 | 
						|
  // Reset the rx path and leave it disabled.
 | 
						|
  enable (false);
 | 
						|
 | 
						|
  sendRqst(VRQ_FPGA_SET_RX_RESET, 1);
 | 
						|
  usleep(10);
 | 
						|
  sendRqst(VRQ_FPGA_SET_RX_RESET, 0);
 | 
						|
 | 
						|
  setSampleRateDivisor (2);	// usually correct
 | 
						|
 | 
						|
  setDcOffsetClEnable(0xf, 0xf);	// enable DC offset removal control loops
 | 
						|
 | 
						|
  // check fusb buffering parameters
 | 
						|
  int blockSize = 4096; //fusb::default_block_size();
 | 
						|
  int numBlocks = 128; //std::max (1, fusb::default_buffer_size() / blockSize);
 | 
						|
 | 
						|
  mDevHandle = fusb::make_devhandle (getHandle(), getContext());
 | 
						|
  mEndptHandle = mDevHandle->make_ephandle (RAD1_RX_ENDPOINT, true,
 | 
						|
					   blockSize, numBlocks);
 | 
						|
 | 
						|
  writeFpgaReg(FR_ATR_MASK_1,0);
 | 
						|
  writeFpgaReg(FR_ATR_TXVAL_1,0);
 | 
						|
  writeFpgaReg(FR_ATR_RXVAL_1,0);
 | 
						|
  writeFpgaReg(FR_ATR_MASK_3,0);
 | 
						|
  writeFpgaReg(FR_ATR_TXVAL_3,0);
 | 
						|
  writeFpgaReg(FR_ATR_RXVAL_3,0);
 | 
						|
 | 
						|
  mSwMux = 0;
 | 
						|
  mHwMux = 0;
 | 
						|
 | 
						|
  writeFpgaReg(FR_RX_FORMAT,0x00000300);
 | 
						|
  writeHwMuxReg();
 | 
						|
  setDecimRate(mDecimRate);
 | 
						|
  unsigned int mux = 0x00000010;
 | 
						|
  setMux(mux);
 | 
						|
  writeFpgaReg(FR_MODE, 0);
 | 
						|
  setRxFreq(0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
rnrad1Rx::~rnrad1Rx()
 | 
						|
{
 | 
						|
  enable (false);
 | 
						|
  
 | 
						|
  delete mEndptHandle;
 | 
						|
  delete mDevHandle;
 | 
						|
  
 | 
						|
  // initialize registers that are common to rx and tx
 | 
						|
  bool result= write9862(REG_RX_PWR_DN,0x1);
 | 
						|
  
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool rnrad1Rx::writeHwMuxReg()
 | 
						|
{
 | 
						|
  bool s = disable();
 | 
						|
  bool ok = writeFpgaReg (FR_RX_MUX, mHwMux | 1);
 | 
						|
  restore (s);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool rnrad1Rx::setRxFreq (double freq)
 | 
						|
{
 | 
						|
  int   v = (int) rint (freq / (double) adcRate() * pow (2.0, 32.0));
 | 
						|
  mRxFreq = v * (double) adcRate() / pow (2.0, 32.0);
 | 
						|
  return writeFpgaReg (FR_RX_FREQ_0, v);
 | 
						|
}
 | 
						|
 | 
						|
rnrad1Rx *rnrad1Rx::make(int whichBoard,
 | 
						|
			 unsigned int wDecimRate,
 | 
						|
			 const std::string fpgaFilename = "",
 | 
						|
			 const std::string firmwareFilename = "")
 | 
						|
{
 | 
						|
  try {
 | 
						|
    rnrad1Rx *u = new rnrad1Rx(whichBoard,
 | 
						|
			       wDecimRate,
 | 
						|
			       fpgaFilename,
 | 
						|
			       firmwareFilename);
 | 
						|
    return u;
 | 
						|
  }
 | 
						|
  catch (...) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool rnrad1Rx::setDecimRate (unsigned int rate)
 | 
						|
{
 | 
						|
  if ((rate & 0x1) || rate < 4 || rate > 256){
 | 
						|
      LOG(ERR) << "decimation rate must be EVEN and in [4, 256]";
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
  mDecimRate = rate;
 | 
						|
  setUsbDataRate ((adcRate()/rate) * (2 * sizeof (short)));
 | 
						|
 | 
						|
  bool s = disable ();
 | 
						|
  int v = mDecimRate/2 - 1;
 | 
						|
  bool ok = writeFpgaReg (FR_DECIM_RATE, v);
 | 
						|
  restore (s);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool rnrad1Rx::setMux (int mux)
 | 
						|
{
 | 
						|
  int mHwMux = 0;
 | 
						|
  for (int i = 0; i < 8; i++){
 | 
						|
    int t = (mux >> (4 * i)) & 0x3;
 | 
						|
    mHwMux |= t << (2 * i + 4);
 | 
						|
  }
 | 
						|
  mSwMux = mux;
 | 
						|
  return writeHwMuxReg ();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool rnrad1Rx::start()
 | 
						|
{
 | 
						|
  if (!rnrad1Core::start ())	// invoke parent's method
 | 
						|
    return false;
 | 
						|
  
 | 
						|
  // fire off reads before asserting rx_enable
 | 
						|
  
 | 
						|
  if (!mEndptHandle->start ()){
 | 
						|
    LOG(ERR) << "Can't start USB RX stream";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!enable (true)){
 | 
						|
    LOG(ERR) << "Can't enable RX";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool rnrad1Rx::setSampleRateDivisor (unsigned int div)
 | 
						|
{
 | 
						|
  return writeFpgaReg (FR_RX_SAMPLE_RATE_DIV, div - 1);
 | 
						|
}
 | 
						|
 | 
						|
int rnrad1Rx::read (void *buf, int len, bool *overrun)
 | 
						|
{
 | 
						|
  int	r;
 | 
						|
  
 | 
						|
  if (overrun) *overrun = false;
 | 
						|
  
 | 
						|
  if (len < 0 || (len % 512) != 0){
 | 
						|
    LOG(ERR) << "read: invalid length = " << len;
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  
 | 
						|
  r = mEndptHandle->read (buf, len);
 | 
						|
  if (r > 0) mBytesSeen += r;
 | 
						|
  
 | 
						|
  if (overrun != 0 && mBytesSeen >= mBytesPerPoll){
 | 
						|
    mBytesSeen = 0;
 | 
						|
    *overrun = true;
 | 
						|
    unsigned char status;
 | 
						|
    if (checkOverrun(&status) != 1)
 | 
						|
      LOG(ERR) << "Overrun check failed";
 | 
						|
    *overrun = status;
 | 
						|
  }
 | 
						|
 | 
						|
  return r;
 | 
						|
}
 | 
						|
 | 
						|
bool rnrad1Rx::enable (bool on)
 | 
						|
{
 | 
						|
  mEnabled = on;
 | 
						|
  return (sendRqst(VRQ_FPGA_SET_RX_ENABLE, on) == 0);
 | 
						|
}
 | 
						|
 | 
						|
// conditional disable, return prev state
 | 
						|
bool rnrad1Rx::disable ()
 | 
						|
{
 | 
						|
  bool enabled = enable ();
 | 
						|
  if (enabled) enable (false);
 | 
						|
  return enabled;
 | 
						|
}
 | 
						|
 | 
						|
// conditional set
 | 
						|
void rnrad1Rx::restore (bool on)
 | 
						|
{
 | 
						|
  if (on != enable ()) enable (on);
 | 
						|
}
 | 
						|
 | 
						|
bool rnrad1Rx::setPga (int amp, double gain)
 | 
						|
{
 | 
						|
  if (amp < 0 || amp > 1)
 | 
						|
    return false;
 | 
						|
  
 | 
						|
  gain = std::min(pgaMax(), std::max(pgaMin(), gain));
 | 
						|
  int intGain = (int) rint((gain - pgaMin()) / pgaDbPerStep());
 | 
						|
  int reg = (amp & 1 == 0) ? REG_RX_A : REG_RX_B;
 | 
						|
  // read current value to get input buffer bypass flag.
 | 
						|
  unsigned char curRx;
 | 
						|
  if (!read9862(reg, &curRx))
 | 
						|
    return false;
 | 
						|
  
 | 
						|
  curRx = (curRx & RX_X_BYPASS_INPUT_BUFFER) | (intGain & 0x7f);
 | 
						|
  return write9862(reg, curRx);
 | 
						|
  
 | 
						|
}
 | 
						|
 | 
						|
double rnrad1Rx::pga (int amp) const
 | 
						|
{
 | 
						|
  if (amp < 0 || amp > 1) return READ_FAILED;
 | 
						|
  int reg = (amp & 1 == 0) ? REG_RX_A : REG_RX_B;
 | 
						|
  unsigned char v;
 | 
						|
  if (!read9862 (reg, &v)) return READ_FAILED;
 | 
						|
  return (pgaDbPerStep() * (v & 0x1f)) + pgaMin();
 | 
						|
}
 | 
						|
 | 
						|
bool rnrad1Rx::writeOE (int value, int mask) 
 | 
						|
{
 | 
						|
  return writeFpgaReg(FR_OE_1, (mask << 16) | (value & 0xffff));
 | 
						|
}
 | 
						|
 | 
						|
bool rnrad1Rx::writeIO (int value, int mask)
 | 
						|
{
 | 
						|
  return writeFpgaReg(FR_IO_1, (mask << 16) | (value & 0xffff));
 | 
						|
}
 | 
						|
 | 
						|
bool rnrad1Rx::readIO (int *value)
 | 
						|
{
 | 
						|
  int t;
 | 
						|
  int reg = 0 + 1;      // FIXME, *very* magic number (fix in serial_io.v)
 | 
						|
  if (!readFpgaReg(reg, &t)) return false;
 | 
						|
  *value = (t >> 16) & 0xffff;        // FIXME, more magic
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
int rnrad1Rx::readIO (void)
 | 
						|
{
 | 
						|
  int   value;
 | 
						|
  if (!readIO(&value)) return READ_FAILED;
 | 
						|
  return value;
 | 
						|
}
 | 
						|
 | 
						|
bool rnrad1Rx::writeRefClk(int value)
 | 
						|
{
 | 
						|
  return writeFpgaReg(FR_RX_A_REFCLK, value);
 | 
						|
}
 | 
						|
 | 
						|
bool rnrad1Rx::writeAuxDac (int dac, int value)
 | 
						|
{
 | 
						|
  return rnrad1Core::writeAuxDac(dac, value);
 | 
						|
}
 | 
						|
 | 
						|
bool rnrad1Rx::readAuxAdc (int adc, int *value)
 | 
						|
{
 | 
						|
  return rnrad1Core::readAuxAdc(false, adc, value);
 | 
						|
}
 | 
						|
 | 
						|
int  rnrad1Rx::readAuxAdc (int adc)
 | 
						|
{
 | 
						|
  int retVal;
 | 
						|
  rnrad1Rx::readAuxAdc(adc, &retVal);
 | 
						|
  return retVal;
 | 
						|
}
 | 
						|
 | 
						|
int rnrad1Rx::blockSize() const { return mEndptHandle->block_size(); }
 | 
						|
 | 
						|
 |