libcyberradio 22.01.24
Packetizer.cpp
1#include "LibCyberRadio/NDR651/Packetizer.h"
2
3namespace 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}
Provides programming elements for controlling the CyberRadio Solutions NDR651 radio.
Defines functionality for LibCyberRadio applications.
Definition App.h:24
VITA 49 frame header information.
Definition PacketTypes.h:39
uint32_t timeSeconds
Timestamp integer field.
Definition PacketTypes.h:65
uint32_t frameStart
Frame start word (ASCII string "VRLP")
Definition PacketTypes.h:40
uint16_t T
Frame trailer present indicator.
Definition PacketTypes.h:48
uint32_t timeFracSecLSB
Timestamp fractional field, LSW.
Definition PacketTypes.h:67
uint16_t TSF
Timestamp fractional field format.
Definition PacketTypes.h:45
uint32_t timeFracSecMSB
Timestamp fractional field, MSW.
Definition PacketTypes.h:66
uint32_t classId1
Class ID Field Part 1.
Definition PacketTypes.h:57
uint16_t C
Class ID field present indicator.
Definition PacketTypes.h:49
uint32_t frameSize
Frame size, in 32-bit words.
Definition PacketTypes.h:41
uint16_t packetCount
Packet counter.
Definition PacketTypes.h:44
uint32_t frameCount
Frame Count.
Definition PacketTypes.h:42
uint16_t packetSize
Packet size, in 32-bit words.
Definition PacketTypes.h:43
uint16_t packetType
Packet type.
Definition PacketTypes.h:50
uint32_t classId2
Class ID Field Part 2.
Definition PacketTypes.h:64
VITA 49 frame trailer information.
Definition PacketTypes.h:80
uint32_t frameEnd
Frame end word (ASCII string "VEND")
Definition PacketTypes.h:81