libcyberradio  22.01.24
DUCSink.cpp
1 /* -*- c++ -*- */
2 /***************************************************************************
3  * \file DUCSink.cpp
4  *
5  * \brief Implementation of the digital upconverter (DUC) transmission
6  * sink block for the NDR651.
7  *
8  * \author DA
9  * \copyright 2015 CyberRadio Solutions, Inc.
10  */
11 
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15 
16 #include "LibCyberRadio/NDR651/DUCSink.h"
17 #include "LibCyberRadio/NDR651/TransmitPacketizer.h"
18 #include <stdarg.h>
19 #include <iostream>
20 #include <math.h>
21 
22 
23 namespace LibCyberRadio
24 {
25  namespace NDR651
26  {
28  const std::string& name,
29  const std::string& radio_host_name,
30  unsigned int radio_tcp_port,
31  unsigned int tengig_iface_index,
32  float iq_scale_factor,
33  unsigned int duc_channel,
34  const std::string& duc_iface_string,
35  unsigned int duc_rate_index,
36  long duc_frequency,
37  float duc_attenuation,
38  unsigned int duc_tx_channels,
39  double duc_tx_frequency,
40  unsigned int duc_tx_attenuation,
41  unsigned int duc_stream_id,
42  bool config_tx,
43  bool debug,
44  unsigned int fc_update_rate,
45  bool use_udp,
46  bool use_ring_buffer,
47  unsigned int duchsPfThresh,
48  unsigned int duchsPeThresh,
49  unsigned int duchsPeriod,
50  bool updatePE,
51  int txinv_mode) :
52  Debuggable(debug, name),
53  d_name(name),
54  d_radio_host_name(radio_host_name),
55  d_radio_tcp_port(radio_tcp_port),
56  d_duc_iface_index(tengig_iface_index),
57  d_iq_scale_factor(iq_scale_factor),
58  d_duc_channel(duc_channel),
59  d_duc_iface_string(duc_iface_string),
60  d_duc_rate_index(duc_rate_index),
61  d_duc_frequency(duc_frequency),
62  d_duc_attenuation(duc_attenuation),
63  d_duc_tx_channels(duc_tx_channels),
64  d_duc_tx_frequency(duc_tx_frequency),
65  d_duc_tx_attenuation(duc_tx_attenuation),
66  d_duc_stream_id(duc_stream_id),
67  d_config_tx(config_tx),
68  d_fc_update_rate(fc_update_rate),
69  d_use_udp(use_udp),
70  d_use_ring_buffer(use_ring_buffer),
71  d_tx(NULL),
72  d_duchsPfThresh(duchsPfThresh),
73  d_duchsPeThresh(duchsPeThresh),
74  d_duchsPeriod(duchsPeriod),
75  d_updatePE(updatePE),
76  d_duc_txinv_mode(txinv_mode)
77  {
78  this->debug("construction\n");
79  memset(d_sample_buffer, 0, SAMPLES_PER_FRAME * 2 * sizeof(short));
80  //~ set_duc_iface_index_from_string();
81  // d_tx initial configuration
82  d_tx = new NDR651::TransmitPacketizer(
83  d_radio_host_name, d_radio_tcp_port,
84  d_duc_channel, d_duc_iface_string,
85  d_duc_iface_index, -1, d_duc_rate_index,
86  d_duc_tx_channels, d_duc_frequency,
87  d_duc_attenuation, d_duc_tx_frequency,
88  d_duc_tx_attenuation, d_duc_stream_id,
89  d_config_tx, _debug);
90  d_tx->setDuchsParameters(d_duchsPfThresh, d_duchsPeThresh, d_duchsPeriod, d_updatePE);
91  d_tx->setDucTxinvMode(d_duc_txinv_mode);
92  }
93 
94  /*
95  * Our virtual destructor.
96  */
98  {
99  this->debug("destruction\n");
100  if ( d_tx != NULL )
101  delete d_tx;
102  }
103 
104  std::string DUCSink::get_radio_host_name() const
105  {
106  return d_radio_host_name;
107  }
108 
110  {
111  return d_radio_tcp_port;
112  }
113 
114  std::vector<std::string> DUCSink::get_tengig_iface_list() const
115  {
116  return d_tengig_iface_list;
117  }
118 
120  {
121  return d_iq_scale_factor;
122  }
123 
124  void DUCSink::set_iq_scale_factor(float iq_scale_factor)
125  {
126  d_iq_scale_factor = iq_scale_factor;
127  }
128 
130  {
131  return d_duc_channel;
132  }
133 
134  void DUCSink::set_duc_channel(int duc_channel)
135  {
136  d_duc_channel = duc_channel;
137  if ( d_tx != NULL )
138  d_tx->setDucChannel(d_duc_channel);
139  }
140 
141  std::string DUCSink::get_duc_iface_string() const
142  {
143  return d_duc_iface_string;
144  }
145 
147  {
148  return d_duc_iface_index;
149  }
150 
151  void DUCSink::set_duc_iface_string(const std::string& duc_iface_string)
152  {
153  d_duc_iface_string = duc_iface_string;
154  //~ set_duc_iface_index_from_string();
155  if ( d_tx != NULL )
156  d_tx->setDucInterface(d_duc_iface_string, d_duc_iface_index);
157  }
158 
160  {
161  return d_duc_rate_index;
162  }
163 
164  void DUCSink::set_duc_rate_index(int duc_rate_index)
165  {
166  d_duc_rate_index = duc_rate_index;
167  if ( d_tx != NULL )
168  d_tx->setDucRate(d_duc_rate_index);
169  }
170 
172  {
173  return d_duc_frequency;
174  }
175 
176  void DUCSink::set_duc_frequency(long duc_frequency)
177  {
178  d_duc_frequency = duc_frequency;
179  if ( d_tx != NULL )
180  d_tx->setDucFreq(d_duc_frequency);
181  }
182 
183  void DUCSink::set_duc_txinv_mode(int duc_txinv_mode)
184  {
185  d_duc_txinv_mode = duc_txinv_mode;
186  if ( d_tx != NULL )
187  d_tx->setDucTxinvMode((unsigned int)duc_txinv_mode);
188  }
189 
191  {
192  return d_duc_attenuation;
193  }
194 
195  void DUCSink::set_duc_attenuation(float duc_attenuation)
196  {
197  d_duc_attenuation = duc_attenuation;
198  if ( d_tx != NULL )
199  d_tx->setDucAtten(d_duc_attenuation);
200  }
201 
202  unsigned int DUCSink::get_duc_tx_channels() const
203  {
204  return d_duc_tx_channels;
205  }
206 
207  void DUCSink::set_duc_tx_channels(unsigned int duc_tx_channels)
208  {
209  d_duc_tx_channels = duc_tx_channels;
210  if ( d_tx != NULL )
211  d_tx->setDucTxChannels(d_duc_tx_channels);
212  }
213 
215  {
216  return d_duc_tx_frequency;
217  }
218 
219  void DUCSink::set_duc_tx_frequency(double duc_tx_frequency)
220  {
221  d_duc_tx_frequency = duc_tx_frequency;
222  if ( (d_tx != NULL)&&d_config_tx )
223  d_tx->setTxFreq(d_duc_tx_frequency);
224  }
225 
226  unsigned int DUCSink::get_duc_tx_attenuation() const
227  {
228  return d_duc_tx_attenuation;
229  }
230 
231  void DUCSink::set_duc_tx_attenuation(unsigned int duc_tx_attenuation)
232  {
233  d_duc_tx_attenuation = duc_tx_attenuation;
234  if ( (d_tx != NULL)&&d_config_tx )
235  d_tx->setTxAtten(d_duc_tx_attenuation);
236  }
237 
238  unsigned int DUCSink::get_duc_stream_id() const
239  {
240  return d_duc_stream_id;
241  }
242 
243  void DUCSink::set_duc_stream_id(unsigned int duc_stream_id)
244  {
245  d_duc_stream_id = duc_stream_id;
246  if ( d_tx != NULL )
247  d_tx->setStreamId(d_duc_stream_id);
248  }
249 
251  {
252  long ret = 0;
253  if ( d_duc_rate_index == 16 )
254  ret = 270833;
255  else
256  ret = (long)(102.4e6 / pow(2, d_duc_rate_index));
257  return ret;
258  }
259 
260  void DUCSink::set_duchs_pf_threshold(unsigned int duchsPfThresh) {
261  d_duchsPfThresh = duchsPfThresh;
262  //~ d_tx->setDuchsParameters(duchsPfThresh, d_tx->getDuchsPeThresh(), d_tx->getDuchsPeriod(), d_tx->getUpdatePE());
263  d_tx->setDuchsParameters(d_duchsPfThresh, d_duchsPeThresh, d_duchsPeriod, d_updatePE);
264  }
265 
266  void DUCSink::set_duchs_pe_threshold(unsigned int duchsPeThresh) {
267  d_duchsPeThresh = duchsPeThresh;
268  //~ d_tx->setDuchsParameters(d_tx->getDuchsPfThresh(), duchsPeThresh, d_tx->getDuchsPeriod(), d_tx->getUpdatePE());
269  d_tx->setDuchsParameters(d_duchsPfThresh, d_duchsPeThresh, d_duchsPeriod, d_updatePE);
270  }
271 
272  void DUCSink::set_duchs_period(unsigned int duchsPeriod) {
273  d_duchsPeriod = duchsPeriod;
274  //~ d_tx->setDuchsParameters(d_tx->getDuchsPfThresh(), d_tx->getDuchsPeThresh(), duchsPeriod, d_tx->getUpdatePE());
275  d_tx->setDuchsParameters(d_duchsPfThresh, d_duchsPeThresh, d_duchsPeriod, d_updatePE);
276  }
277 
278  void DUCSink::set_duchs_update_pe(bool updatePE) {
279  d_updatePE = updatePE;
280  //~ d_tx->setDuchsParameters(d_tx->getDuchsPfThresh(), d_tx->getDuchsPeThresh(), d_tx->getDuchsPeriod(), updatePE);
281  d_tx->setDuchsParameters(d_duchsPfThresh, d_duchsPeThresh, d_duchsPeriod, d_updatePE);
282  }
283 
284 
286  {
287  d_tx->start();
288  return true;
289  }
290 
292  {
293  // d_tx -- need Packetizer method to interrupt sub-threads
294  d_tx->stop();
295  return true;
296  }
297 
298  int DUCSink::sendFrames(int noutput_items, std::complex<float>* input_items)
299  {
300  // noutput_items = Number of outgoing VITA 49 frames requested
301  // input_items = Array of complex samples. It should have at least
302  // (noutput_items * SAMPLES_PER_FRAME) elements in it.
303  int noutput_items_processed = 0;
304  int sample;
305  int sample_input_item;
306  bool sending = true;
307  // If the transmit packetizer is ready to receive --
308  if ( (d_tx != NULL) && d_tx->isReadyToReceive() )
309  {
310  // While the packetizer stays ready to receive AND we can still
311  // process outgoing items:
312  while ( d_tx->isReadyToReceive() &&
313  sending &&
314  (noutput_items_processed < noutput_items) )
315  {
316  // Fill the sample buffer. Note that I/Q data is filled in reverse order --
317  // Q, then I.
318  for (sample = 0; sample < SAMPLES_PER_FRAME; sample++)
319  {
320  sample_input_item = noutput_items_processed * SAMPLES_PER_FRAME + sample;
321  d_sample_buffer[sample * 2] = (short)(input_items[sample_input_item].imag() * d_iq_scale_factor);
322  d_sample_buffer[sample * 2 + 1] = (short)(input_items[sample_input_item].real() * d_iq_scale_factor);
323  }
324  // Send data
325  int samplesSent = d_tx->sendFrame(d_sample_buffer);
326  if ( samplesSent > 0 )
327  noutput_items_processed++;
328  else
329  sending = false;
330  }
331  }
332  // If the packetizer wasn't connected at the start, go ahead and
333  // consume all of the input items so we don't block up anything
334  // supplying our input sample data.
335  else
336  {
337  noutput_items_processed = noutput_items;
338  }
339  return noutput_items_processed;
340  }
341 
343  const std::string& radio_host_name,
344  int radio_tcp_port,
345  const std::vector<std::string>& tengig_iface_list)
346  {
347  this->debug("setting radio parameters\n");
348  d_radio_host_name = radio_host_name;
349  d_radio_tcp_port = radio_tcp_port;
350  d_tengig_iface_list = tengig_iface_list;
351  set_duc_iface_index_from_string();
352  if ( d_tx != NULL )
353  {
354  d_tx->setRadioParameters(d_radio_host_name, d_radio_tcp_port);
355  d_tx->setDucInterface(d_duc_iface_string, d_duc_iface_index);
356  d_tx->setDucParameters(d_duc_iface_index, d_duc_rate_index,
357  d_duc_tx_channels, d_duc_frequency,
358  d_duc_attenuation, d_duc_tx_frequency,
359  d_duc_attenuation, d_duc_stream_id);
360  }
361  }
362 
363  void DUCSink::set_duc_iface_index_from_string()
364  {
365  d_duc_iface_index = 0;
366  for (int idx = 1; idx <= (int)d_tengig_iface_list.size(); idx++)
367  {
368  if ( d_tengig_iface_list[idx-1] == d_duc_iface_string )
369  {
370  d_duc_iface_index = idx;
371  break;
372  }
373  }
374  }
375 
376  } /* namespace NDR651 */
377 
378 } /* namespace CyberRadio */
379 
float get_iq_scale_factor() const
Gets the I/Q scale factor used for the radio.
Definition: DUCSink.cpp:119
bool setDucChannel(unsigned int ducChannel)
Sets the DUC channel number.
~DUCSink()
Destroys a DUCSink object.
Definition: DUCSink.cpp:97
void set_duc_tx_frequency(double duc_tx_frequency)
Sets the transmit center frequency (in MHz) for the DUC in use.
Definition: DUCSink.cpp:219
void set_iq_scale_factor(float iq_scale_factor)
Sets the I/Q scale factor used for the radio.
Definition: DUCSink.cpp:124
void set_duc_attenuation(float duc_attenuation)
Sets the attenuation for the DUC in use.
Definition: DUCSink.cpp:195
void set_duc_tx_attenuation(unsigned int duc_tx_attenuation)
Sets the transmit attenuation (in dB) for the DUC in use.
Definition: DUCSink.cpp:231
void set_duc_frequency(long duc_frequency)
Sets the frequency offset for the DUC in use.
Definition: DUCSink.cpp:176
bool setDucTxChannels(unsigned int ducTxChannels)
Sets the DUC transmit channel bitmap.
unsigned int get_duc_tx_attenuation() const
Gets the transmit attenuation (in dB) for the DUC in use.
Definition: DUCSink.cpp:226
bool setDucTxinvMode(unsigned int txinvMode)
Sets the DUC TX Inversion Mode.
DUCSink(const std::string &name="DUCSink", const std::string &radio_host_name="", unsigned int radio_tcp_port=8617, unsigned int tengig_iface_index=1, float iq_scale_factor=1.0, unsigned int duc_channel=1, const std::string &duc_iface_string="eth0", unsigned int duc_rate_index=0, long duc_frequency=0, float duc_attenuation=0, unsigned int duc_tx_channels=0, double duc_tx_frequency=900, unsigned int duc_tx_attenuation=0, unsigned int duc_stream_id=40001, bool config_tx=false, bool debug=false, unsigned int fc_update_rate=20, bool use_udp=false, bool use_ring_buffer=false, unsigned int duchsPfThresh=25, unsigned int duchsPeThresh=24, unsigned int duchsPeriod=10, bool updatePE=false, int txinv_mode=0)
Creates a DUCSink object.
Definition: DUCSink.cpp:27
bool setRadioParameters(const std::string &radioHostName, int radioTcpPort)
Sets the radio parameters.
Class that supports debug output.
Definition: Debuggable.h:38
void set_duc_tx_channels(unsigned int duc_tx_channels)
Sets the transmit channel mask for the DUC in use.
Definition: DUCSink.cpp:207
int get_duc_rate_index() const
Gets the rate index (zero-based) for the DUC in use.
Definition: DUCSink.cpp:159
bool setDucRate(unsigned int ducRate)
Sets the DUC rate index.
int get_duc_iface_index() const
Gets the interface index (one-based) for the DUC in use.
Definition: DUCSink.cpp:146
unsigned int get_duc_stream_id() const
Gets the VITA stream ID for the DUC.
Definition: DUCSink.cpp:238
void set_duc_txinv_mode(int duc_txinv_mode)
Sets the TX inversion mode for the DUC in use.
Definition: DUCSink.cpp:183
bool setDucInterface(const std::string &ifname, unsigned int tenGigIndex)
Sets the DUC interface parameters.
std::vector< std::string > get_tengig_iface_list() const
Gets the 10GigE interface list for the radio.
Definition: DUCSink.cpp:114
virtual int debug(const char *format,...)
Outputs debug information.
Definition: Debuggable.cpp:95
bool setTxFreq(double txFreq)
Sets the transmitter frequency.
unsigned int get_duc_tx_channels() const
Gets the transmit channel mask for the DUC in use.
Definition: DUCSink.cpp:202
void set_duc_channel(int duc_channel)
Sets the channel number for the DUC in use.
Definition: DUCSink.cpp:134
bool isReadyToReceive(void)
Gets whether or not the packetizer is ready to receive data.
int get_duc_channel() const
Gets the channel number for the DUC in use.
Definition: DUCSink.cpp:129
Defines functionality for LibCyberRadio applications.
Definition: App.h:23
bool setDucFreq(float ducFreq)
Sets the DUC frequency.
float get_duc_attenuation() const
Gets the attenuation for the DUC in use.
Definition: DUCSink.cpp:190
std::string get_duc_iface_string() const
Gets the interface name for the DUC in use.
Definition: DUCSink.cpp:141
std::string get_radio_host_name() const
Gets the radio host name.
Definition: DUCSink.cpp:104
int sendFrames(int noutput_items, std::complex< float > *input_items)
Sends a number of VITA 49 frames.
Definition: DUCSink.cpp:298
void set_radio_params(const std::string &radio_host_name, int radio_tcp_port, const std::vector< std::string > &tengig_iface_list)
Sets the radio parameters.
Definition: DUCSink.cpp:342
long get_duc_sample_rate() const
Gets the sample rate (in Hz) for the DUC in use, based on the rate index.
Definition: DUCSink.cpp:250
bool stop()
Stops the sink.
Definition: DUCSink.cpp:291
void set_duc_iface_string(const std::string &duc_iface_string)
Sets the interface name for the DUC in use.
Definition: DUCSink.cpp:151
bool setDucParameters(unsigned int tenGigIndex, unsigned int ducRate, unsigned int ducTxChannels, float ducFreq, float ducAtten, double txFreq, float txAtten, unsigned int streamId)
Sets the DUC parameters.
bool setTxAtten(float txAtten)
Sets the transmitter attenuation.
bool setDucAtten(float ducAtten)
Sets the DUC attenuation.
void set_duc_stream_id(unsigned int duc_stream_id)
Sets the VITA stream ID for the DUC.
Definition: DUCSink.cpp:243
long get_duc_frequency() const
Gets the frequency offset for the DUC in use.
Definition: DUCSink.cpp:171
bool setStreamId(unsigned int streamId)
Sets the stream ID.
double get_duc_tx_frequency() const
Gets the transmit center frequency (in MHz) for the DUC in use.
Definition: DUCSink.cpp:214
unsigned int sendFrame(short *samples)
Sends a number of samples as a VITA 49 frame.
int get_radio_tcp_port() const
Gets the radio TCP port.
Definition: DUCSink.cpp:109
bool start()
Starts the sink.
Definition: DUCSink.cpp:285
void set_duc_rate_index(int duc_rate_index)
Sets the rate index (zero-based) for the DUC in use.
Definition: DUCSink.cpp:164