Removed unused RadioInterface methods and data. BladeRF driver is now advertising radio caps and is accumulating data to send to avoid short write operations.

git-svn-id: http://yate.null.ro/svn/yate/trunk@6055 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2015-10-12 15:06:31 +00:00
parent a4ce1f1ed5
commit fb066c3e51
6 changed files with 138 additions and 509 deletions

View File

@ -25,14 +25,6 @@
; Valid values 100000 - 5000000, default 250000
;filter_step=250000
; rx_latency: integer: Simulated receiver latency (samples)
; Valid values 0 - 50000, default 10000
;rx_latency=10000
; tx_latency: integer: Simulated transmitter latency (samples)
; Valid values 0 - 50000, default 10000
;tx_latency=10000
; The following parameters correspond to members of the RadioCapability structure
; maxTuneFreq: integer: Maximum tunable frequency (Hz)
@ -43,22 +35,6 @@
; Default values 250000000 - 5000000000, default 500000000
;minTuneFreq=500000000
; maxOutputPower: integer: Maximum settable output power (dBm)
; Valid values 0 - 50, default 30
;maxOutputPower=30
; minOutputPower: integer: Minimum settable output power (dBm)
; Valid values -10 - 30, default 0
;minOutputPower=0
; maxInputSaturation: integer: Maximum settable receiver saturation level (dBm)
; Valid values -50 - 0, default -30
;maxInputSaturation=-30
; minInputSaturation: integer: Minimum settable receiver saturation level (dBm)
; Valid values -80 - -30, default -50
;minInputSaturation=-50
; maxSampleRate: integer: Maximum settable sample rate (Hz)
; valid values 5000000 - 50000000, default 20000000
;maxSampleRate=20000000
@ -75,6 +51,14 @@
; Valid values 100000 - 5000000, default 1500000
;minFilterBandwidth=1500000
; rxLatency: integer: Simulated receiver latency (samples)
; Valid values 0 - 50000, default 10000
;rxLatency=10000
; txLatency: integer: Simulated transmitter latency (samples)
; Valid values 0 - 50000, default 10000
;txLatency=10000
; profiling: boolean: True if a profiling tool is running
; Disable some time related capabilities
;profiling=no

View File

@ -44,6 +44,16 @@
; positive: the number of times to check
;rxcheckts=-1
; tx_min_buffers: integer: Minimum number of buffers (USB frames) to send
; This option is used to accumulate data before sending it (avoid short write operations)
; Minimum allowed value is 1
; Defaults to the number of allocated buffers
;tx_min_buffers=
; silence_time: integer: Interval (in milliseconds) to silence timestamp related debug messages
; Allowed interval [0..60000]
;silence_time=5000
; rx_ts_past_error_interval: integer: Interval (in milliseconds) for allowed late timestamps
; when reading from device. I.e. how many old samples in a row we accept when reading
; This value is used to make sure we are returning from device read (with error): avoid

View File

