From fb066c3e51818274f111dead1228d8dbf8819444 Mon Sep 17 00:00:00 2001 From: marian Date: Mon, 12 Oct 2015 15:06:31 +0000 Subject: [PATCH] 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 --- conf.d/dummyradio.conf.sample | 32 +-- conf.d/ybladerf.conf.sample | 10 + libs/yradio/yateradio.h | 381 +++------------------------------- modules/radio/dummyradio.cpp | 26 +-- modules/radio/ybladerf.cpp | 196 ++++++++--------- modules/test/radiotest.cpp | 2 +- 6 files changed, 138 insertions(+), 509 deletions(-) diff --git a/conf.d/dummyradio.conf.sample b/conf.d/dummyradio.conf.sample index 4d9250b2..1b76a4f0 100644 --- a/conf.d/dummyradio.conf.sample +++ b/conf.d/dummyradio.conf.sample @@ -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 diff --git a/conf.d/ybladerf.conf.sample b/conf.d/ybladerf.conf.sample index 54bd00b2..ef3f4ff0 100644 --- a/conf.d/ybladerf.conf.sample +++ b/conf.d/ybladerf.conf.sample @@ -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 diff --git a/libs/yradio/yateradio.h b/libs/yradio/yateradio.h index 40bcc967..d446302e 100644 --- a/libs/yradio/yateradio.h +++ b/libs/yradio/yateradio.h @@ -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 diff --git a/modules/radio/dummyradio.cpp b/modules/radio/dummyradio.cpp index 2b86bb78..77f235fb 100644 --- a/modules/radio/dummyradio.cpp +++ b/modules/radio/dummyradio.cpp @@ -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() diff --git a/modules/radio/ybladerf.cpp b/modules/radio/ybladerf.cpp index 44b646e5..88a7ff8e 100644 --- a/modules/radio/ybladerf.cpp +++ b/modules/radio/ybladerf.cpp @@ -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); diff --git a/modules/test/radiotest.cpp b/modules/test/radiotest.cpp index b39d8663..807eed5c 100644 --- a/modules/test/radiotest.cpp +++ b/modules/test/radiotest.cpp @@ -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;