libcyberradio  22.01.24
Packetizer.cpp
1 #include "LibCyberRadio/NDR651/Packetizer.h"
2 
3 namespace LibCyberRadio
4 {
5  namespace NDR651
6  {
7  // Constructor
8  Packetizer::Packetizer(const std::string &txInterfaceName, unsigned short txUdpPort, unsigned int ducRateIndex, bool debug) :
9  Debuggable(debug, "Packetizer"),
10  txInterfaceName(txInterfaceName),
11  txUdpPort(txUdpPort),
12  samplesPerFrame(1024),
13  sampleRate(calculateSampleRate(ducRateIndex)),
14  txSocket(-1),
15  fracTimestampIncrement(2048)
16  {
17 
18  // An IO Vector is used to handle transmitting the header, payload, and footer consisely.
19  // Vita Header
20  this->txVec[0].iov_base = new char[sizeof(struct LibCyberRadio::NDR651::Vita49Header)];
21  this->txVec[0].iov_len = sizeof(struct LibCyberRadio::NDR651::Vita49Header);
22  // Sample Payload
23  this->txVec[1].iov_base = NULL;
24  this->txVec[1].iov_len = 0;
25  // Vita Footer
26  this->txVec[2].iov_base = new char[sizeof(struct LibCyberRadio::NDR651::Vita49Trailer)];
27  this->txVec[2].iov_len = sizeof(struct LibCyberRadio::NDR651::Vita49Trailer);
28 
29  }
30 
31  // Destructor
32  Packetizer::~Packetizer()
33  {
34  if (this->txSocket >= 0)
35  {
36  close(this->txSocket);
37  }
38 
39  // Free txVec
40  if (this->txVec[0].iov_base != NULL)
41  {
42  delete [] (char *)(this->txVec[0].iov_base);
43  }
44  if (this->txVec[2].iov_base != NULL)
45  {
46  delete [] (char *)(this->txVec[2].iov_base);
47  }
48 
49  this->debug("Exiting Packetizer\n");
50  }
51 
52  /* Public */
53  // 1) Sends a frame
54  // 2) Increments Vita Headers
55  void Packetizer::sendFrame(short * samples)
56  {
57  if (this->txSocket >= 0)
58  {
59  // Set out txVec to point to the current samples
60  this->txVec[1].iov_base = (char *)(samples);
61  this->txVec[1].iov_len = 4*(this->samplesPerFrame);
62  int bytesSent = writev(this->txSocket, this->txVec, 3);
63  this->incrementVitaHeader();
64  }
65  }
66 
67  void Packetizer::setSamplesPerFrame(unsigned int samplesPerFrame){
68  this->samplesPerFrame = samplesPerFrame;
69  this->setVitaHeader(this->txUdpPort);
70 
71  }
72 
73  void Packetizer::start()
74  {
75  this->debug("Starting the Packetizer\n");
76  this->initBroadcastTxSocket(txInterfaceName, txUdpPort);
77  this->setVitaHeader(txUdpPort);
78  }
79 
80  int Packetizer::getSocketFd()
81  {
82  return this->txSocket;
83  }
84 
85  /* Private */
86  void Packetizer::setVitaHeader(unsigned short streamId)
87  {
88  // Determine sampleCount
89  this->fracTimestampIncrement = ((unsigned long long)(DAC_RATE) / (this->sampleRate * 2)) * (this->samplesPerFrame*2);
90 
91  //Vita49
92  struct LibCyberRadio::NDR651::Vita49Header *hdr = (struct LibCyberRadio::NDR651::Vita49Header *)(this->txVec[0].iov_base);
93  struct LibCyberRadio::NDR651::Vita49Trailer *ftr = (struct LibCyberRadio::NDR651::Vita49Trailer *)(this->txVec[2].iov_base);
94  hdr->frameStart = VRLP;
95  hdr->frameSize = this->samplesPerFrame+10;
96  hdr->streamId = streamId;
97  hdr->packetType = 0x1;
98  hdr->TSF = 0x1;
99  hdr->TSF = 0x1;
100  hdr->T = 0;
101  hdr->C = 1;
102  hdr->classId1 = 0x00fffffa;
103  hdr->classId2 = 0x00130000;
104  hdr->packetSize = this->samplesPerFrame+7;
105  hdr->timeSeconds = 0;
106  hdr->timeFracSecMSB = 0;
107  hdr->timeFracSecLSB = 0;
108  ftr->frameEnd = VEND;
109  }
110 
111  void Packetizer::incrementVitaHeader()
112  {
113  struct LibCyberRadio::NDR651::Vita49Header *hdr = (struct LibCyberRadio::NDR651::Vita49Header *)(this->txVec[0].iov_base);
114  hdr->frameCount = (hdr->frameCount + 1) % 4*(this->samplesPerFrame);
115  hdr->packetCount = (hdr->packetCount + 1) % 16;
116 
117  if ((hdr->timeFracSecLSB + this->fracTimestampIncrement) >= DAC_RATE)
118  {
119  hdr->timeSeconds++;
120  }
121  hdr->timeFracSecLSB = (hdr->timeFracSecLSB + this->fracTimestampIncrement) % DAC_RATE;
122  }
123 
124  void Packetizer::initBroadcastTxSocket(const std::string &txInterfaceName, unsigned short port)
125  {
126  // Used for both setsockopt and connect
127  int rv;
128 
129  // Create a generic UDP Socket
130  int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
131  if (sockfd < 0)
132  {
133  perror("");
134  throw std::runtime_error("Could not create socket");
135  }
136 
137  // Set the socket to broadcast mode
138  int optval = 1;
139  rv = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void *)&optval, sizeof(int) );
140  if (rv != 0)
141  {
142  perror("");
143  throw std::runtime_error("Could not set broadcast sockopt");
144  }
145 
146  // Determine the broadcast IP (x.x.x.255) of the interface
147  struct ifreq ifr;
148  struct ifaddrs *ifap, *ifa;
149  struct sockaddr_in *sa;
150  char *addr;
151  std::string retString;
152  getifaddrs (&ifap);
153  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
154  if ( strcmp(ifa->ifa_name,txInterfaceName.c_str())==0 ){
155  if (ifa->ifa_addr->sa_family==AF_INET) {
156  sa = (struct sockaddr_in *) ifa->ifa_ifu.ifu_broadaddr;
157  sa->sin_port = htons(port);
158  addr = inet_ntoa(sa->sin_addr);
159  break;
160  }
161  }
162  }
163  freeifaddrs(ifap);
164 
165  // Connect to the broadcast address (you cant't REALLY connect to a UDP socket, but it does allow us to call send instead of sendto)
166  rv = connect(sockfd, (struct sockaddr *)sa, sizeof(sockaddr_in));
167  if (rv != 0)
168  {
169  perror("");
170  throw std::runtime_error("Could not call connect on the UDP socket");
171  }
172 
173  // Success
174  this->txSocket = sockfd;
175 
176  }
177 
178  unsigned long long Packetizer::calculateSampleRate(unsigned int ducRateIndex)
179  {
180  switch(ducRateIndex) {
181  case 0:
182  return 102400000;
183  case 1:
184  return 51200000;
185  case 2:
186  return 25600000;
187  case 3:
188  return 12800000;
189  case 4:
190  return 6400000;
191  case 5:
192  return 3200000;
193  case 6:
194  return 1600000;
195  case 7:
196  return 800000;
197  case 8:
198  return 400000;
199  case 9:
200  return 200000;
201  case 10:
202  return 100000;
203  case 11:
204  return 50000;
205  case 12:
206  return 25000;
207  case 13:
208  return 12500;
209  default:
210  return 0;
211  }
212 
213  }
214 
215  }
216 }
uint16_t packetSize
Packet size, in 32-bit words.
Definition: PacketTypes.h:43
uint32_t timeSeconds
Timestamp integer field.
Definition: PacketTypes.h:65
uint32_t timeFracSecMSB
Timestamp fractional field, MSW.
Definition: PacketTypes.h:66
uint16_t packetType
Packet type.
Definition: PacketTypes.h:50
uint32_t frameCount
Frame Count.
Definition: PacketTypes.h:42
uint32_t classId1
Class ID Field Part 1.
Definition: PacketTypes.h:57
VITA 49 frame header information.
Definition: PacketTypes.h:39
uint16_t packetCount
Packet counter.
Definition: PacketTypes.h:44
uint16_t TSF
Timestamp fractional field format.
Definition: PacketTypes.h:45
Defines functionality for LibCyberRadio applications.
Definition: App.h:23
uint16_t C
Class ID field present indicator.
Definition: PacketTypes.h:49
uint32_t frameEnd
Frame end word (ASCII string "VEND")
Definition: PacketTypes.h:81
uint32_t frameSize
Frame size, in 32-bit words.
Definition: PacketTypes.h:41
uint32_t frameStart
Frame start word (ASCII string "VRLP")
Definition: PacketTypes.h:40
uint32_t classId2
Class ID Field Part 2.
Definition: PacketTypes.h:64
uint16_t T
Frame trailer present indicator.
Definition: PacketTypes.h:48
uint32_t timeFracSecLSB
Timestamp fractional field, LSW.
Definition: PacketTypes.h:67
VITA 49 frame trailer information.
Definition: PacketTypes.h:80