2018-03-07 06:50:57 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2018 sysmocom - s.f.m.c. GmbH
|
|
|
|
*
|
2019-07-22 10:05:52 +00:00
|
|
|
* SPDX-License-Identifier: AGPL-3.0+
|
|
|
|
*
|
|
|
|
* This software is distributed under multiple licenses; see the COPYING file in
|
2019-10-13 17:08:00 +00:00
|
|
|
* the main directory for licensing information for this specific distribution.
|
2018-03-07 06:50:57 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _LMS_DEVICE_H_
|
|
|
|
#define _LMS_DEVICE_H_
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "radioDevice.h"
|
2019-05-03 14:15:06 +00:00
|
|
|
#include "smpl_buf.h"
|
2018-03-07 06:50:57 +00:00
|
|
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <math.h>
|
2018-04-25 10:17:10 +00:00
|
|
|
#include <limits.h>
|
2018-03-07 06:50:57 +00:00
|
|
|
#include <string>
|
|
|
|
#include <iostream>
|
2018-04-25 10:17:10 +00:00
|
|
|
#include <lime/LimeSuite.h>
|
|
|
|
|
2018-11-26 18:17:00 +00:00
|
|
|
/* Definition of LIMESDR_TX_AMPL limits maximum amplitude of I and Q
|
|
|
|
* channels separately. Hence LIMESDR_TX_AMPL value must be 1/sqrt(2) =
|
|
|
|
* 0.7071.... to get an amplitude of 1 of the complex signal:
|
|
|
|
* A^2 = I^2 + Q^2
|
|
|
|
* A^2 = (1/sqrt(2))^2 + (1/sqrt(2))^2
|
|
|
|
* A^2 = 1/2 + 1/2
|
|
|
|
* A^2 = 1 */
|
|
|
|
#define LIMESDR_TX_AMPL 0.707
|
2018-03-07 06:50:57 +00:00
|
|
|
|
|
|
|
/** A class to handle a LimeSuite supported device */
|
|
|
|
class LMSDevice:public RadioDevice {
|
|
|
|
|
|
|
|
private:
|
|
|
|
lms_device_t *m_lms_dev;
|
2018-04-25 10:17:10 +00:00
|
|
|
std::vector<lms_stream_t> m_lms_stream_rx;
|
|
|
|
std::vector<lms_stream_t> m_lms_stream_tx;
|
|
|
|
|
2019-05-03 14:15:06 +00:00
|
|
|
std::vector<smpl_buf *> rx_buffers;
|
|
|
|
|
2018-04-25 10:17:10 +00:00
|
|
|
double actualSampleRate; ///< the actual USRP sampling rate
|
2018-03-07 06:50:57 +00:00
|
|
|
|
|
|
|
bool started; ///< flag indicates LMS has started
|
|
|
|
bool skipRx; ///< set if LMS is transmit-only.
|
|
|
|
|
2018-04-25 10:17:10 +00:00
|
|
|
TIMESTAMP ts_initial, ts_offset;
|
|
|
|
|
2019-09-13 14:51:48 +00:00
|
|
|
std::vector<double> tx_gains, rx_gains;
|
2019-04-16 15:10:13 +00:00
|
|
|
double maxTxGainClamp;
|
2018-04-25 10:17:10 +00:00
|
|
|
|
2019-04-16 14:35:53 +00:00
|
|
|
bool do_calib(size_t chan);
|
|
|
|
bool do_filters(size_t chan);
|
2019-08-26 15:10:27 +00:00
|
|
|
void log_ant_list(bool dir_tx, size_t chan, std::ostringstream& os);
|
2018-04-25 10:17:10 +00:00
|
|
|
int get_ant_idx(const std::string & name, bool dir_tx, size_t chan);
|
|
|
|
bool flush_recv(size_t num_pkts);
|
2019-07-29 18:11:25 +00:00
|
|
|
void update_stream_stats_rx(size_t chan, bool *overrun);
|
|
|
|
void update_stream_stats_tx(size_t chan, bool *underrun);
|
2018-03-07 06:50:57 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
/** Object constructor */
|
2020-01-13 15:00:04 +00:00
|
|
|
LMSDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chan_num, double lo_offset,
|
2018-06-13 19:55:09 +00:00
|
|
|
const std::vector<std::string>& tx_paths,
|
|
|
|
const std::vector<std::string>& rx_paths);
|
2018-12-03 17:17:18 +00:00
|
|
|
~LMSDevice();
|
2018-03-07 06:50:57 +00:00
|
|
|
|
|
|
|
/** Instantiate the LMS */
|
2018-04-25 10:17:10 +00:00
|
|
|
int open(const std::string &args, int ref, bool swap_channels);
|
2018-03-07 06:50:57 +00:00
|
|
|
|
|
|
|
/** Start the LMS */
|
|
|
|
bool start();
|
|
|
|
|
|
|
|
/** Stop the LMS */
|
|
|
|
bool stop();
|
|
|
|
|
2018-04-25 10:17:10 +00:00
|
|
|
enum TxWindowType getWindowType() {
|
2018-03-07 06:50:57 +00:00
|
|
|
return TX_WINDOW_LMS1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Read samples from the LMS.
|
|
|
|
@param buf preallocated buf to contain read result
|
|
|
|
@param len number of samples desired
|
|
|
|
@param overrun Set if read buffer has been overrun, e.g. data not being read fast enough
|
|
|
|
@param timestamp The timestamp of the first samples to be read
|
|
|
|
@param underrun Set if LMS does not have data to transmit, e.g. data not being sent fast enough
|
|
|
|
@param RSSI The received signal strength of the read result
|
|
|
|
@return The number of samples actually read
|
|
|
|
*/
|
|
|
|
int readSamples(std::vector < short *>&buf, int len, bool * overrun,
|
|
|
|
TIMESTAMP timestamp = 0xffffffff, bool * underrun =
|
|
|
|
NULL, unsigned *RSSI = NULL);
|
|
|
|
/**
|
|
|
|
Write samples to the LMS.
|
|
|
|
@param buf Contains the data to be written.
|
|
|
|
@param len number of samples to write.
|
|
|
|
@param underrun Set if LMS does not have data to transmit, e.g. data not being sent fast enough
|
|
|
|
@param timestamp The timestamp of the first sample of the data buffer.
|
|
|
|
@param isControl Set if data is a control packet, e.g. a ping command
|
|
|
|
@return The number of samples actually written
|
|
|
|
*/
|
|
|
|
int writeSamples(std::vector < short *>&bufs, int len, bool * underrun,
|
|
|
|
TIMESTAMP timestamp = 0xffffffff, bool isControl =
|
|
|
|
false);
|
|
|
|
|
|
|
|
/** Update the alignment between the read and write timestamps */
|
|
|
|
bool updateAlignment(TIMESTAMP timestamp);
|
|
|
|
|
|
|
|
/** Set the transmitter frequency */
|
|
|
|
bool setTxFreq(double wFreq, size_t chan = 0);
|
|
|
|
|
|
|
|
/** Set the receiver frequency */
|
|
|
|
bool setRxFreq(double wFreq, size_t chan = 0);
|
|
|
|
|
|
|
|
/** Returns the starting write Timestamp*/
|
|
|
|
TIMESTAMP initialWriteTimestamp(void) {
|
2018-04-25 10:17:10 +00:00
|
|
|
return ts_initial;
|
2018-03-07 06:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns the starting read Timestamp*/
|
|
|
|
TIMESTAMP initialReadTimestamp(void) {
|
2018-04-25 10:17:10 +00:00
|
|
|
return ts_initial;
|
2018-03-07 06:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** returns the full-scale transmit amplitude **/
|
|
|
|
double fullScaleInputValue() {
|
2018-04-25 10:17:10 +00:00
|
|
|
return(double) SHRT_MAX * LIMESDR_TX_AMPL;
|
2018-03-07 06:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** returns the full-scale receive amplitude **/
|
|
|
|
double fullScaleOutputValue() {
|
2018-04-25 10:17:10 +00:00
|
|
|
return (double) SHRT_MAX;
|
2018-03-07 06:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** sets the receive chan gain, returns the gain setting **/
|
|
|
|
double setRxGain(double dB, size_t chan = 0);
|
|
|
|
|
|
|
|
/** get the current receive gain */
|
|
|
|
double getRxGain(size_t chan = 0) {
|
2019-09-13 14:51:48 +00:00
|
|
|
return rx_gains[chan];
|
2018-03-07 06:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** return maximum Rx Gain **/
|
|
|
|
double maxRxGain(void);
|
|
|
|
|
|
|
|
/** return minimum Rx Gain **/
|
|
|
|
double minRxGain(void);
|
|
|
|
|
|
|
|
/** sets the transmit chan gain, returns the gain setting **/
|
|
|
|
double setTxGain(double dB, size_t chan = 0);
|
2019-09-13 15:05:02 +00:00
|
|
|
|
|
|
|
/** get transmit gain */
|
|
|
|
double getTxGain(size_t chan = 0) {
|
|
|
|
return tx_gains[chan];
|
|
|
|
}
|
2018-03-07 06:50:57 +00:00
|
|
|
|
|
|
|
/** return maximum Tx Gain **/
|
|
|
|
double maxTxGain(void);
|
|
|
|
|
|
|
|
/** return minimum Rx Gain **/
|
|
|
|
double minTxGain(void);
|
|
|
|
|
|
|
|
/** sets the RX path to use, returns true if successful and false otherwise */
|
|
|
|
bool setRxAntenna(const std::string & ant, size_t chan = 0);
|
|
|
|
|
|
|
|
/* return the used RX path */
|
|
|
|
std::string getRxAntenna(size_t chan = 0);
|
|
|
|
|
|
|
|
/** sets the RX path to use, returns true if successful and false otherwise */
|
|
|
|
bool setTxAntenna(const std::string & ant, size_t chan = 0);
|
|
|
|
|
|
|
|
/* return the used RX path */
|
|
|
|
std::string getTxAntenna(size_t chan = 0);
|
|
|
|
|
2018-04-25 10:17:10 +00:00
|
|
|
/** return whether user drives synchronization of Tx/Rx of USRP */
|
|
|
|
bool requiresRadioAlign();
|
|
|
|
|
|
|
|
/** return whether user drives synchronization of Tx/Rx of USRP */
|
|
|
|
virtual GSM::Time minLatency();
|
|
|
|
|
2018-03-07 06:50:57 +00:00
|
|
|
/** Return internal status values */
|
|
|
|
inline double getTxFreq(size_t chan = 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
inline double getRxFreq(size_t chan = 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
inline double getSampleRate() {
|
|
|
|
return actualSampleRate;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // _LMS_DEVICE_H_
|