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.
xtrxinputthread.cpp
Go to the documentation of this file.
1 // Copyright (C) 2017, 2018 Edouard Griffiths, F4EXB //
3 // Copyright (C) 2017 Sergey Kostanbaev, Fairwaves Inc. //
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 #include <errno.h>
20 #include <chrono>
21 #include <thread>
22 
23 #include "xtrx/devicextrx.h"
24 #include "xtrxinputsettings.h"
25 #include "xtrxinputthread.h"
26 
27 XTRXInputThread::XTRXInputThread(struct xtrx_dev *dev, unsigned int nbChannels, unsigned int uniqueChannelIndex, QObject* parent) :
28  QThread(parent),
29  m_running(false),
30  m_dev(dev),
31  m_nbChannels(nbChannels),
32  m_uniqueChannelIndex(uniqueChannelIndex)
33 {
34  qDebug("XTRXInputThread::XTRXInputThread: nbChannels: %u uniqueChannelIndex: %u", nbChannels, uniqueChannelIndex);
35  m_channels = new Channel[2];
36 
37  for (unsigned int i = 0; i < 2; i++) {
39  }
40 }
41 
43 {
44  qDebug("XTRXInputThread::~XTRXInputThread");
45 
46  if (m_running) {
47  stopWork();
48  }
49 
50  delete[] m_channels;
51 }
52 
54 {
55  if (m_running) {
56  return; // return if running already
57  }
58 
59  m_startWaitMutex.lock();
60  start();
61 
62  while (!m_running) {
63  m_startWaiter.wait(&m_startWaitMutex, 100);
64  }
65 
66  m_startWaitMutex.unlock();
67 }
68 
70 {
71  if (!m_running) {
72  return; // return if not running
73  }
74 
75  m_running = false;
76  wait();
77 }
78 
79 
81 {
82  int res;
83 
84  m_running = true;
85  m_startWaiter.wakeAll();
86 
87  unsigned int nbFifos = getNbFifos();
88 
89  if ((m_nbChannels != 0) && (nbFifos != 0))
90  {
91  xtrx_run_params params;
92  xtrx_run_params_init(&params);
93 
94  params.dir = XTRX_RX;
95  params.rx.chs = XTRX_CH_AB;
96  params.rx.wfmt = XTRX_WF_16;
97  params.rx.hfmt = XTRX_IQ_INT16;
98  params.rx_stream_start = 2*DeviceXTRX::blockSize; // was 2*8192
99  params.rx.paketsize = 2*DeviceXTRX::blockSize;
100 
101  if (m_nbChannels == 1)
102  {
103  qDebug("XTRXInputThread::run: SI mode for channel #%u", m_uniqueChannelIndex);
104  params.rx.flags |= XTRX_RSP_SISO_MODE;
105 
106  if (m_uniqueChannelIndex == 1) {
107  params.rx.flags |= XTRX_RSP_SWAP_AB;
108  }
109  }
110 
111  res = xtrx_run_ex(m_dev, &params);
112 
113  if (res != 0)
114  {
115  qCritical("XTRXInputThread::run: could not start stream err:%d", res);
116  m_running = false;
117  }
118  else
119  {
120  std::this_thread::sleep_for(std::chrono::milliseconds(50));
121  qDebug("XTRXInputThread::run: stream started");
122  }
123 
124  const unsigned int elemSize = 4; // XTRX uses 4 byte I+Q samples
125  std::vector<std::vector<char>> buffMem(m_nbChannels, std::vector<char>(elemSize*DeviceXTRX::blockSize));
126  std::vector<void *> buffs(m_nbChannels);
127 
128  for (std::size_t i = 0; i < m_nbChannels; i++) {
129  buffs[i] = buffMem[i].data();
130  }
131 
132  xtrx_recv_ex_info_t nfo;
133  nfo.samples = DeviceXTRX::blockSize;
134  nfo.buffer_count = m_nbChannels;
135  nfo.buffers = (void* const*) buffs.data();
136  nfo.flags = RCVEX_DONT_INSER_ZEROS | RCVEX_DROP_OLD_ON_OVERFLOW;
137 
138  while (m_running)
139  {
140  res = xtrx_recv_sync_ex(m_dev, &nfo);
141 
142  if (res < 0)
143  {
144  qCritical("XTRXInputThread::run read error: %d", res);
145  qDebug("XTRXInputThread::run: out_samples: %u out_events: %u", nfo.out_samples, nfo.out_events);
146  break;
147  }
148 
149  if (nfo.out_events & RCVEX_EVENT_OVERFLOW) {
150  qDebug("XTRXInputThread::run: overflow");
151  }
152 
153  if (m_nbChannels > 1) {
154  callbackMI((const qint16*) buffs[0], (const qint16*) buffs[1], 2 * nfo.out_samples);
155  } else {
156  callbackSI((const qint16*) buffs[0], 2 * nfo.out_samples);
157  }
158  }
159 
160  res = xtrx_stop(m_dev, XTRX_RX);
161 
162  if (res != 0)
163  {
164  qCritical("XTRXInputThread::run: could not stop stream");
165  }
166  else
167  {
168  std::this_thread::sleep_for(std::chrono::milliseconds(50));
169  qDebug("XTRXInputThread::run: stream stopped");
170  }
171  }
172  else
173  {
174  qWarning("XTRXInputThread::run: no channels or FIFO allocated. Aborting");
175  }
176 
177  m_running = false;
178 }
179 
181 {
182  unsigned int fifoCount = 0;
183 
184  for (unsigned int i = 0; i < 2; i++)
185  {
186  if (m_channels[i].m_sampleFifo) {
187  fifoCount++;
188  }
189  }
190 
191  return fifoCount;
192 }
193 
194 void XTRXInputThread::setLog2Decimation(unsigned int channel, unsigned int log2_decim)
195 {
196  if (channel < 2) {
197  m_channels[channel].m_log2Decim = log2_decim;
198  }
199 }
200 
201 unsigned int XTRXInputThread::getLog2Decimation(unsigned int channel) const
202 {
203  if (channel < 2) {
204  return m_channels[channel].m_log2Decim;
205  } else {
206  return 0;
207  }
208 }
209 
210 void XTRXInputThread::setFifo(unsigned int channel, SampleSinkFifo *sampleFifo)
211 {
212  if (channel < 2) {
213  m_channels[channel].m_sampleFifo = sampleFifo;
214  }
215 }
216 
218 {
219  if (channel < 2) {
220  return m_channels[channel].m_sampleFifo;
221  } else {
222  return 0;
223  }
224 }
225 
226 void XTRXInputThread::callbackSI(const qint16* buf, qint32 len)
227 {
228  SampleVector::iterator it = m_channels[m_uniqueChannelIndex].m_convertBuffer.begin();
229 
230  if (m_channels[m_uniqueChannelIndex].m_log2Decim == 0)
231  {
233  }
234  else
235  {
236  switch (m_channels[m_uniqueChannelIndex].m_log2Decim)
237  {
238  case 1:
240  break;
241  case 2:
243  break;
244  case 3:
246  break;
247  case 4:
249  break;
250  case 5:
252  break;
253  case 6:
255  break;
256  default:
257  break;
258  }
259  }
260 
262 }
263 
264 void XTRXInputThread::callbackMI(const qint16* buf0, const qint16* buf1, qint32 len)
265 {
266  unsigned int uniqueChannelIndex = m_uniqueChannelIndex;
267 
268  // channel 0
270  callbackSI(buf0, len);
271  // channel 1
273  callbackSI(buf1, len);
274 
275  m_uniqueChannelIndex = uniqueChannelIndex;
276 }
QWaitCondition m_startWaiter
unsigned int getNbFifos()
void decimate64_cen(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:3040
void decimate2_cen(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:554
uint write(const quint8 *data, uint count)
Channel * m_channels
Array of channels dynamically allocated for the given number of Rx channels.
XTRXInputThread(struct xtrx_dev *dev, unsigned int nbChannels, unsigned int uniqueChannelIndex=0, QObject *parent=0)
unsigned int m_uniqueChannelIndex
virtual void stopWork()
void decimate8_cen(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:1057
SampleSinkFifo * m_sampleFifo
Decimators< qint32, qint16, SDR_RX_SAMP_SZ, 12 > m_decimators
int32_t i
Definition: decimators.h:244
void setFifo(unsigned int channel, SampleSinkFifo *sampleFifo)
void decimate4_cen(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:782
void setLog2Decimation(unsigned int channel, unsigned int log2_decim)
static const unsigned int blockSize
Definition: devicextrx.h:44
unsigned int getLog2Decimation(unsigned int channel) const
SampleSinkFifo * getFifo(unsigned int channel)
struct xtrx_dev * m_dev
virtual void startWork()
unsigned int m_nbChannels
void decimate16_cen(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:1483
void decimate32_cen(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:2212
void decimate1(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:462
void callbackMI(const qint16 *buf0, const qint16 *buf1, qint32 len)
void callbackSI(const qint16 *buf, qint32 len)