SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
dspdevicemimoengine.h
Go to the documentation of this file.
1 // Copyright (C) 2019 F4EXB //
3 // written by Edouard Griffiths //
4 // //
5 // This program is free software; you can redistribute it and/or modify //
6 // it under the terms of the GNU General Public License as published by //
7 // the Free Software Foundation as version 3 of the License, or //
8 // (at your option) any later version. //
9 // //
10 // This program is distributed in the hope that it will be useful, //
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
13 // GNU General Public License V3 for more details. //
14 // //
15 // You should have received a copy of the GNU General Public License //
16 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
18 
19 #ifndef SDRBASE_DSP_DSPDEVICEMIMOENGINE_H_
20 #define SDRBASE_DSP_DSPDEVICEMIMOENGINE_H_
21 
22 #include <QThread>
23 
24 #include "dsp/dsptypes.h"
25 #include "util/message.h"
26 #include "util/messagequeue.h"
27 #include "util/syncmessenger.h"
28 #include "util/movingaverage.h"
29 #include "export.h"
30 
31 class DeviceSampleMIMO;
34 class BasebandSampleSink;
35 
36 class SDRBASE_API DSPDeviceMIMOEngine : public QThread {
37  Q_OBJECT
38 
39 public:
40  class SetSampleMIMO : public Message {
42  public:
43  SetSampleMIMO(DeviceSampleMIMO* sampleMIMO) : Message(), m_sampleMIMO(sampleMIMO) { }
44  DeviceSampleMIMO* getSampleMIMO() const { return m_sampleMIMO; }
45  private:
47  };
48 
51  public:
52  AddThreadedBasebandSampleSource(ThreadedBasebandSampleSource* threadedSampleSource, unsigned int index) :
53  Message(),
54  m_threadedSampleSource(threadedSampleSource),
55  m_index(index)
56  { }
57  ThreadedBasebandSampleSource* getThreadedSampleSource() const { return m_threadedSampleSource; }
58  unsigned int getIndex() const { return m_index; }
59  private:
61  unsigned int m_index;
62  };
63 
64  class AddSourceStream : public Message {
66  public:
67  AddSourceStream(bool connect) : Message(), m_connect(connect) { }
68  bool getConnect() const { return m_connect; }
69  private:
70  bool m_connect;
71  };
72 
75  };
76 
77  class AddSinkStream : public Message {
79  public:
80  AddSinkStream(bool connect) : Message(), m_connect(connect) { }
81  bool getConnect() const { return m_connect; }
82  private:
83  bool m_connect;
84  };
85 
86  class RemoveLastSinkStream : public Message {
88  };
89 
92 
93  public:
94  RemoveThreadedBasebandSampleSource(ThreadedBasebandSampleSource* threadedSampleSource, unsigned int index) :
95  Message(),
96  m_threadedSampleSource(threadedSampleSource),
97  m_index(index)
98  { }
99  ThreadedBasebandSampleSource* getThreadedSampleSource() const { return m_threadedSampleSource; }
100  unsigned int getIndex() const { return m_index; }
101  private:
103  unsigned int m_index;
104  };
105 
108  public:
109  AddThreadedBasebandSampleSink(ThreadedBasebandSampleSink* threadedSampleSink, unsigned int index) :
110  Message(),
111  m_threadedSampleSink(threadedSampleSink),
112  m_index(index)
113  { }
114  ThreadedBasebandSampleSink* getThreadedSampleSink() const { return m_threadedSampleSink; }
115  unsigned int getIndex() const { return m_index; }
116  private:
118  unsigned int m_index;
119  };
120 
123  public:
124  RemoveThreadedBasebandSampleSink(ThreadedBasebandSampleSink* threadedSampleSink, unsigned int index) :
125  Message(),
126  m_threadedSampleSink(threadedSampleSink),
127  m_index(index)
128  { }
129  ThreadedBasebandSampleSink* getThreadedSampleSink() const { return m_threadedSampleSink; }
130  unsigned int getIndex() const { return m_index; }
131  private:
133  unsigned int m_index;
134  };
135 
138  public:
139  AddBasebandSampleSink(BasebandSampleSink* sampleSink, unsigned int index) :
140  Message(),
141  m_sampleSink(sampleSink),
142  m_index(index)
143  { }
144  BasebandSampleSink* getSampleSink() const { return m_sampleSink; }
145  unsigned int getIndex() const { return m_index; }
146  private:
148  unsigned int m_index;
149  };
150 
153  public:
154  RemoveBasebandSampleSink(BasebandSampleSink* sampleSink, unsigned int index) :
155  Message(),
156  m_sampleSink(sampleSink),
157  m_index(index)
158  { }
159  BasebandSampleSink* getSampleSink() const { return m_sampleSink; }
160  unsigned int getIndex() const { return m_index; }
161  private:
163  unsigned int m_index;
164  };
165 
166  class AddSpectrumSink : public Message {
168  public:
169  AddSpectrumSink(BasebandSampleSink* sampleSink) : Message(), m_sampleSink(sampleSink) { }
170  BasebandSampleSink* getSampleSink() const { return m_sampleSink; }
171  private:
173  };
174 
175  class RemoveSpectrumSink : public Message {
177  public:
178  RemoveSpectrumSink(BasebandSampleSink* sampleSink) : Message(), m_sampleSink(sampleSink) { }
179  BasebandSampleSink* getSampleSink() const { return m_sampleSink; }
180  private:
182  };
183 
184  class GetErrorMessage : public Message {
186  public:
187  void setErrorMessage(const QString& text) { m_errorMessage = text; }
188  const QString& getErrorMessage() const { return m_errorMessage; }
189  private:
190  QString m_errorMessage;
191  };
192 
195  public:
196  void setDeviceDescription(const QString& text) { m_deviceDescription = text; }
197  const QString& getDeviceDescription() const { return m_deviceDescription; }
198  private:
200  };
201 
202  class ConfigureCorrection : public Message {
204  public:
205  ConfigureCorrection(bool dcOffsetCorrection, bool iqImbalanceCorrection, unsigned int index) :
206  Message(),
207  m_dcOffsetCorrection(dcOffsetCorrection),
208  m_iqImbalanceCorrection(iqImbalanceCorrection),
209  m_index(index)
210  { }
211  bool getDCOffsetCorrection() const { return m_dcOffsetCorrection; }
212  bool getIQImbalanceCorrection() const { return m_iqImbalanceCorrection; }
213  unsigned int getIndex() const { return m_index; }
214  private:
217  unsigned int m_index;
218  };
219 
220  class SetSpectrumSinkInput : public Message {
222  public:
223  SetSpectrumSinkInput(bool sourceElseSink, int index) :
224  m_sourceElseSink(sourceElseSink),
225  m_index(index)
226  { }
227  bool getSourceElseSink() const { return m_sourceElseSink; }
228  int getIndex() const { return m_index; }
229  private:
231  int m_index;
232  };
233 
234  enum State {
239  StError
240  };
241 
242  DSPDeviceMIMOEngine(uint32_t uid, QObject* parent = nullptr);
244 
245  MessageQueue* getInputMessageQueue() { return &m_inputMessageQueue; }
246 
247  void start();
248  void stop();
249 
250  bool initProcess();
251  bool startProcess();
252  void stopProcess();
253 
254  void setMIMO(DeviceSampleMIMO* mimo);
255  DeviceSampleMIMO *getMIMO() { return m_deviceSampleMIMO; }
256  void setMIMOSequence(int sequence);
257  uint getUID() const { return m_uid; }
258 
259  void addSourceStream(bool connect);
260  void removeLastSourceStream();
261  void addSinkStream(bool connect);
262  void removeLastSinkStream();
263 
264  void addChannelSource(ThreadedBasebandSampleSource* source, int index = 0);
265  void removeChannelSource(ThreadedBasebandSampleSource* source, int index = 0);
266  void addChannelSink(ThreadedBasebandSampleSink* sink, int index = 0);
267  void removeChannelSink(ThreadedBasebandSampleSink* sink, int index = 0);
268 
269  void addAncillarySink(BasebandSampleSink* sink, int index = 0);
270  void removeAncillarySink(BasebandSampleSink* sink, int index = 0);
271 
272  void addSpectrumSink(BasebandSampleSink* spectrumSink);
273  void removeSpectrumSink(BasebandSampleSink* spectrumSink);
274  void setSpectrumSinkInput(bool sourceElseSink, int index);
275 
276  State state() const { return m_state; }
277 
278  QString errorMessage();
279  QString deviceDescription();
280 
281  void configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection, int isource);
282 
283 private:
285  {
288  double m_iOffset;
289  double m_qOffset;
290  int m_iRange;
291  int m_qRange;
295 #if IMBALANCE_INT
296  // Fixed point DC + IQ corrections
303 #else
304  // Floating point DC + IQ corrections
311 #endif
313  {
314  m_dcOffsetCorrection = false;
315  m_iqImbalanceCorrection = false;
316  m_iOffset = 0;
317  m_qOffset = 0;
318  m_iRange = 1 << 16;
319  m_qRange = 1 << 16;
320  m_imbalance = 65536;
321  m_iBeta.reset();
322  m_qBeta.reset();
323  m_avgAmp.reset();
324  m_avgII.reset();
325  m_avgII2.reset();
326  m_avgIQ.reset();
327  m_avgPhi.reset();
328  m_avgQQ2.reset();
329  m_iBeta.reset();
330  m_qBeta.reset();
331  }
332  };
333 
336 
337  QString m_errorMessage;
339 
342 
343  MessageQueue m_inputMessageQueue; //<! Input message queue. Post here.
345 
346  typedef std::list<BasebandSampleSink*> BasebandSampleSinks;
347  std::vector<BasebandSampleSinks> m_basebandSampleSinks;
348 
349  typedef std::list<ThreadedBasebandSampleSink*> ThreadedBasebandSampleSinks;
350  std::vector<ThreadedBasebandSampleSinks> m_threadedBasebandSampleSinks;
352 
353  typedef std::list<ThreadedBasebandSampleSource*> ThreadedBasebandSampleSources;
354  std::vector<ThreadedBasebandSampleSources> m_threadedBasebandSampleSources;
356 
357  std::vector<SourceCorrection> m_sourcesCorrections;
358 
361  unsigned int m_spectrumInputIndex;
362 
363  void run();
364  void work(int nbWriteSamples);
365 
366  State gotoIdle();
367  State gotoInit();
368  State gotoRunning();
369  State gotoError(const QString& errorMsg);
370 
371  void handleSetMIMO(DeviceSampleMIMO* mimo);
372  void iqCorrections(SampleVector::iterator begin, SampleVector::iterator end, int isource, bool imbalanceCorrection);
373 
374 private slots:
375  void handleData();
376  void workSampleSink(unsigned int sinkIndex);
377  void handleSynchronousMessages();
378  void handleInputMessages();
379  void handleForwardToSpectrumSink(int nbSamples);
380 };
381 
382 #endif // SDRBASE_DSP_DSPDEVICEMIMOENGINE_H_
MovingAverageUtil< double, double, 128 > m_avgPhi
MovingAverageUtil< float, double, 128 > m_avgIQ
SyncMessenger m_syncMessenger
Used to process messages synchronously with the thread.
std::vector< ThreadedBasebandSampleSinks > m_threadedBasebandSampleSinks
channel sample sinks on their own thread (per input stream)
SetSpectrumSinkInput(bool sourceElseSink, int index)
AddThreadedBasebandSampleSource(ThreadedBasebandSampleSource *threadedSampleSource, unsigned int index)
AddBasebandSampleSink(BasebandSampleSink *sampleSink, unsigned int index)
DeviceSampleMIMO * getMIMO()
BasebandSampleSink * getSampleSink() const
std::list< ThreadedBasebandSampleSink * > ThreadedBasebandSampleSinks
RemoveBasebandSampleSink(BasebandSampleSink *sampleSink, unsigned int index)
RemoveSpectrumSink(BasebandSampleSink *sampleSink)
bool m_spectrumInputSourceElseSink
Source else sink stream to be used as spectrum sink input.
engine is before initialization
MovingAverageUtil< double, double, 128 > m_avgAmp
BasebandSampleSink * m_spectrumSink
The spectrum sink.
std::vector< SourceCorrection > m_sourcesCorrections
unsigned int uint32_t
Definition: rtptypes_win.h:46
std::list< BasebandSampleSink * > BasebandSampleSinks
ThreadedBasebandSampleSource * getThreadedSampleSource() const
MessageQueue * getInputMessageQueue()
DeviceSampleMIMO * getSampleMIMO() const
std::list< ThreadedBasebandSampleSource * > ThreadedBasebandSampleSources
AddThreadedBasebandSampleSink(ThreadedBasebandSampleSink *threadedSampleSink, unsigned int index)
#define MESSAGE_CLASS_DECLARATION
Definition: message.h:43
std::vector< int > m_sampleSinkConnectionIndexes
MovingAverageUtil< int32_t, int64_t, 1024 > m_qBeta
DeviceSampleMIMO * m_deviceSampleMIMO
ThreadedBasebandSampleSink * getThreadedSampleSink() const
MovingAverageUtil< float, double, 128 > m_avgII2
State state() const
Return DSP engine current state.
SetSampleMIMO(DeviceSampleMIMO *sampleMIMO)
ConfigureCorrection(bool dcOffsetCorrection, bool iqImbalanceCorrection, unsigned int index)
std::vector< BasebandSampleSinks > m_basebandSampleSinks
ancillary sample sinks on main thread (per input stream)
RemoveThreadedBasebandSampleSource(ThreadedBasebandSampleSource *threadedSampleSource, unsigned int index)
void setErrorMessage(const QString &text)
BasebandSampleSink * getSampleSink() const
MovingAverageUtil< int32_t, int64_t, 1024 > m_iBeta
unsigned int m_spectrumInputIndex
Index of the stream to be used as spectrum sink input.
ThreadedBasebandSampleSink * getThreadedSampleSink() const
ThreadedBasebandSampleSource * getThreadedSampleSource() const
MovingAverageUtil< float, double, 128 > m_avgQQ2
MovingAverageUtil< float, double, 128 > m_avgII
uint32_t m_uid
unique ID
AddSpectrumSink(BasebandSampleSink *sampleSink)
#define SDRBASE_API
Definition: export.h:40
std::vector< ThreadedBasebandSampleSources > m_threadedBasebandSampleSources
channel sample sources on their own threads (per output stream)
std::vector< int > m_sampleSourceConnectionIndexes
RemoveThreadedBasebandSampleSink(ThreadedBasebandSampleSink *threadedSampleSink, unsigned int index)
MessageQueue m_inputMessageQueue