libcyberradio  22.01.24
VitaIqSource.cpp
1 /* -*- c++ -*- */
2 /***************************************************************************
3  * \file VitaIqSource.cpp
4  *
5  * \brief Implementation of a generic VITA 49-compatible I/Q data source
6  * block.
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/Common/VitaIqSource.h"
17 #include <iostream>
18 
19 namespace LibCyberRadio
20 {
21  VitaIqSource::VitaIqSource(const std::string& name,
22  int vita_type,
23  size_t payload_size,
24  size_t vita_header_size,
25  size_t vita_tail_size,
26  bool byte_swapped,
27  bool iq_swapped,
28  const std::string& host,
29  unsigned short port,
30  bool debug) :
31  Debuggable(debug, name),
32  d_name(name),
33  d_vita_type(vita_type),
34  d_payload_size(payload_size),
35  d_vita_header_size(vita_header_size),
36  d_vita_tail_size(vita_tail_size),
37  d_byte_swapped(byte_swapped),
38  d_iq_swapped(iq_swapped),
39  d_host(host),
40  d_port(port),
41  d_packet_size(0)
42  {
43  this->debug("construction\n");
44  // Determine packet size
45  d_packet_size = (vita_type == 0 ? payload_size : vita_header_size + payload_size + vita_tail_size);
46  // Create UDP port for collecting data
47  this->debug(" -- Packet Size: %d\n", d_packet_size);
48  connect_udp_port();
49  }
50 
51  /*
52  * Our virtual destructor.
53  */
55  {
56  this->debug("destruction\n");
57  // Destroy/disconnect UDP port for collecting data
58  disconnect_udp_port();
59  }
60 
61  int VitaIqSource::getPackets(int noutput_items, Vita49PacketVector& output_items)
62  {
63  int noutput_items_processed = 0;
64  bool got_data_on_loop = false;
65  // Check to see if the UDP port is available for reading
66  if ( d_udp_port_mtx.try_lock() )
67  {
68  // Get as many packets as we can, up to the maximum number requested.
69  do
70  {
71  got_data_on_loop = false;
72  // Get data from UDP port if it's available
73  d_udp_port->read_data();
74  if ( d_udp_port->is_packet_ready() )
75  {
76  // Handle disposition of the new packet object depending on whether or not
77  // the output vector has been pre-allocated
78  if ( noutput_items_processed < (int)output_items.size() )
79  {
80  output_items[noutput_items_processed] = Vita49Packet(
81  d_vita_type,
82  d_payload_size,
83  d_vita_header_size,
84  d_vita_tail_size,
85  d_byte_swapped,
86  d_iq_swapped,
87  (unsigned char*)(d_udp_port->recv_buffer),
88  d_packet_size);
89  }
90  else
91  {
92  output_items.push_back( Vita49Packet(
93  d_vita_type,
94  d_payload_size,
95  d_vita_header_size,
96  d_vita_tail_size,
97  d_byte_swapped,
98  d_iq_swapped,
99  (unsigned char*)(d_udp_port->recv_buffer),
100  d_packet_size) );
101  }
102  // Increment the items processed counter
103  noutput_items_processed++;
104  // Reset the UDP port buffer
105  d_udp_port->clear_buffer();
106  // Set the got data on loop flag
107  got_data_on_loop = true;
108  }
109  } while ( got_data_on_loop && (noutput_items_processed < noutput_items) );
110  d_udp_port_mtx.unlock();
111  }
112  return noutput_items_processed;
113  }
114 
115  int VitaIqSource::getPacketsPayloadData(int noutput_items, void * buffer)
116  {
117  int noutput_items_processed = 0;
118  bool got_data_on_loop = false;
119  // Check to see if the UDP port is available for reading
120  if ( d_udp_port_mtx.try_lock() )
121  {
122  // Get as many packets as we can, up to the maximum number requested.
123  do
124  {
125  got_data_on_loop = false;
126  // Get data from UDP port if it's available
127  d_udp_port->read_data();
128  if ( d_udp_port->is_packet_ready() )
129  {
130  Vita49Packet temp = Vita49Packet(
131  d_vita_type,
132  d_payload_size,
133  d_vita_header_size,
134  d_vita_tail_size,
135  d_byte_swapped,
136  d_iq_swapped,
137  (unsigned char*)(d_udp_port->recv_buffer),
138  d_packet_size);
139  //std::cout << temp.timestampFrac << std::endl;
140  std::memcpy(buffer, temp.sampleData, d_payload_size);
141  // Increment the items processed counter
142  noutput_items_processed++;
143  // Reset the UDP port buffer
144  d_udp_port->clear_buffer();
145  // Set the got data on loop flag
146  got_data_on_loop = true;
147  }
148  } while ( got_data_on_loop && (noutput_items_processed < noutput_items) );
149  d_udp_port_mtx.unlock();
150  }
151  return noutput_items_processed;
152  }
153 
155  {
156  return d_packet_size;
157  }
158 
160  {
161  return d_byte_swapped;
162  }
163 
165  {
166  return d_iq_swapped;
167  }
168 
170  {
171  return d_payload_size;
172  }
173 
175  {
176  return d_vita_header_size;
177  }
178 
180  {
181  return d_vita_tail_size;
182  }
183 
185  {
186  return d_vita_type;
187  }
188 
189  void VitaIqSource::recalc_packet_size()
190  {
191  // Determine packet size
192  d_packet_size = (d_vita_type == 0 ? d_payload_size :
193  d_vita_header_size + d_payload_size + d_vita_tail_size);
194  // Reconnect the UDP port
195  disconnect_udp_port();
196  connect_udp_port();
197  }
198 
199  void VitaIqSource::connect_udp_port()
200  {
201  d_udp_port_mtx.lock();
202  // Create UDP port for collecting data
203  this->debug("connect udp %s/%d\n", d_host.c_str(), d_port);
204  d_udp_port = new VitaIqUdpPort(d_host, d_port, d_packet_size, isDebug());
205  this->debug("-- connect result: %d\n", d_udp_port->connected);
206  d_udp_port_mtx.unlock();
207  }
208 
209  void VitaIqSource::disconnect_udp_port()
210  {
211  d_udp_port_mtx.lock();
212  // Destroy UDP port for collecting data
213  this->debug("disconnect udp %s/%d\n", d_host.c_str(), d_port);
214  delete d_udp_port;
215  d_udp_port = NULL;
216  d_udp_port_mtx.unlock();
217  }
218 
219 
220 } /* namespace LibCyberRadio */
221 
virtual int getPacketSize() const
Gets the VITA 49 or I/Q packet size.
size_t getPayloadSize() const
Gets the payload size.
virtual ~VitaIqSource()
Destroys a vita_iq_source object.
Class that supports debug output.
Definition: Debuggable.h:38
int getVitaType() const
Gets the VITA type.
size_t getVitaHeaderSize() const
Gets the VITA 49 frame header size.
virtual int debug(const char *format,...)
Outputs debug information.
Definition: Debuggable.cpp:95
bool isIqSwapped() const
Gets the I/Q-swapping state.
Defines functionality for LibCyberRadio applications.
Definition: App.h:23
VitaIqSource(const std::string &name="VitaIqSource", int vita_type=0, size_t payload_size=8192, size_t vita_header_size=0, size_t vita_tail_size=0, bool byte_swapped=false, bool iq_swapped=false, const std::string &host="0.0.0.0", unsigned short port=0, bool debug=false)
Creates a VitaIqSource object.
bool isByteSwapped() const
Gets the byte-swapping state.
size_t getVitaTailSize() const
Gets the VITA 49 frame trailer size.
virtual int getPacketsPayloadData(int noutput_items, void *buff)
Gets VITA 49 or I/Q data packets.
virtual int getPackets(int noutput_items, Vita49PacketVector &output_items)
Gets VITA 49 or I/Q data packets.
virtual bool isDebug() const
Gets whether this object produces debug output.
Definition: Debuggable.cpp:133
Decodes a VITA 49 or I/Q data packet.
Definition: Vita49Packet.h:37