@ -314,60 +314,16 @@ public:
*/
RadioCapability();
// Application-level parameters
// Hardware
unsigned maxPorts; // the maximum allowed ports
unsigned currPorts; // the currently available ports
// Tuning
uint64_t maxTuneFreq; // maximum allowed tuning frequency, Hz
uint64_t minTuneFreq; // minimum allowed tuning frequency, Hz
// Output power
float maxOutputPower; // maximum allowed output power, dBm
float minOutputPower; // minimum allowed output power, dBm
// Input gain (saturation point)
float maxInputSaturation; // maximum selectable saturation point, dBm
float minInputSaturation; // minimum selectable saturation point, dBm
// Sample rate
unsigned maxSampleRate; // max in Hz
unsigned minSampleRate; // min in Hz
// Anti-alias filter bandwidth
unsigned maxFilterBandwidth; // max in Hz
unsigned minFilterBandwidth; // min in Hz
// Calibration parameters
// Tx Gain Control
int txGain1MaxVal; // max allowed value
int txGain1MinVal; // min allowed value
float txGain1StepSize; // control step size in dB
int txGain2MaxVal; // max allowed value
int txGain2MinVal; // min allowed value
float txGain2StepSize; // control step size in dB
// Rx Gain Control
int rxGain1MaxVal; // max allowed value
int rxGain1MinVal; // min allowed value
float rxGain1StepSize; // control step size in dB
int rxGain2MaxVal; // max allowed value
int rxGain2MinVal; // min allowed value
float rxGain2StepSize; // control step size in dB
// Freq Cal Control
unsigned freqCalControlMaxVal; // maximum value of frequency control parameter
unsigned freqCalControlMinVal; // minimum value of frequency control parameter
float freqCalControlStepSize; // avg step size in Hz
// IQ Offset Control
unsigned iqOffsetMaxVal; // max allowed value
unsigned iqOffsetMinVal; // min allowed value
float iqOffsetStepSize; // control step size as fraction of full scale
// IQ Gain Balance Control
unsigned iqBalanceMaxVal; // max allowed value
unsigned iqBalanceMinVal; // min allowed value
float iqBalanceStepSize; // control step size in dB of I/Q
// IQ Delay Control
unsigned iqDelayMaxVal; // max allowed value
unsigned iqDelayMinVal; // min allowed value
float iqDelayStepSize; // control step size in fractions of a sample
// Phase control
unsigned phaseCalMaxVal; // max allowed value
unsigned phaseCalMinVal; // min allowed value
float phaseCalStepSize; // control step size in radians
unsigned maxPorts; // Available number of ports
unsigned currPorts; // Number of used (available) ports
uint64_t maxTuneFreq; // Maximum allowed tuning frequency (in Hz)
uint64_t minTuneFreq; // Minimum allowed tuning frequency (in Hz)
unsigned maxSampleRate; // Maximum allowed sampling rate (in Hz)
unsigned minSampleRate; // Minimum allowed sampling rate (in Hz)
unsigned maxFilterBandwidth; // Maximum allowed anti-alias filter bandwidth (in Hz)
unsigned minFilterBandwidth; // Minimum allowed anti-alias filter bandwidth (in Hz)
unsigned rxLatency; // Estimated radio latency (in samples)
unsigned txLatency; // Estimated transmit latency (in samples)
};
@ -567,7 +523,15 @@ public:
virtual unsigned int initialize(const NamedList& params = NamedList::empty()) = 0;
/**
* Set multiple intrface parameters.
* Set radio loopback
* @param name Loopback name (NULL for none)
* @return Error code (0 on success)
*/
virtual unsigned int setLoopback(const char* name = 0)
{ return NotSupported; }
/**
* Set multiple interface parameters.
* Each command must start with 'cmd:' to allow the code to detect unhandled commands.
* Command sub-params should not start with the prefix
* @param params Parameters list
@ -591,8 +555,7 @@ public:
const NamedList* params = 0) = 0;
/**
* Run internal calibration procedures and/or load calibration parmameters.
* Any attempt to transmit or receive prior to this operation will return NotCalibrated.
* Run internal calibration procedures and/or load calibration parmameters
* @return Error code (0 on success)
*/
virtual unsigned int calibrate()
@ -603,7 +566,7 @@ public:
* @param count The number of ports to be used
* @return Error code (0 on success)
*/
virtual unsigned int setPorts(unsigned count) const = 0;
virtual unsigned int setPorts(unsigned count) = 0;
/**
* Return any persistent error codes.
@ -667,13 +630,6 @@ public:
virtual unsigned int read(uint64_t& when, RadioReadBufs& bufs,
unsigned int& skippedBufs);
/**
* Get the current radio time at the MSFE converter
* @param when Destination buffer for requested radio time
* @return Error code (0 on success)
*/
virtual unsigned int getTime(uint64_t& when) const = 0;
/**
* Get the time of the data currently being received from the radio
* @param when Destination buffer for requested radio time
@ -762,132 +718,35 @@ public:
virtual unsigned int getRxFreq(uint64_t& hz) const = 0;
/**
* Set the input gain reference level in dBm.
* This sets the satuation point of the receiver in dBm.
* @param dBm Input gain value
* @return Error code (0 on success)
*/
virtual unsigned int setRxSaturationPoint(int dBm)
{ return NotSupported; }
/**
* Get the current rx gain reference level in dBm
* @param dBm Receive gain value
* @return Error code (0 on success)
*/
virtual unsigned int getRxSaturationPoint(int& dBm) const
{ return NotSupported; }
/**
* Get the expected receiver noise floor in dBm.
* This takes into account all noise sources in the receiver:
* - thermal + noise figure
* - quantization noise
* @param dBm Receiver noise floor value
* @return Error code (0 on success)
*/
virtual unsigned int getExpectedNoiseFloor(int& dBm) const
{ return NotSupported; }
/**
* Set radio loopback
* @param name Loopback name (NULL for none)
* @return Error code (0 on success)
*/
virtual unsigned int setLoopback(const char* name = 0)
{ return NotSupported; }
/**
* Put the radio into normal mode
* @return Error code (0 on success)
*/
virtual unsigned int setRadioNormal()
{ return NotSupported; }
/**
* Set software loopback inside the interface class
* @return Error code (0 on success)
*/
virtual unsigned int setSRadioLoopbackSW()
{ return NotSupported; }
/**
* Set hardware loopback inside the radio, pre-mixer
* @return Error code (0 on success)
*/
virtual unsigned int setRadioLoopbackBaseband()
{ return NotSupported; }
/**
* Set hardware loopback inside the radio, post-mixer
* @return Error code (0 on success)
*/
virtual unsigned int setRadioLoopbackRF()
{ return NotSupported; }
/**
* Turn off modulation, and/or send DC
* @return Error code (0 on success)
*/
virtual unsigned int setRadioUnmodulated(float i = 0.0F, float q = 0.0F)
{ return NotSupported; }
virtual unsigned int getPowerConsumption(float& watts) const
{ return NotSupported; }
virtual unsigned int getPowerOutput(float& dBm, unsigned port) const
{ return NotSupported; }
virtual unsigned int getVswr(float& dB, unsigned port) const
{ return NotSupported; }
virtual unsigned int getTemperature(float& degrees) const
{ return NotSupported; }
/**
* Calibration. Set the transmit pre-mixer gain in dB wrt max
* Set the transmit pre-mixer gain in dB wrt max
* @return Error code (0 on success)
*/
virtual unsigned int setTxGain1(int val, unsigned port)
{ return NotSupported; }
/**
* Calibration. Set the transmit post-mixer gain in dB wrt max
* Set the transmit post-mixer gain in dB wrt max
* @return Error code (0 on success)
*/
virtual unsigned int setTxGain2(int val, unsigned port)
{ return NotSupported; }
/**
* Calibration. Automatic tx gain setting
* @return Error code (0 on success)
*/
virtual unsigned int autocalTxGain() const
{ return NotSupported; }
/**
* Calibration. Set the receive pre-mixer gain in dB wrt max
* Set the receive pre-mixer gain in dB wrt max
* @return Error code (0 on success)
*/
virtual unsigned int setRxGain1(int val, unsigned port)
{ return NotSupported; }
/**
* Calibration. Set the receive post-mixer gain in dB wrt max
* Set the receive post-mixer gain in dB wrt max
* @return Error code (0 on success)
*/
virtual unsigned int setRxGain2(int val, unsigned port)
{ return NotSupported; }
/**
* Calibration. Automatic rx gain setting
* @return Error code (0 on success)
*/
virtual unsigned int autocalRxGain() const
{ return NotSupported; }
/**
* Calibration. Automatic tx/rx gain setting
* Automatic tx/rx gain setting
* Set post mixer value. Return a value to be used by upper layer
* @param tx Direction
* @param val Value to set
@ -899,194 +758,6 @@ public:
int* newVal = 0) const
{ return NotSupported; }
// Frequency calibration.
// The "val" here is a integer tuning control
// on a scale that is specific to the hardware.
// There are readback and write methodss to support a closed-loop search.
// There is also a method to report the mean freq control step size.
/**
* @return Error code (0 on success)
*/
virtual unsigned int getFreqCal(int& val) const
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int setFreqCal(int val)
{ return NotSupported; }
/**
* For automatic frequency calibration, the radio is presented
* with a carrier at a calibrated feqeuency.
* @return Error code (0 on success)
*/
virtual unsigned int autoCalFreq(uint64_t refFreqHz)
{ return NotSupported; }
/**
* Calibration. Automatic TX/RX DC calibration
* @return Error code (0 on success)
*/
virtual unsigned int autocalDCOffsets()
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int getTxIOffsetCal(int& val, unsigned port) const
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int getTxQOffsetCal(int& val, unsigned port) const
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int getRxIOffsetCal(int& val, unsigned port) const
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int getRxQOffsetCal(int& val, unsigned port) const
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int setTxIOffsetCal(int val, unsigned port) const
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int setTxQOffsetCal(int val, unsigned port) const
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int setRxIOffsetCal(int val, unsigned port) const
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int setRxQOffsetCal(int val, unsigned port) const
{ return NotSupported; }
/**
* Automatic IQ offset calibration, if the hardware supports it.
* @param port Port number, -1 for all ports
* @return Error code (0 on success)
*/
virtual unsigned int autocalIQOffset(int port = -1)
{ return NotSupported; }
// The balance control is a single gain ratio expressed in dB
// The "val" here is a integer balance control
// on a scale that is specific to the hardware.
// There are readback and write methods to support a closed-loop search.
// There is also a method to report the mean control step size.
// This calibration is done on each port.
//
// This can be implemented in software if the hardware does not support it.
/**
* @return Error code (0 on success)
*/
virtual unsigned int getIQBalanceCal(int& val, unsigned port) const
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int setIQBalanceCal(int val, unsigned port)
{ return NotSupported; }
/**
* Automatic IQ balance calibration, if the hardware supports it.
* @param port Port number, or -1 for all ports
* @return Error code (0 on success)
*/
virtual unsigned int autoCalIQBalance(int port = -1)
{ return NotSupported; }
// The phase offset control calibrates relative phase across ports.
// The "val" here is a integer balance control
// on a scale that is specific to the hardware.
// There are readback and write methods to support a closed-loop search.
// There is also a method to report the mean control step size.
// This calibration is done on each port.
//
// This can be implemented in software if the hardware does not support it.
/**
* @return Error code (0 on success)
*/
virtual unsigned int getTxPhaseCal(int& val, unsigned port) const
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int getRxPhaseCal(int& val, unsigned port) const
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int setTxPhaseCal(int val, unsigned port)
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int setRxPhaseCal(int val, unsigned port)
{ return NotSupported; }
/**
* Automatic phase calibration across all ports, if the hardware supports it.
* A set offset will also be added to all ports.
* @return Error code (0 on success)
*/
virtual unsigned int autoCalPhase(float baseRadians = 0.0F)
{ return NotSupported; }
// The I-Q delay control calibrates relative I-Q timing across ports.
// The "val" here is a integer balance control
// on a scale that is specific to the hardware.
// There are readback and write methods to support a closed-loop search.
// There is also a method to report the mean control step size.
// This calibration is done on each port.
//
// This can be implemented in software if the hardware does not support it.
/**
* @return Error code (0 on success)
*/
virtual unsigned int getIQDelayCal(int& val, unsigned port) const
{ return NotSupported; }
/**
* @return Error code (0 on success)
*/
virtual unsigned int setIQDelayCal(int val, unsigned port)
{ return NotSupported; }
/**
* Automatic IQ balance calibration, if the hardware supports it.
* @param port Port number, or -1 for all ports
* @return Error code (0 on success)
*/
virtual unsigned int autoCalIQDelay(int port = -1)
{ return NotSupported; }
/**
* Retrieve the interface name
* @return Interface name

View File

@ -72,10 +72,8 @@ public:
{ time = getTS(); return 0; }
virtual unsigned int getRxTime(uint64_t& time) const
{ time = getTS(); return 0; }
virtual unsigned int getTime(uint64_t& time) const
{ time = getTS(); return 0; }
virtual unsigned int setTxPower(const unsigned dBm);
virtual unsigned int setPorts(unsigned ports) const
virtual unsigned int setPorts(unsigned ports)
{ return NotSupported; }
virtual unsigned status(int port = -1) const
{ return (m_totalErr & FatalErrorMask); }
@ -119,8 +117,6 @@ private:
unsigned int m_freqStep;
unsigned int m_sampleStep;
unsigned int m_filterStep;
unsigned int m_rxLatency;
unsigned int m_txLatency;
uint64_t m_rxSamp;
uint64_t m_txSamp;
DataBlock m_rxDataBuf; // RX data
@ -214,21 +210,19 @@ DummyInterface::DummyInterface(const char* name, const NamedList& config)
m_caps.currPorts = 1;
m_caps.maxTuneFreq = config.getInt64Value("maxTuneFreq",5000000000LL,100000000LL,50000000000LL);
m_caps.minTuneFreq = config.getInt64Value("minTuneFreq",500000000LL,250000000LL,5000000000LL);
m_caps.maxOutputPower = config.getIntValue("maxOutputPower",30,0,50);
m_caps.minOutputPower = config.getIntValue("minOutputPower",0,-10,30);
m_caps.maxInputSaturation = config.getIntValue("maxInputSaturation",-30,-50,0);
m_caps.minInputSaturation = config.getIntValue("minInputSaturation",-50,-80,-30);
m_caps.maxSampleRate = config.getIntValue("maxSampleRate",20000000,5000000,50000000);
m_caps.minSampleRate = config.getIntValue("minSamplerate",250000,50000,5000000);
m_caps.maxFilterBandwidth = config.getIntValue("maxFilterBandwidth",5000000,5000000,50000000);
m_caps.minFilterBandwidth = config.getIntValue("minFilterBandwidth",1500000,100000,5000000);
if (config.getParam("rx_latency") || config.getParam("tx_latency"))
Debug(this,DebugConf,"rx_latency/tx_latency are obsolete, please use rxLatency/txLatency");
m_caps.rxLatency = config.getIntValue("rxLatency",10000,0,50000);
m_caps.txLatency = config.getIntValue("txLatency",10000,0,50000);
m_freqError = config.getIntValue("freq_error",0,-10000,10000);
m_freqStep = config.getIntValue("freq_step",1,1,10000000);
m_sampleError = config.getIntValue("sample_error",0,-1000,1000);
m_sampleStep = config.getIntValue("sample_step",1,1,1000);
m_filterStep = config.getIntValue("filter_step",250000,100000,5000000);
m_rxLatency = config.getIntValue("rx_latency",10000,0,50000);
m_txLatency = config.getIntValue("tx_latency",10000,0,100000);
m_radioCaps = &m_caps;
m_profiling = config.getBoolValue("profiling",false);
m_sampleEnergize = config.getIntValue("sample_energize",0,0,10000);
@ -345,18 +339,18 @@ uint64_t DummyInterface::getRxUsec(uint64_t ts) const
{
if (!(m_startTime && m_sample))
return 0;
if (ts < m_rxLatency)
if (ts < m_caps.rxLatency)
return m_startTime;
return (ts - m_rxLatency) * m_divisor / m_sample + m_startTime;
return (ts - m_caps.rxLatency) * m_divisor / m_sample + m_startTime;
}
uint64_t DummyInterface::getTxUsec(uint64_t ts) const
{
if (!(m_startTime && m_sample))
return 0;
if (ts < m_txLatency)
if (ts < m_caps.txLatency)
return m_startTime;
return (ts - m_txLatency) * m_divisor / m_sample + m_startTime;
return (ts - m_caps.txLatency) * m_divisor / m_sample + m_startTime;
}
unsigned int DummyInterface::send(uint64_t when, float* samples, unsigned size, float* powerScale)
@ -447,7 +441,7 @@ unsigned int DummyInterface::setFilter(uint64_t hz)
unsigned int DummyInterface::setTxPower(const unsigned dBm)
{
Debug(this,DebugCall,"setTxPower(%u) [%p]",dBm,this);
return ((dBm >= m_caps.minOutputPower && dBm <= m_caps.minOutputPower) ? NoError : NotExact) | status();
return status();
}
void DummyInterface::destroyed()

View File

@ -56,7 +56,8 @@ class BrfModule; // The module
#define BRF_USB_CMD_RF_TX 5
#define BRF_USB_CMD_READ_CAL_CACHE 110
#define BRF_SAMPLERATE_MIN 80000u
#define BRF_SAMPLERATE_MIN 80000u
#define BRF_SAMPLERATE_MAX 0xffffffffu
// Frequency bounds
#define BRF_FREQUENCY_MIN 232500000u
@ -355,10 +356,12 @@ static inline void ver2str(String& dest, uint32_t ver)
}
// Code is expecting this array to have 15 elements
#define BRF_FILTER_BW_MIN 1500000u
#define BRF_FILTER_BW_MAX 20000000u
static uint32_t s_bandSet[] = {
1500000u, 1750000u, 2500000u, 2750000u, 3000000u,
3840000u, 5000000u, 5500000u, 6000000u, 7000000u,
8750000u, 10000000u,12000000u,14000000u,20000000u
BRF_FILTER_BW_MIN, 1750000u, 2500000u, 2750000u, 3000000u,
3840000u, 5000000u, 5500000u, 6000000u, 7000000u,
8750000u, 10000000u,12000000u,14000000u,BRF_FILTER_BW_MAX
};
#if 0
@ -437,6 +440,19 @@ static const uint8_t s_rxvga1_get[121] = {
25, 25, 26, 27, 28, 29, 30
};
// Init radio caps with default values
static void initRadioCaps(RadioCapability& caps)
{
caps.maxPorts = 1;
caps.currPorts = 1;
caps.maxTuneFreq = BRF_FREQUENCY_MAX;
caps.minTuneFreq = BRF_FREQUENCY_MIN;
caps.maxSampleRate = BRF_SAMPLERATE_MAX;
caps.minSampleRate = BRF_SAMPLERATE_MIN;
caps.maxFilterBandwidth = BRF_FILTER_BW_MAX;
caps.minFilterBandwidth = BRF_FILTER_BW_MIN;
}
// Utility macros (call methods)
#define BRF_FUNC_CALL_(result,func,cond,instr) { \
result = func; \
@ -949,6 +965,10 @@ public:
{ return m_owner; }
inline libusb_device_handle* handle() const
{ return m_devHandle; }
inline RadioCapability& capabilities()
{ return m_radioCaps; }
inline bool validPort(unsigned int port) const
{ return port < m_radioCaps.currPorts; }
inline int speed() const
{ return m_devSpeed; }
inline int bus() const
@ -1447,7 +1467,7 @@ private:
const char* desc = 0, String* error = 0);
String& dumpCalCache(String& dest);
// Update speed related data
unsigned int updateSpeed(String* error = 0);
unsigned int updateSpeed(const NamedList& params, String* error = 0);
// Compute Rx avg values, autocorrect offsets if configured
void computeRx(uint64_t ts);
// Check io timestamps
@ -1559,6 +1579,7 @@ private:
libusb_device_handle* m_devHandle; // Device handle
libusb_device* m_dev; // Pointer to used device (in m_list)
// Device info
RadioCapability m_radioCaps;
int m_devBus; // Device bus
int m_devAddr; // Device address
int m_devSpeed; // Device speed
@ -1589,6 +1610,9 @@ private:
unsigned int m_rxTsPastIntervalMs; // RX: allowed timestamp in the past interval in 1 read operation
unsigned int m_rxTsPastSamples; // RX: How many samples in the past to allow in 1 read operation
float m_warnClamped; // TX: Warn clamped threshold (percent)
unsigned int m_minBufsSend; // Minimum buffers to send
unsigned int m_silenceTimeMs; // Silence timestamp related debug messages (in millseconds)
uint64_t m_silenceTs; // Silence timestamp related debug messages
// TX power scale
bool m_calibrated;
float m_txPowerBalance;
@ -1701,61 +1725,26 @@ public:
{ return setTxGain(val,port,true); }
virtual unsigned int setTxGain2(int val, unsigned port)
{ return setTxGain(val,port,false); }
// Calibration. Automatic tx/rx gain setting
// Set pre and post mixer value
unsigned int setGain(bool tx, int val, unsigned int port,
int* newValue = 0) const;
virtual unsigned int autocalDCOffsets()
{ return m_dev->calibrate(); }
unsigned int setOffsetCal(bool tx, bool Q, int val, unsigned port) const;
unsigned int getOffsetCal(bool tx, bool Q, int& val, unsigned port) const;
virtual unsigned int getTxIOffsetCal(int& val, unsigned port) const
{ return getOffsetCal(true,false,val,port); }
virtual unsigned int getTxQOffsetCal(int& val, unsigned port) const
{ return getOffsetCal(true,true,val,port); }
virtual unsigned int getRxIOffsetCal(int& val, unsigned port) const
{ return getOffsetCal(false,false,val,port); }
virtual unsigned int getRxQOffsetCal(int& val, unsigned port) const
{ return getOffsetCal(false,true,val,port); }
virtual unsigned int setTxIOffsetCal(int val, unsigned port) const
{ return setOffsetCal(true,false,val,port); }
virtual unsigned int setTxQOffsetCal(int val, unsigned port) const
{ return setOffsetCal(true,true,val,port); }
virtual unsigned int setRxIOffsetCal(int val, unsigned port) const
{ return setOffsetCal(false,false,val,port); }
virtual unsigned int setRxQOffsetCal(int val, unsigned port) const
{ return setOffsetCal(false,true,val,port); }
unsigned int getPhaseCal(bool tx, int& val, unsigned port) const;
unsigned int setPhaseCal(bool tx, int val, unsigned port);
virtual unsigned int getTxPhaseCal(int& val, unsigned port) const
{ return getPhaseCal(true,val,port); }
virtual unsigned int getRxPhaseCal(int& val, unsigned port) const
{ return getPhaseCal(false,val,port); }
virtual unsigned int setTxPhaseCal(unsigned val, unsigned port)
{ return setPhaseCal(true,val,port); }
virtual unsigned int setRxPhaseCal(unsigned val, unsigned port)
{ return setPhaseCal(true,val,port); }
virtual unsigned int getTxTime(uint64_t& time) const
{ return m_dev->getTimestamp(true,time); }
virtual unsigned int getRxTime(uint64_t& time) const
{ return m_dev->getTimestamp(false,time); }
virtual unsigned int getTime(uint64_t& time) const
{ return NotSupported; }
virtual unsigned int setTxPower(const unsigned dBm)
{ return setTxGain2(dBm,0); }
virtual unsigned int getFreqCal(int& val) const {
val = m_txFreqCorr;
return 0;
virtual unsigned int setPorts(unsigned ports) {
if (ports == m_radioCaps->currPorts)
return 0;
return ports ? NotSupported : OutOfRange;
}
virtual unsigned int setFreqCal(int val);
virtual unsigned int getIQDelayCal(int& val, unsigned port = 0) const
{ return NotSupported; }
virtual unsigned int setPorts(unsigned ports) const
{ return NotSupported; }
// Set pre and post mixer value
unsigned int setGain(bool tx, int val, unsigned int port,
int* newValue = 0) const;
virtual unsigned status(int port = -1) const
{ return (m_totalErr & FatalErrorMask); }
virtual unsigned int setLoopback(const char* name = 0)
{ return m_dev ? m_dev->setLoopback(name) : NotInitialized; }
virtual unsigned int calibrate()
{ return m_dev->calibrate(); }
protected:
BrfInterface(const char* name);
@ -2305,6 +2294,9 @@ BrfLibUsbDevice::BrfLibUsbDevice(BrfInterface* owner)
m_rxTsPastIntervalMs(200),
m_rxTsPastSamples(0),
m_warnClamped(0),
m_minBufsSend(1),
m_silenceTimeMs(0),
m_silenceTs(0),
m_calibrated(false),
m_txPowerBalance(1),
m_txPowerBalanceChanged(false),
@ -2341,6 +2333,7 @@ BrfLibUsbDevice::BrfLibUsbDevice(BrfInterface* owner)
m_txIO.vga2 = BRF_TXVGA2_GAIN_MIN - 1;
m_txIO.dcOffsetI = BRF_RX_DC_OFFSET_MAX + 1;
m_txIO.dcOffsetQ = BRF_RX_DC_OFFSET_MAX + 1;
initRadioCaps(m_radioCaps);
}
BrfLibUsbDevice::~BrfLibUsbDevice()
@ -2449,7 +2442,7 @@ void BrfLibUsbDevice::dumpTimestamps(String& buf, const char* sep)
{
BRF_TX_SERIALIZE_NONE;
uint64_t tsTx = 0;
uint64_t ourTx = m_txIO.timestamp;
uint64_t ourTx = m_txIO.lastTs;
unsigned int codeTx = internalGetTimestamp(true,tsTx);
txSerialize.drop();
BRF_RX_SERIALIZE_NONE;
@ -2655,7 +2648,7 @@ bool BrfLibUsbDevice::open(const NamedList& params)
while (true) {
BRF_FUNC_CALL_BREAK(resetUsb(&e));
BRF_FUNC_CALL_BREAK(openDevice(true,&e));
BRF_FUNC_CALL_BREAK(updateSpeed(&e));
BRF_FUNC_CALL_BREAK(updateSpeed(params,&e));
m_calCache.clear();
readCalCache();
status = updateFpga(params);
@ -2720,6 +2713,7 @@ bool BrfLibUsbDevice::open(const NamedList& params)
params.getBoolValue("txbufoutput_nodata"));
showBuf(false,params.getIntValue("rxbufoutput",0),
params.getBoolValue("rxbufoutput_nodata"));
m_silenceTimeMs = clampIntParam(params,"silence_time",5000,0,60000);
break;
}
if (status) {
@ -3535,13 +3529,7 @@ unsigned int BrfLibUsbDevice::send(uint64_t ts, float* data, unsigned int sample
io.advanceBuffer();
}
unsigned int nBuf = io.crtBuf;
unsigned int oldBufSampOffs = 0;
if (nBuf && io.crtBufSampOffs) {
if (io.crtBufSampOffs == 0)
nBuf++;
else
oldBufSampOffs = io.crtBufSampOffs;
}
unsigned int oldBufSampOffs = nBuf ? io.crtBufSampOffs : 0;
if (m_txIO.syncFlags || m_rxIO.syncFlags) {
if ((m_txIO.syncFlags & ~DevStatTs) != 0)
setStatus(m_txIO.syncStatus,m_txIO.syncFlags);
@ -3552,10 +3540,12 @@ unsigned int BrfLibUsbDevice::send(uint64_t ts, float* data, unsigned int sample
m_txIO.syncFlags = 0;
m_rxIO.syncFlags = 0;
}
if (!nBuf)
if (nBuf < m_minBufsSend)
break;
if (checkDbgInt(io.checkTs))
ioBufCheckTs(true,nBuf);
else
io.lastTs = io.timestamp;
unsigned int nPrint = checkDbgInt(io.showBuf,nBuf);
if (nPrint)
printIOBuffer(true,"SEND",-1,nPrint);
@ -3567,7 +3557,7 @@ unsigned int BrfLibUsbDevice::send(uint64_t ts, float* data, unsigned int sample
// Copy partial buffer from end
if (oldBufSampOffs) {
#ifdef DEBUG_DEVICE_TX
Debug(DebugAll,"TX: copying buffer %u to start [%p]",nBuf,m_owner);
Debug(m_owner,DebugMild,"TX: copying buffer %u to start [%p]",nBuf,m_owner);
#endif
::memcpy(io.bufStart(0),io.bufStart(nBuf),io.hdrLen + samplesi2bytes(oldBufSampOffs));
io.crtBufSampOffs = oldBufSampOffs;
@ -3678,14 +3668,14 @@ unsigned int BrfLibUsbDevice::recv(uint64_t& ts, float* data, unsigned int& samp
#endif
if (resync) {
if ((resync > -1000 && resync < 1000) || bufTs == m_rxResyncCandidate) {
Debug(m_owner,DebugNote,
Debug(m_owner,bufTs > m_silenceTs ? DebugNote : DebugAll,
"RX: timestamp adjusted by " FMT64 " to " FMT64U " [%p]",
resync,bufTs,m_owner);
m_rxTimestamp = bufTs;
m_rxResyncCandidate = 0;
}
else {
Debug(m_owner,DebugWarn,
Debug(m_owner,bufTs > m_silenceTs ? DebugWarn : DebugAll,
"RX: timestamp jumped by " FMT64 " to " FMT64U " in buffer %u/%u [%p]",
resync,m_rxTimestamp,io.crtBuf + 1,io.buffers,m_owner);
m_rxResyncCandidate = bufTs;
@ -3882,9 +3872,13 @@ unsigned int BrfLibUsbDevice::internalSetSampleRate(bool tx, uint32_t value,
Debug(m_owner,DebugInfo,"%s samplerate set to %u [%p]",
brfDir(tx),value,m_owner);
}
// Calculate RX samples allowed to be in the past
if (!tx)
m_rxTsPastSamples = m_rxTsPastIntervalMs * ((value + 999) / 1000);
if (!tx) {
unsigned int samplesMs = (value + 999) / 1000;
// Calculate RX samples allowed to be in the past
m_rxTsPastSamples = m_rxTsPastIntervalMs * samplesMs;
// Calculate RX timestamp silence
m_silenceTs = m_silenceTimeMs * samplesMs;
}
return 0;
}
e.printf(1024,"Failed to set %s samplerate %u: %s",brfDir(tx),value,e.c_str());
@ -5575,7 +5569,7 @@ String& BrfLibUsbDevice::dumpCalCache(String& dest)
}
// Update speed related data
unsigned int BrfLibUsbDevice::updateSpeed(String* error)
unsigned int BrfLibUsbDevice::updateSpeed(const NamedList& params, String* error)
{
if (speed() == LIBUSB_SPEED_SUPER || speed() == LIBUSB_SPEED_HIGH) {
unsigned int brfBufSamples = 508;
@ -5585,13 +5579,25 @@ unsigned int BrfLibUsbDevice::updateSpeed(String* error)
nBuffers = 8;
}
m_txIO.resetSamplesBuffer(brfBufSamples,16,nBuffers);
if (m_minBufsSend > nBuffers)
m_minBufsSend = nBuffers;
m_rxIO.resetSamplesBuffer(brfBufSamples,16,nBuffers);
if (speed() == LIBUSB_SPEED_SUPER)
m_minBufsSend = clampIntParam(params,"tx_min_buffers",nBuffers,1,nBuffers);
if (speed() == LIBUSB_SPEED_SUPER) {
m_radioCaps.rxLatency = clampIntParam(params,"rx_latency_super",4000,0,150000);
m_radioCaps.txLatency = clampIntParam(params,"tx_latency_super",10000,0,150000);
m_ctrlTransferPage = BRF_FLASH_PAGE_SIZE;
else
}
else {
m_radioCaps.rxLatency = clampIntParam(params,"rx_latency_high",7000,0,150000);
m_radioCaps.txLatency = clampIntParam(params,"tx_latency_high",20000,0,150000);
m_ctrlTransferPage = 64;
}
return 0;
}
m_minBufsSend = 1;
m_radioCaps.rxLatency = 0;
m_radioCaps.txLatency = 0;
m_ctrlTransferPage = 0;
String e;
e << "Unsupported USB speed " << m_devSpeed;
@ -7119,6 +7125,7 @@ BrfInterface::~BrfInterface()
BrfLibUsbDevice* BrfInterface::init()
{
m_dev = BrfLibUsbDevice::create(this);
m_radioCaps = &m_dev->capabilities();
Debug(this,DebugAll,"Created device (%p) [%p]",m_dev,this);
return m_dev;
}
@ -7167,8 +7174,8 @@ unsigned int BrfInterface::setParams(NamedList& params, bool shareFate)
METH_CALL_1(setSampleRate,(uint64_t)ns->toInt64());
if (cmd == YSTRING("setFilter"))
METH_CALL_1(setFilter,(uint64_t)ns->toInt64());
if (cmd == "autocalDCOffsets")
METH_CALL(autocalDCOffsets);
if (cmd == "calibrate")
METH_CALL(calibrate);
Debug(this,DebugNote,"setParams: unhandled cmd '%s' [%p]",cmd.c_str(),this);
SETPARAMS_HANDLE_CODE(NotSupported);
}
@ -7319,6 +7326,8 @@ unsigned int BrfInterface::setRxGain(int val, unsigned port, bool preMixer)
{
XDebug(this,DebugAll,"BrfInterface::setRxGain(%d,%u,VGA%c) [%p]",
val,port,mixer(preMixer),this);
if (!m_dev->validPort(port))
return OutOfRange;
unsigned int status = m_dev->enableRxVga(true,preMixer);
if (status)
return status;
@ -7340,6 +7349,8 @@ unsigned int BrfInterface::setTxGain(int val, unsigned port, bool preMixer)
{
XDebug(this,DebugAll,"BrfInterface::setTxGain(%d,%u,VGA%c) [%p]",
val,port,mixer(preMixer),this);
if (!m_dev->validPort(port))
return OutOfRange;
unsigned int status = m_dev->setTxVga(val,preMixer);
if (status)
return status;
@ -7359,52 +7370,11 @@ unsigned int BrfInterface::setTxGain(int val, unsigned port, bool preMixer)
unsigned int BrfInterface::setGain(bool tx, int val, unsigned int port,
int* newVal) const
{
if (!m_dev->validPort(port))
return OutOfRange;
return m_dev->setGain(tx,val,newVal);
}
unsigned int BrfInterface::setOffsetCal(bool tx, bool Q, int val, unsigned port) const
{
return m_dev->setDcOffset(tx,!Q,val);
}
unsigned int BrfInterface::getOffsetCal(bool tx, bool Q, int& val, unsigned port) const
{
int16_t tmp = 0;
unsigned int status = m_dev->getDcOffset(tx,!Q,tmp);
if (status == 0)
val = tmp;
return status;
}
unsigned int BrfInterface::getPhaseCal(bool tx, int& val, unsigned port) const
{
int16_t tmp = 0;
unsigned int status = m_dev->getFpgaCorr(tx,BrfLibUsbDevice::CorrFpgaPhase,tmp);
if (status == 0)
val = tmp;
return status;
}
unsigned int BrfInterface::setPhaseCal(bool tx, int val, unsigned port)
{
return m_dev->setFpgaCorr(tx,BrfLibUsbDevice::CorrFpgaPhase,val);
}
unsigned int BrfInterface::setFreqCal(int val)
{
uint64_t freq = 0;
unsigned int status = getTxFreq(freq);
if (status != NoError)
return status;
freq += val;
status = setTxFreq(freq);
if (status == NoError)
m_txFreqCorr = freq;
else
Debug(this,DebugNote,"Failed to set calibrated frequency %d [%p]",val,this);
return status;
}
void BrfInterface::destroyed()
{
Debug(this,DebugAll,"Destroying device=(%p) [%p]",m_dev,this);

View File

@ -537,7 +537,7 @@ bool RadioTest::execute(const String& cmd, const String& param, bool fatal,
else if (cmd == YSTRING("loopback"))
c = m_radio->setLoopback(param);
else if (cmd == YSTRING("calibrate"))
c = m_radio->autocalDCOffsets();
c = m_radio->calibrate();
else {
Debug(this,DebugNote,"Unhandled command '%s' [%p]",cmd.c_str(),this);
return true;