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
23namespace 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
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
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
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
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
virtual int debug(const char *format,...)
Outputs debug information.
Debuggable(bool debug=false, const std::string &debug_name="", FILE *debug_fp=DEBUG_FP, const std::string &debug_timefmt=DEBUG_TIME_FMT)
Constructs a Debuggable object.
float get_duc_attenuation() const
Gets the attenuation for the DUC in use.
Definition DUCSink.cpp:190
int get_radio_tcp_port() const
Gets the radio TCP port.
Definition DUCSink.cpp:109
void set_duc_attenuation(float duc_attenuation)
Sets the attenuation for the DUC in use.
Definition DUCSink.cpp:195
void set_duc_frequency(long duc_frequency)
Sets the frequency offset for the DUC in use.
Definition DUCSink.cpp:176
unsigned int get_duc_stream_id() const
Gets the VITA stream ID for the DUC.
Definition DUCSink.cpp:238
int get_duc_channel() const
Gets the channel number for the DUC in use.
Definition DUCSink.cpp:129
void set_duc_rate_index(int duc_rate_index)
Sets the rate index (zero-based) for the DUC in use.
Definition DUCSink.cpp:164
long get_duc_frequency() const
Gets the frequency offset for the DUC in use.
Definition DUCSink.cpp:171
void set_iq_scale_factor(float iq_scale_factor)
Sets the I/Q scale factor used for the radio.
Definition DUCSink.cpp:124
~DUCSink()
Destroys a DUCSink object.
Definition DUCSink.cpp:97
std::string get_radio_host_name() const
Gets the radio host name.
Definition DUCSink.cpp:104
bool stop()
Stops the sink.
Definition DUCSink.cpp:291
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
void set_duc_iface_string(const std::string &duc_iface_string)
Sets the interface name for the DUC in use.
Definition DUCSink.cpp:151
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
unsigned int get_duc_tx_attenuation() const
Gets the transmit attenuation (in dB) for the DUC in use.
Definition DUCSink.cpp:226
unsigned int get_duc_tx_channels() const
Gets the transmit channel mask for the DUC in use.
Definition DUCSink.cpp:202
void set_duc_tx_channels(unsigned int duc_tx_channels)
Sets the transmit channel mask for the DUC in use.
Definition DUCSink.cpp:207
float get_iq_scale_factor() const
Gets the I/Q scale factor used for the radio.
Definition DUCSink.cpp:119
void set_duc_stream_id(unsigned int duc_stream_id)
Sets the VITA stream ID for the DUC.
Definition DUCSink.cpp:243
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
bool start()
Starts the sink.
Definition DUCSink.cpp:285
double get_duc_tx_frequency() const
Gets the transmit center frequency (in MHz) for the DUC in use.
Definition DUCSink.cpp:214
void set_duc_txinv_mode(int duc_txinv_mode)
Sets the TX inversion mode for the DUC in use.
Definition DUCSink.cpp:183
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
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
int get_duc_iface_index() const
Gets the interface index (one-based) for the DUC in use.
Definition DUCSink.cpp:146
int sendFrames(int noutput_items, std::complex< float > *input_items)
Sends a number of VITA 49 frames.
Definition DUCSink.cpp:298
int get_duc_rate_index() const
Gets the rate index (zero-based) for the DUC in use.
Definition DUCSink.cpp:159
void set_duc_channel(int duc_channel)
Sets the channel number for the DUC in use.
Definition DUCSink.cpp:134
std::vector< std::string > get_tengig_iface_list() const
Gets the 10GigE interface list for the radio.
Definition DUCSink.cpp:114
std::string get_duc_iface_string() const
Gets the interface name for the DUC in use.
Definition DUCSink.cpp:141
Provides programming elements for controlling the CyberRadio Solutions NDR651 radio.
Defines functionality for LibCyberRadio applications.
Definition App.h:24