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.
generic.h
Go to the documentation of this file.
1 // This file is part of LeanSDR Copyright (C) 2016-2018 <pabr@pabr.org>.
2 // See the toplevel README for more information.
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, either 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 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/>.
16 
17 #ifndef LEANSDR_GENERIC_H
18 #define LEANSDR_GENERIC_H
19 
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <sys/types.h>
23 
24 #ifdef _MSC_VER
25 #include <stdlib.h>
26 #include <io.h>
27 #else
28 #include <unistd.h>
29 #endif
30 
31 #include "leansdr/math.h"
32 
33 namespace leansdr
34 {
35 
37 // Simple blocks
39 
40 // [file_reader] reads raw data from a file descriptor into a [pipebuf].
41 // If the file descriptor is seekable, data can be looped.
42 
43 template <typename T>
45 {
46  file_reader(scheduler *sch, int _fdin, pipebuf<T> &_out)
47  : runnable(sch, _out.name),
48  loop(false),
49  filler(NULL),
50  fdin(_fdin), out(_out)
51  {
52  }
53  void run()
54  {
55  size_t size = out.writable() * sizeof(T);
56  if (!size)
57  return;
58 
59  again:
60  ssize_t nr = read(fdin, out.wr(), size);
61  if (nr < 0 && errno == EWOULDBLOCK)
62  {
63  if (filler)
64  {
65  if (sch->debug)
66  fprintf(stderr, "U");
67  out.write(*filler);
68  }
69  return;
70  }
71  if (nr < 0)
72  fatal("read(file_reader)");
73  if (!nr)
74  {
75  if (!loop)
76  return;
77  if (sch->debug)
78  fprintf(stderr, "%s looping\n", name);
79  off_t res = lseek(fdin, 0, SEEK_SET);
80  if (res == (off_t)-1)
81  fatal("lseek");
82  goto again;
83  }
84 
85  // Always stop at element boundary (may block)
86  size_t partial = nr % sizeof(T);
87  size_t remain = partial ? sizeof(T) - partial : 0;
88  while (remain)
89  {
90  if (sch->debug)
91  fprintf(stderr, "+");
92  ssize_t nr2 = read(fdin, (char *)out.wr() + nr, remain);
93  if (nr2 <= 0)
94  fatal("partial read");
95  nr += nr2;
96  remain -= nr2;
97  }
98 
99  out.written(nr / sizeof(T));
100  }
101  bool loop;
102  void set_realtime(T &_filler)
103  {
104  int flags = fcntl(fdin, F_GETFL);
105  if (fcntl(fdin, F_SETFL, flags | O_NONBLOCK))
106  fatal("fcntl");
107  filler = new T(_filler);
108  }
109 
110  private:
111  T *filler;
112  int fdin;
114 };
115 
116 // [file_writer] writes raw data from a [pipebuf] to a file descriptor.
117 
118 template <typename T>
120 {
121  file_writer(scheduler *sch, pipebuf<T> &_in, int _fdout) : runnable(sch, _in.name),
122  in(_in), fdout(_fdout)
123  {
124  }
125  void run()
126  {
127  int size = in.readable() * sizeof(T);
128  if (!size)
129  return;
130  int nw = write(fdout, in.rd(), size);
131  if (!nw)
132  fatal("pipe");
133  if (nw < 0)
134  fatal("write");
135  if (nw % sizeof(T))
136  fatal("partial write");
137  in.read(nw / sizeof(T));
138  }
139 
140  private:
142  int fdout;
143 };
144 
145 // [file_printer] writes data from a [pipebuf] to a file descriptor,
146 // with printf-style formatting and optional scaling.
147 
148 template <typename T>
150 {
151  file_printer(scheduler *sch, const char *_format,
152  pipebuf<T> &_in, int _fdout,
153  int _decimation = 1) : runnable(sch, _in.name),
154  scale(1), decimation(_decimation),
155  in(_in), format(_format), fdout(_fdout), phase(0)
156  {
157  }
158  void run()
159  {
160  int n = in.readable();
161  T *pin = in.rd(), *pend = pin + n;
162  for (; pin < pend; ++pin)
163  {
164  if (++phase >= decimation)
165  {
166  phase -= decimation;
167  char buf[256];
168  int len = snprintf(buf, sizeof(buf), format, (*pin) * scale);
169  if (len < 0)
170  fatal("obsolete glibc");
171  int nw = write(fdout, buf, len);
172  if (nw != len)
173  fatal("partial write");
174  }
175  }
176  in.read(n);
177  }
178  T scale;
180 
181  private:
183  const char *format;
184  int fdout;
185  int phase;
186 };
187 
188 // [file_carrayprinter] writes all data available from a [pipebuf]
189 // to a file descriptor on a single line.
190 // Special case for complex.
191 
192 template <typename T>
194 {
196  const char *_head,
197  const char *_format,
198  const char *_sep,
199  const char *_tail,
200  pipebuf<complex<T>> &_in, int _fdout) : runnable(sch, _in.name),
201  scale(1), fixed_size(0), in(_in),
202  head(_head), format(_format), sep(_sep), tail(_tail),
203  fout(fdopen(_fdout, "w"))
204  {
205  }
206  void run()
207  {
208  int n, nmin = fixed_size ? fixed_size : 1;
209  while ((n = in.readable()) >= nmin)
210  {
211  if (fixed_size)
212  n = fixed_size;
213  if (fout)
214  {
215  fprintf(fout, head, n);
216  complex<T> *pin = in.rd();
217  for (int i = 0; i < n; ++i)
218  {
219  if (i)
220  fprintf(fout, "%s", sep);
221  fprintf(fout, format, pin[i].re * scale, pin[i].im * scale);
222  }
223  fprintf(fout, "%s", tail);
224  }
225  fflush(fout);
226  in.read(n);
227  }
228  }
229  T scale;
230  int fixed_size; // Number of elements per batch, or 0.
231  private:
233  const char *head, *format, *sep, *tail;
234  FILE *fout;
235 };
236 
237 template <typename T, int N>
239 {
241  const char *_head,
242  const char *_format,
243  const char *_sep,
244  const char *_tail,
245  pipebuf<T[N]> &_in, int _fdout, int _n = N) : runnable(sch, _in.name), scale(1), in(_in),
246  head(_head), format(_format), sep(_sep), tail(_tail), n(_n)
247  {
248  fout = fdopen(_fdout, "w");
249  if (!fout)
250  fatal("fdopen");
251  }
252  void run()
253  {
254  while (in.readable() >= 1)
255  {
256  fprintf(fout, head, n);
257  T(*pin)
258  [N] = in.rd();
259  for (int i = 0; i < n; ++i)
260  {
261  if (i)
262  fprintf(fout, "%s", sep);
263  fprintf(fout, format, (*pin)[i] * scale);
264  }
265  fprintf(fout, "%s", tail);
266  in.read(1);
267  }
268  fflush(fout);
269  }
270  T scale;
271 
272  private:
274  const char *head, *format, *sep, *tail;
275  FILE *fout;
276  int n;
277 };
278 
279 // [itemcounter] writes the number of input items to the output [pipebuf].
280 // [Tout] must be a numeric type.
281 
282 template <typename Tin, typename Tout>
284 {
286  : runnable(sch, "itemcounter"),
287  in(_in), out(_out)
288  {
289  }
290  void run()
291  {
292  if (out.writable() < 1)
293  return;
294  unsigned long count = in.readable();
295  if (!count)
296  return;
297  out.write(count);
298  in.read(count);
299  }
300 
301  private:
304 };
305 
306 // [decimator] forwards 1 in N sample.
307 
308 template <typename T>
310 {
311  int d;
312 
313  decimator(scheduler *sch, int _d, pipebuf<T> &_in, pipebuf<T> &_out)
314  : runnable(sch, "decimator"),
315  d(_d),
316  in(_in), out(_out)
317  {
318  }
319  void run()
320  {
321  long count = min(in.readable() / d, out.writable());
322  T *pin = in.rd(), *pend = pin + count * d, *pout = out.wr();
323  for (; pin < pend; pin += d, ++pout)
324  *pout = *pin;
325  in.read(count * d);
326  out.written(count);
327  }
328 
329  private:
332 };
333 
334 // [rate_estimator] accumulates counts of two quantities
335 // and periodically outputs their ratio.
336 
337 template <typename T>
339 {
341 
343  pipebuf<int> &_num, pipebuf<int> &_den,
344  pipebuf<float> &_rate)
345  : runnable(sch, "rate_estimator"),
346  sample_size(10000),
347  num(_num), den(_den), rate(_rate),
348  acc_num(0), acc_den(0)
349  {
350  }
351 
352  void run()
353  {
354  if (rate.writable() < 1)
355  return;
356  int count = min(num.readable(), den.readable());
357  int *pnum = num.rd(), *pden = den.rd();
358  for (int n = count; n--; ++pnum, ++pden)
359  {
360  acc_num += *pnum;
361  acc_den += *pden;
362  }
363  num.read(count);
364  den.read(count);
365  if (acc_den >= sample_size)
366  {
367  rate.write((float)acc_num / acc_den);
368  acc_num = acc_den = 0;
369  }
370  }
371 
372  private:
375  T acc_num, acc_den;
376 };
377 
378 // SERIALIZER
379 
380 template <typename Tin, typename Tout>
382 {
384  : nin(max((size_t)1, sizeof(Tin) / sizeof(Tout))),
385  nout(max((size_t)1, sizeof(Tout) / sizeof(Tin))),
386  in(_in), out(_out, nout)
387  {
388  if (nin * sizeof(Tin) != nout * sizeof(Tout))
389  fail("serializer: incompatible sizes");
390  }
391  void run()
392  {
393  while (in.readable() >= nin && out.writable() >= nout)
394  {
395  memcpy(out.wr(), in.rd(), nout * sizeof(Tout));
396  in.read(nin);
397  out.written(nout);
398  }
399  }
400 
401  private:
402  int nin, nout;
405 }; // serializer
406 
407 // [buffer_reader] reads from a user-supplied buffer.
408 
409 template <typename T>
411 {
412  buffer_reader(scheduler *sch, T *_data, int _count, pipebuf<T> &_out)
413  : runnable(sch, "buffer_reader"),
414  data(_data), count(_count), out(_out), pos(0)
415  {
416  }
417  void run()
418  {
419  int n = min(out.writable(), (unsigned long)(count - pos));
420  memcpy(out.wr(), &data[pos], n * sizeof(T));
421  pos += n;
422  out.written(n);
423  }
424 
425  private:
426  T *data;
427  int count;
429  int pos;
430 }; // buffer_reader
431 
432 // [buffer_writer] writes to a user-supplied buffer.
433 
434 template <typename T>
436 {
437  buffer_writer(scheduler *sch, pipebuf<T> &_in, T *_data, int _count)
438  : runnable(sch, "buffer_reader"),
439  in(_in), data(_data), count(_count), pos(0)
440  {
441  }
442  void run()
443  {
444  int n = min(in.readable(), (unsigned long)(count - pos));
445  memcpy(&data[pos], in.rd(), n * sizeof(T));
446  in.read(n);
447  pos += n;
448  }
449 
450  private:
452  T *data;
453  int count;
454  int pos;
455 }; // buffer_writer
456 
457 } // namespace leansdr
458 
459 #endif // LEANSDR_GENERIC_H
pipewriter< T > out
Definition: generic.h:428
const char * format
Definition: generic.h:183
pipewriter< float > rate
Definition: generic.h:374
rate_estimator(scheduler *sch, pipebuf< int > &_num, pipebuf< int > &_den, pipebuf< float > &_rate)
Definition: generic.h:342
int decimation(float Fin, float Fout)
Definition: datvdemod.h:66
pipereader< T > in
Definition: generic.h:330
file_reader(scheduler *sch, int _fdin, pipebuf< T > &_out)
Definition: generic.h:46
pipereader< T > in
Definition: generic.h:182
pipereader< T > in
Definition: generic.h:451
pipereader< complex< T > > in
Definition: generic.h:232
pipewriter< Tout > out
Definition: generic.h:303
pipewriter< T > out
Definition: generic.h:331
file_carrayprinter(scheduler *sch, const char *_head, const char *_format, const char *_sep, const char *_tail, pipebuf< complex< T >> &_in, int _fdout)
Definition: generic.h:195
pipereader< Tin > in
Definition: generic.h:302
buffer_writer(scheduler *sch, pipebuf< T > &_in, T *_data, int _count)
Definition: generic.h:437
serializer(scheduler *sch, pipebuf< Tin > &_in, pipebuf< Tout > &_out)
Definition: generic.h:383
void fail(const char *s)
Definition: framework.cpp:11
pipereader< T > in
Definition: generic.h:141
int32_t i
Definition: decimators.h:244
pipereader< int > num
Definition: generic.h:373
void set_realtime(T &_filler)
Definition: generic.h:102
file_printer(scheduler *sch, const char *_format, pipebuf< T > &_in, int _fdout, int _decimation=1)
Definition: generic.h:151
decimator(scheduler *sch, int _d, pipebuf< T > &_in, pipebuf< T > &_out)
Definition: generic.h:313
file_writer(scheduler *sch, pipebuf< T > &_in, int _fdout)
Definition: generic.h:121
itemcounter(scheduler *sch, pipebuf< Tin > &_in, pipebuf< Tout > &_out)
Definition: generic.h:285
buffer_reader(scheduler *sch, T *_data, int _count, pipebuf< T > &_out)
Definition: generic.h:412
void fatal(const char *s)
Definition: framework.cpp:6
pipereader< T[N]> in
Definition: generic.h:273
scheduler * sch
Definition: framework.h:199
file_vectorprinter(scheduler *sch, const char *_head, const char *_format, const char *_sep, const char *_tail, pipebuf< T[N]> &_in, int _fdout, int _n=N)
Definition: generic.h:240
pipereader< Tin > in
Definition: generic.h:403
pipewriter< Tout > out
Definition: generic.h:404
pipewriter< T > out
Definition: generic.h:113
T max(const T &x, const T &y)
Definition: framework.h:446
T min(const T &x, const T &y)
Definition: framework.h:440