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.
plutosdrinputthread.cpp
Go to the documentation of this file.
1 // Copyright (C) 2017 Edouard Griffiths, F4EXB //
3 // //
4 // This program is free software; you can redistribute it and/or modify //
5 // it under the terms of the GNU General Public License as published by //
6 // the Free Software Foundation as version 3 of the License, or //
7 // (at your option) any later version. //
8 // //
9 // This program is distributed in the hope that it will be useful, //
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
12 // GNU General Public License V3 for more details. //
13 // //
14 // You should have received a copy of the GNU General Public License //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
17 
19 #include "plutosdrinputsettings.h"
20 #include "plutosdrinputthread.h"
21 
22 #include "iio.h"
23 
24 PlutoSDRInputThread::PlutoSDRInputThread(uint32_t blocksizeSamples, DevicePlutoSDRBox* plutoBox, SampleSinkFifo* sampleFifo, QObject* parent) :
25  QThread(parent),
26  m_running(false),
27  m_plutoBox(plutoBox),
28  m_blockSizeSamples(blocksizeSamples),
29  m_convertBuffer(blocksizeSamples),
30  m_convertIt(m_convertBuffer.begin()),
31  m_sampleFifo(sampleFifo),
32  m_log2Decim(0),
33  m_fcPos(PlutoSDRInputSettings::FC_POS_CENTER),
34  m_phasor(0)
35 {
36  m_buf = new qint16[blocksizeSamples*2]; // (I,Q) -> 2 * int16_t
37  m_bufConv = new qint16[blocksizeSamples*2]; // (I,Q) -> 2 * int16_t
38 }
39 
41 {
42  stopWork();
43  delete[] m_buf;
44 }
45 
47 {
48  if (m_running) return; // return if running already
49 
50  m_startWaitMutex.lock();
51  start();
52  while(!m_running)
53  m_startWaiter.wait(&m_startWaitMutex, 100);
54  m_startWaitMutex.unlock();
55 }
56 
58 {
59  if (!m_running) return; // return if not running
60 
61  m_running = false;
62  wait();
63 }
64 
65 void PlutoSDRInputThread::setLog2Decimation(unsigned int log2_decim)
66 {
67  m_log2Decim = log2_decim;
68 }
69 
71 {
72  m_fcPos = fcPos;
73 }
74 
76 {
77  std::ptrdiff_t p_inc = m_plutoBox->rxBufferStep();
78 
79  qDebug("PlutoSDRInputThread::run: rxBufferStep: %ld bytes", p_inc);
80  qDebug("PlutoSDRInputThread::run: Rx sample size is %ld bytes", m_plutoBox->getRxSampleSize());
81  qDebug("PlutoSDRInputThread::run: Tx sample size is %ld bytes", m_plutoBox->getTxSampleSize());
82  qDebug("PlutoSDRInputThread::run: nominal nbytes_rx is %d bytes with 2 refills", m_blockSizeSamples*2);
83 
84  m_running = true;
85  m_startWaiter.wakeAll();
86 
87  while (m_running)
88  {
89  ssize_t nbytes_rx;
90  char *p_dat, *p_end;
91  int ihs; // half sample index (I then Q to make a sample)
92 
93  // Refill RX buffer
94  nbytes_rx = m_plutoBox->rxBufferRefill();
95 
96  if (nbytes_rx != m_blockSizeSamples*2)
97  {
98  qWarning("PlutoSDRInputThread::run: error refilling buf (1) %d / %d",(int) nbytes_rx, (int) m_blockSizeSamples*2);
99  usleep(200000);
100  continue;
101  }
102 
103  // READ: Get pointers to RX buf and read IQ from RX buf port 0
104  p_end = m_plutoBox->rxBufferEnd();
105  ihs = 0;
106 
107  // p_inc is 2 on a char* buffer therefore each iteration processes only the I or Q sample
108  // I and Q samples are processed one after the other
109  // conversion is not needed as samples are little endian
110 
111  for (p_dat = m_plutoBox->rxBufferFirst(); p_dat < p_end; p_dat += p_inc)
112  {
113  m_buf[ihs] = *((int16_t *) p_dat);
114 // iio_channel_convert(m_plutoBox->getRxChannel0(), (void *) &m_bufConv[ihs], (const void *) &m_buf[ihs]);
115  ihs++;
116  }
117 
118  // Refill RX buffer again - we still need twice more samples to complete since they come as I followed by Q
119  nbytes_rx = m_plutoBox->rxBufferRefill();
120 
121  if (nbytes_rx != m_blockSizeSamples*2)
122  {
123  qWarning("PlutoSDRInputThread::run: error refilling buf (2) %d / %d",(int) nbytes_rx, (int) m_blockSizeSamples*2);
124  usleep(200000);
125  continue;
126  }
127 
128  // READ: Get pointers to RX buf and read IQ from RX buf port 0
129  p_end = m_plutoBox->rxBufferEnd();
130 
131  // p_inc is 2 on a char* buffer therefore each iteration processes only the I or Q sample
132  // I and Q samples are processed one after the other
133  // conversion is not needed as samples are little endian
134 
135  for (p_dat = m_plutoBox->rxBufferFirst(); p_dat < p_end; p_dat += p_inc)
136  {
137  m_buf[ihs] = *((int16_t *) p_dat);
138 // iio_channel_convert(m_plutoBox->getRxChannel0(), (void *) &m_bufConv[ihs], (const void *) &m_buf[ihs]);
139  ihs++;
140  }
141 
142  //m_sampleFifo->write((unsigned char *) m_buf, ihs*sizeof(int16_t));
143  convert(m_buf, 2*m_blockSizeSamples); // size given in number of int16_t (I and Q interleaved)
144  }
145 
146  m_running = false;
147 }
148 
149 // Decimate according to specified log2 (ex: log2=4 => decim=16)
150 void PlutoSDRInputThread::convert(const qint16* buf, qint32 len)
151 {
152  SampleVector::iterator it = m_convertBuffer.begin();
153 
154  if (m_log2Decim == 0)
155  {
156  m_decimators.decimate1(&it, buf, len);
157  }
158  else
159  {
160  if (m_fcPos == 0) // Infra
161  {
162  switch (m_log2Decim)
163  {
164  case 1:
165  m_decimators.decimate2_inf(&it, buf, len);
166  break;
167  case 2:
168  m_decimators.decimate4_inf(&it, buf, len);
169  break;
170  case 3:
171  m_decimators.decimate8_inf(&it, buf, len);
172  break;
173  case 4:
174  m_decimators.decimate16_inf(&it, buf, len);
175  break;
176  case 5:
177  m_decimators.decimate32_inf(&it, buf, len);
178  break;
179  case 6:
180  m_decimators.decimate64_inf(&it, buf, len);
181  break;
182  default:
183  break;
184  }
185  }
186  else if (m_fcPos == 1) // Supra
187  {
188  switch (m_log2Decim)
189  {
190  case 1:
191  m_decimators.decimate2_sup(&it, buf, len);
192  break;
193  case 2:
194  m_decimators.decimate4_sup(&it, buf, len);
195  break;
196  case 3:
197  m_decimators.decimate8_sup(&it, buf, len);
198  break;
199  case 4:
200  m_decimators.decimate16_sup(&it, buf, len);
201  break;
202  case 5:
203  m_decimators.decimate32_sup(&it, buf, len);
204  break;
205  case 6:
206  m_decimators.decimate64_sup(&it, buf, len);
207  break;
208  default:
209  break;
210  }
211  }
212  else if (m_fcPos == 2) // Center
213  {
214  switch (m_log2Decim)
215  {
216  case 1:
217  m_decimators.decimate2_cen(&it, buf, len);
218  break;
219  case 2:
220  m_decimators.decimate4_cen(&it, buf, len);
221  break;
222  case 3:
223  m_decimators.decimate8_cen(&it, buf, len);
224  break;
225  case 4:
226  m_decimators.decimate16_cen(&it, buf, len);
227  break;
228  case 5:
229  m_decimators.decimate32_cen(&it, buf, len);
230  break;
231  case 6:
232  m_decimators.decimate64_cen(&it, buf, len);
233  break;
234  default:
235  break;
236  }
237  }
238  }
239 
240  m_sampleFifo->write(m_convertBuffer.begin(), it);
241 }
242 
short int16_t
Definition: rtptypes_win.h:43
void decimate2_inf(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:498
void decimate64_sup(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:2975
DevicePlutoSDRBox * m_plutoBox
void setLog2Decimation(unsigned int log2_decim)
void decimate64_cen(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:3040
void decimate2_sup(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:526
void decimate2_cen(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:554
uint write(const quint8 *data, uint count)
QWaitCondition m_startWaiter
void decimate8_sup(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:941
Decimators< qint32, qint16, SDR_RX_SAMP_SZ, 12 > m_decimators
void decimate64_inf(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:2418
void decimate32_inf(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:1592
void decimate32_sup(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:1902
int16_t * m_buf
holds I+Q values of each sample from devce
void convert(const qint16 *buf, qint32 len)
unsigned int uint32_t
Definition: rtptypes_win.h:46
void decimate4_sup(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:682
void decimate8_cen(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:1057
void decimate8_inf(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:825
void decimate16_sup(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:1300
PlutoSDRInputThread(uint32_t blocksize, DevicePlutoSDRBox *plutoBox, SampleSinkFifo *sampleFifo, QObject *parent=0)
SampleVector m_convertBuffer
vector of (I,Q) samples used for decimation and scaling conversion
std::ptrdiff_t rxBufferStep()
void decimate4_cen(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:782
void decimate4_inf(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:582
SampleSinkFifo * m_sampleFifo
DSP sample FIFO (I,Q)
uint32_t m_blockSizeSamples
buffer sizes in number of (I,Q) samples
void decimate16_inf(SampleVector::iterator *it, const T *buf, qint32 len)
Definition: decimators.h:1117
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
int16_t * m_bufConv
holds I+Q values of each sample converted to host format via iio_channel_convert