1 #include <iio.h> 2 #include <vector> 3 #include <mutex> 4 #include <thread> 5 #include <chrono> 6 #include <atomic> 7 #include <SoapySDR/Device.hpp> 8 #include <SoapySDR/Logger.hpp> 9 #include <SoapySDR/Formats.hpp> 10 11 typedef enum plutosdrStreamFormat { 12 PLUTO_SDR_CF32, 13 PLUTO_SDR_CS16, 14 PLUTO_SDR_CS12, 15 PLUTO_SDR_CS8 16 } plutosdrStreamFormat; 17 18 class rx_streamer { 19 public: 20 rx_streamer(const iio_device *dev, const plutosdrStreamFormat format, const std::vector<size_t> &channels, const SoapySDR::Kwargs &args); 21 ~rx_streamer(); 22 size_t recv(void * const *buffs, 23 const size_t numElems, 24 int &flags, 25 long long &timeNs, 26 const long timeoutUs=100000); 27 int start(const int flags, 28 const long long timeNs, 29 const size_t numElems); 30 31 int stop(const int flags, 32 const long long timeNs=100000); 33 34 void set_buffer_size_by_samplerate(const size_t _samplerate); 35 36 size_t get_mtu_size(); 37 38 private: 39 40 void set_buffer_size(const size_t _buffer_size); 41 void set_mtu_size(const size_t mtu_size); 42 43 bool has_direct_copy(); 44 45 std::vector<iio_channel* > channel_list; 46 const iio_device *dev; 47 48 size_t buffer_size; 49 size_t byte_offset; 50 size_t items_in_buffer; 51 iio_buffer *buf; 52 const plutosdrStreamFormat format; 53 bool direct_copy; 54 size_t mtu_size; 55 56 }; 57 58 class tx_streamer { 59 60 public: 61 tx_streamer(const iio_device *dev, const plutosdrStreamFormat format, const std::vector<size_t> &channels, const SoapySDR::Kwargs &args); 62 ~tx_streamer(); 63 int send(const void * const *buffs,const size_t numElems,int &flags,const long long timeNs,const long timeoutUs ); 64 int flush(); 65 66 private: 67 int send_buf(); 68 bool has_direct_copy(); 69 70 std::vector<iio_channel* > channel_list; 71 const iio_device *dev; 72 const plutosdrStreamFormat format; 73 74 iio_buffer *buf; 75 size_t buf_size; 76 size_t items_in_buf; 77 bool direct_copy; 78 79 }; 80 81 // A local spin_mutex usable with std::lock_guard 82 //for lightweight locking for short periods. 83 class pluto_spin_mutex { 84 85 public: 86 pluto_spin_mutex() = default; 87 88 pluto_spin_mutex(const pluto_spin_mutex&) = delete; 89 90 pluto_spin_mutex& operator=(const pluto_spin_mutex&) = delete; 91 ~pluto_spin_mutex()92 ~pluto_spin_mutex() { lock_state.clear(std::memory_order_release); } 93 lock()94 void lock() { while (lock_state.test_and_set(std::memory_order_acquire)); } 95 unlock()96 void unlock() { lock_state.clear(std::memory_order_release); } 97 98 private: 99 std::atomic_flag lock_state = ATOMIC_FLAG_INIT; 100 }; 101 102 103 class SoapyPlutoSDR : public SoapySDR::Device{ 104 105 public: 106 SoapyPlutoSDR( const SoapySDR::Kwargs & args ); 107 ~SoapyPlutoSDR(); 108 109 /******************************************************************* 110 * Identification API 111 ******************************************************************/ 112 113 std::string getDriverKey( void ) const; 114 115 116 std::string getHardwareKey( void ) const; 117 118 119 SoapySDR::Kwargs getHardwareInfo( void ) const; 120 121 122 /******************************************************************* 123 * Channels API 124 ******************************************************************/ 125 126 size_t getNumChannels( const int ) const; 127 128 129 bool getFullDuplex( const int direction, const size_t channel ) const; 130 131 /******************************************************************* 132 * Stream API 133 ******************************************************************/ 134 135 std::vector<std::string> getStreamFormats(const int direction, const size_t channel) const; 136 137 std::string getNativeStreamFormat(const int direction, const size_t channel, double &fullScale) const; 138 139 SoapySDR::ArgInfoList getStreamArgsInfo(const int direction, const size_t channel) const; 140 141 SoapySDR::Stream *setupStream( 142 const int direction, 143 const std::string &format, 144 const std::vector<size_t> &channels = std::vector<size_t>(), 145 const SoapySDR::Kwargs &args = SoapySDR::Kwargs() ); 146 147 void closeStream( SoapySDR::Stream *stream ); 148 149 size_t getStreamMTU( SoapySDR::Stream *stream ) const; 150 151 int activateStream( 152 SoapySDR::Stream *stream, 153 const int flags = 0, 154 const long long timeNs = 0, 155 const size_t numElems = 0 ); 156 157 int deactivateStream( 158 SoapySDR::Stream *stream, 159 const int flags = 0, 160 const long long timeNs = 0 ); 161 162 int readStream( 163 SoapySDR::Stream *stream, 164 void * const *buffs, 165 const size_t numElems, 166 int &flags, 167 long long &timeNs, 168 const long timeoutUs = 100000 ); 169 170 int writeStream( 171 SoapySDR::Stream *stream, 172 const void * const *buffs, 173 const size_t numElems, 174 int &flags, 175 const long long timeNs = 0, 176 const long timeoutUs = 100000); 177 178 int readStreamStatus( 179 SoapySDR::Stream *stream, 180 size_t &chanMask, 181 int &flags, 182 long long &timeNs, 183 const long timeoutUs 184 ); 185 186 187 /******************************************************************* 188 * Sensor API 189 ******************************************************************/ 190 191 std::vector<std::string> listSensors(void) const; 192 193 SoapySDR::ArgInfo getSensorInfo(const std::string &key) const; 194 195 std::string readSensor(const std::string &key) const; 196 197 198 /******************************************************************* 199 * Settings API 200 ******************************************************************/ 201 202 SoapySDR::ArgInfoList getSettingInfo(void) const; 203 204 205 void writeSetting(const std::string &key, const std::string &value); 206 207 208 std::string readSetting(const std::string &key) const; 209 210 211 /******************************************************************* 212 * Antenna API 213 ******************************************************************/ 214 215 std::vector<std::string> listAntennas( const int direction, const size_t channel ) const; 216 217 218 void setAntenna( const int direction, const size_t channel, const std::string &name ); 219 220 221 std::string getAntenna( const int direction, const size_t channel ) const; 222 223 224 /******************************************************************* 225 * Frontend corrections API 226 ******************************************************************/ 227 228 bool hasDCOffsetMode( const int direction, const size_t channel ) const; 229 230 231 /******************************************************************* 232 * Gain API 233 ******************************************************************/ 234 235 std::vector<std::string> listGains( const int direction, const size_t channel ) const; 236 237 238 bool hasGainMode(const int direction, const size_t channel) const; 239 240 241 void setGainMode( const int direction, const size_t channel, const bool automatic ); 242 243 244 bool getGainMode( const int direction, const size_t channel ) const; 245 246 247 void setGain( const int direction, const size_t channel, const double value ); 248 249 250 void setGain( const int direction, const size_t channel, const std::string &name, const double value ); 251 252 253 double getGain( const int direction, const size_t channel, const std::string &name ) const; 254 255 256 SoapySDR::Range getGainRange( const int direction, const size_t channel, const std::string &name ) const; 257 258 259 /******************************************************************* 260 * Frequency API 261 ******************************************************************/ 262 263 void setFrequency( const int direction, const size_t channel, const std::string &name, const double frequency, const SoapySDR::Kwargs &args = SoapySDR::Kwargs() ); 264 265 266 double getFrequency( const int direction, const size_t channel, const std::string &name ) const; 267 268 269 SoapySDR::ArgInfoList getFrequencyArgsInfo(const int direction, const size_t channel) const; 270 271 272 std::vector<std::string> listFrequencies( const int direction, const size_t channel ) const; 273 274 275 SoapySDR::RangeList getFrequencyRange( const int direction, const size_t channel, const std::string &name ) const; 276 277 278 /******************************************************************* 279 * Sample Rate API 280 ******************************************************************/ 281 282 void setSampleRate( const int direction, const size_t channel, const double rate ); 283 284 285 double getSampleRate( const int direction, const size_t channel ) const; 286 287 288 std::vector<double> listSampleRates( const int direction, const size_t channel ) const; 289 290 291 void setBandwidth( const int direction, const size_t channel, const double bw ); 292 293 294 double getBandwidth( const int direction, const size_t channel ) const; 295 296 297 std::vector<double> listBandwidths( const int direction, const size_t channel ) const; 298 299 300 301 private: 302 303 bool IsValidRxStreamHandle(SoapySDR::Stream* handle) const; 304 bool IsValidTxStreamHandle(SoapySDR::Stream* handle) const; 305 306 bool is_sensor_channel(struct iio_channel *chn) const; 307 double double_from_buf(const char *buf) const; 308 double get_sensor_value(struct iio_channel *chn) const; 309 std::string id_to_unit(const std::string &id) const; 310 311 iio_device *dev; 312 iio_device *rx_dev; 313 iio_device *tx_dev; 314 bool gainMode; 315 316 mutable pluto_spin_mutex rx_device_mutex; 317 mutable pluto_spin_mutex tx_device_mutex; 318 319 bool decimation, interpolation; 320 std::unique_ptr<rx_streamer> rx_stream; 321 std::unique_ptr<tx_streamer> tx_stream; 322 323 324 }; 325 326