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