11#include "LibCyberRadio/NDR651/TransmitPacketizer.h"
12#include <boost/algorithm/string.hpp>
13#include <boost/tokenizer.hpp>
16#define BOOL_DEBUG(x) (x ? "true" : "false")
18using namespace boost::algorithm;
21static unsigned short compute_checksum(
unsigned short *addr,
unsigned int count) {
22 register unsigned long sum = 0;
30 sum += ((*addr)&htons(0xFF00));
34 sum = (sum & 0xffff) + (sum >> 16);
38 return ((
unsigned short)sum);
41bool setCpuAffinity(
int cpu) {
45 if (sched_setaffinity(0,
sizeof(set), &set)) {
58 const std::string& radioHostName,
60 unsigned int ducChannel,
61 const std::string& ifname,
62 unsigned int tenGigIndex,
65 unsigned int ducTxChannels,
70 unsigned int streamId,
87 _config_tx(config_tx),
91 _frameStart((unsigned char*)(&_frame)),
101 _duchsPfThresh(61*(67108862/64)),
102 _duchsPeThresh(58*(67108862/64)),
104 _samplesPerFrame(SAMPLES_PER_FRAME),
112 this->
debug(
"construction\n");
113 std::cout <<
"using local lib" << std::endl;
114 memset(&_frame, 0,
sizeof(
TxFrame));
121 ducFreq, ducAtten, txFreq, txAtten,
123 _constructing =
false;
124 _delayTime.tv_sec = 0;
125 _delayTime.tv_nsec = 100;
133 this->
debug(
"destruction\n");
134 if ( _fcClient != NULL )
136 if ( _txSock != NULL )
153 this->
debug(
"setting duc channel = %d\n", ducChannel);
156 if ( (_txSock != NULL) && (_fcClient != NULL) )
159 _fcClient->disableDuc();
161 _fcClient->setDucChannel(ducChannel);
162 this->
debug(
"duc channel set ok\n");
166 this->
debug(
"duc channel set skipped\n");
168 _configuring =
false;
173 unsigned int tenGigIndex)
176 this->
debug(
"setting duc interface = %s/%d\n", ifname.c_str(),
180 if ( ifname != _ifname )
182 if ( _txSock != NULL ) {
188 for (
int i=0; i<_numSock; i++) {
191 std::cout <<
"# sockets = " << _txSockVec.size() << std::endl;
192 _currentSockIndex = 0;
193 _txSock = _txSockVec[_currentSockIndex];
195 _tenGigIndex = tenGigIndex;
196 this->
debug(
"duc interface set ok\n");
198 _ducFreq, _ducAtten, _txFreq,
199 _txAtten, _streamId);
207 if (_fcClient != NULL)
209 ret = _fcClient->setDucRateIndex(_ducRate,
true);
211 _configuring =
false;
219 _ducTxChannels = ducTxChannels;
220 if (_fcClient != NULL)
222 ret = _fcClient->setDucTxChannel(_ducTxChannels,
true);
224 _configuring =
false;
233 if (_fcClient != NULL)
235 ret = _fcClient->setDucFrequency((
long)_ducFreq,
true);
237 _configuring =
false;
245 _txinvMode = txinvMode;
246 if (_fcClient != NULL)
248 ret = _fcClient->setDucTxinvMode(txinvMode,
true);
250 _configuring =
false;
258 _ducAtten = ducAtten;
259 if (_fcClient != NULL)
261 ret = _fcClient->setDucAttenuation(_ducAtten,
true);
263 _configuring =
false;
268 void TransmitPacketizer::setDuchsParameters(
unsigned int duchsPfThresh,
unsigned int duchsPeThresh,
unsigned int duchsPeriod,
bool updatePE) {
270 if (_updatePE != updatePE) {
271 _updatePE = updatePE;
273 std::cerr <<
"setDuchsParameters: Updating on PE packet" << std::endl;
275 std::cerr <<
"setDuchsParameters: Updating on periodic packet" << std::endl;
277 _statusRx->setUpdatePE(_updatePE);
279 if (_duchsPfThresh != duchsPfThresh) {
280 std::cerr <<
"setDuchsParameters: Modify duchsPfThresh " << _duchsPfThresh <<
"->" << duchsPfThresh << std::endl;
281 _duchsPfThresh = duchsPfThresh;
284 if (_duchsPeThresh != duchsPeThresh) {
285 std::cerr <<
"setDuchsParameters: Modify duchsPeThresh " << _duchsPeThresh <<
"->" << duchsPeThresh << std::endl;
286 _duchsPeThresh = duchsPeThresh;
289 if (_duchsPeriod != duchsPeriod) {
290 std::cerr <<
"setDuchsParameters: Modify duchsPeriod " << _duchsPeriod <<
"->" << duchsPeriod << std::endl;
291 _duchsPeriod = duchsPeriod;
294 if (change && _running) {
295 _fcClient->setDuchsParameters(_duchsPfThresh, _duchsPeThresh, _duchsPeriod);
302 bool shfChange = (_txFreq != txFreq) && (((_txFreq >= 200.0)&&(txFreq < 200.0))||((_txFreq < 200.0)&&(txFreq >= 200.0)));
305 if (_fcClient != NULL)
314 ret = _fcClient->setTxFrequency(_txFreq,
true);
317 _configuring =
false;
326 if (_fcClient != NULL)
328 ret = _fcClient->setTxAttenuation((
int)_txAtten,
true);
330 _configuring =
false;
338 _streamId = streamId;
339 setUdpHeader(_streamId, _streamId);
340 setVitaHeader(_streamId);
341 if (_fcClient != NULL)
343 ret = _fcClient->setDucStreamId(_streamId,
true);
345 _configuring =
false;
356 const std::string& radioHostName,
360 this->
debug(
"setting radio parameters host=%s, port=%d\n",
361 radioHostName.c_str(), radioTcpPort);
364 if ( _fcClient != NULL )
370 if ( !_constructing )
374 if ( radioHostName != _radioHostName )
376 _fcClient->disableDuc();
380 if ( (radioHostName != _radioHostName) ||
381 (radioTcpPort != _radioTcpPort) )
383 _fcClient->disconnect();
387 _radioHostName = radioHostName;
388 _radioTcpPort = radioTcpPort;
390 if ( _radioHostName !=
"" )
391 _fcClient->connectToRadio(_radioHostName, _radioTcpPort);
392 this->
debug(
"radio parameters set result = %s\n",
393 BOOL_DEBUG(_fcClient->isConnected()));
397 this->
debug(
"radio parameters set skipped\n");
399 _configuring =
false;
404 unsigned int ducRate,
405 unsigned int ducTxChannels,
410 unsigned int streamId)
414 this->
debug(
"setting duc parameters index=%d\n", tenGigIndex);
415 _tenGigIndex = tenGigIndex;
417 _ducTxChannels = ducTxChannels;
419 _ducAtten = ducAtten;
422 _streamId = streamId;
423 this->
debug(
"-- ducRate=%u ducTxChannels=%d ducFreq=%f "
424 "ducAtten=%f txFreq=%f txAtten=%f streamId=%u\n",
425 _ducRate, _ducTxChannels, _ducFreq, _ducAtten,
426 _txFreq, _txAtten, _streamId);
429 if ( (_txSock != NULL) && (_fcClient != NULL) )
431 _sMac = _txSock->getMacAddress();
432 _sIp = _txSock->getIpAddress();
433 if (_txSock->isUsingRawSocket()) {
434 this->
debug(
"-- source mac = %s\n", _sMac.c_str());
435 _dMac = _fcClient->getRadioMac(tenGigIndex);
436 this->
debug(
"-- dest mac = %s\n", _dMac.c_str());
437 setEthernetHeader(_sMac, _dMac);
438 this->
debug(
"-- source ip = %s\n", _sIp.c_str());
439 _dIp = _fcClient->getRadioIp(tenGigIndex);
440 this->
debug(
"-- dest ip = %s\n", _dIp.c_str());
441 setIpHeader(_sIp, _dIp);
442 setUdpHeader(_streamId, _streamId);
444 _frameStart = (
unsigned char*)(&_frame.v49.frameStart);
445 _frameLength =
sizeof(
TxFrame)-(
sizeof(ethhdr) +
sizeof(iphdr) +
sizeof(udphdr) );
447 setVitaHeader(_streamId);
448 this->
debug(
"-- enabling duc\n");
449 ret = _fcClient->enableDuc(_ducRate, _ducTxChannels,
450 _streamId, _tenGigIndex,
453 (
unsigned int)_txAtten);
454 this->
debug(
"-- duc enable = %s\n", BOOL_DEBUG(ret));
458 this->
debug(
"duc parameters set skipped\n");
460 this->
debug(
"duc parameters set result = %s\n", BOOL_DEBUG(ret));
461 _configuring =
false;
470 _fcClient->setDucDipStatusEntry(-1, _sIp, _sMac, _statusRx->getUdpPort());
471 _statusRx->setUpdatePE(_updatePE);
472 _fcClient->setDuchsParameters(_duchsPfThresh, _duchsPeThresh, _duchsPeriod);
473 if ( _statusRx != NULL )
479 std::cerr <<
"Stopping flow control threads.\n";
480 this->setDuchsParameters(0, 0, 0,
false);
481 if ( _fcClient != NULL ) {
483 _fcClient->setDucTenGbePort(0,
false);
484 _fcClient->setDucRateIndex(0,
false);
485 _fcClient->setDucFrequency(0,
false);
486 _fcClient->setDucStreamId(0,
false);
487 _fcClient->setDucEnable(
false,
true);
491 if ( _statusRx != NULL ){
492 std::cerr <<
"_statusRx->interrupt()\n";
493 _statusRx->interrupt();
494 std::cerr <<
"delete _statusRx\n";
498 std::cerr <<
"Stopped flow control threads.\n";
506 if ( (_txSock != NULL) && (_fcClient != NULL) && (_statusRx != NULL) )
508 while (!_statusRx->okToSend(SAMPLES_PER_FRAME,
false))
512 memcpy(&_frame.payload.samples, samples, 4*SAMPLES_PER_FRAME);
513 if (_txSock->sendFrame(_frameStart, _frameLength))
515 _samplesSent = SAMPLES_PER_FRAME;
516 _incrementVitaHeader();
518 this->
debug(
"1st frame sent!\n");
523 _currentSockIndex = (_currentSockIndex+1)%_txSockVec.size();
524 _txSock = _txSockVec[_currentSockIndex];
525 _statusRx->sentNSamples(_samplesSent);
538 return ( (_fcClient != NULL) &&
539 _fcClient->isConnected() );
547 bool TransmitPacketizer::setEthernetHeader(
const std::string& sourceMac,
548 const std::string& destMac)
550 std::vector<std::string> macVec;
554 split(macVec, destMac, is_any_of(
":"));
557 for (std::vector<std::string>::iterator i=macVec.begin(); i!=macVec.end(); i++) {
558 unsigned char val = strtol((*i).c_str(), NULL, 16);
560 _frame.
eth.h_dest[ind++] = val;
565 split(macVec, sourceMac, is_any_of(
":"));
568 for (std::vector<std::string>::iterator i=macVec.begin(); i!=macVec.end(); i++) {
569 unsigned char val = strtol((*i).c_str(), NULL, 16);
571 _frame.
eth.h_source[ind++] = val;
575 _frame.
eth.h_proto = htons(ETH_P_IP);
580 bool TransmitPacketizer::setIpHeader(
const std::string& sourceIp,
581 const std::string& destIp)
583 _frame.ip.version = 4;
584 _frame.ip.ihl =
sizeof(iphdr)/4;
586 _frame.ip.protocol = 17;
587 _frame.ip.tot_len = htons(
sizeof(TxFrame)-
sizeof(ethhdr));
591 inet_pton(AF_INET, destIp.c_str(), &(_frame.ip.daddr));
594 inet_pton(AF_INET, sourceIp.c_str(), &(_frame.ip.saddr));
598 _frame.ip.check = compute_checksum((
unsigned short*)&(_frame.ip), _frame.ip.ihl<<2);
603 bool TransmitPacketizer::setUdpHeader(
unsigned short sourcePort,
604 unsigned short destPort)
606 _frame.udp.source = htons(sourcePort);
607 _frame.udp.dest = htons(destPort);
608 _frame.udp.len = htons(
sizeof(TxFrame)-
sizeof(ethhdr)-
sizeof(iphdr));
612 bool TransmitPacketizer::setVitaHeader(
unsigned int streamId)
615 _frame.v49.frameStart = VRLP;
617 _frame.v49.frameSize = _samplesPerFrame+10;
618 _frame.v49.streamId = streamId;
619 _frame.v49.packetType = 0x1;
620 _frame.v49.TSF = 0x1;
621 _frame.v49.TSF = 0x1;
624 _frame.v49.classId1 = 0x00fffffa;
625 _frame.v49.classId2 = 0x00130000;
627 _frame.v49.packetSize = _samplesPerFrame+7;
628 _frame.vend.frameEnd = VEND;
638 void TransmitPacketizer::_incrementVitaHeader()
643 _frame.v49.frameCount = (_frame.v49.frameCount + 1) % 4096;
644 _frame.v49.packetCount = (_frame.v49.packetCount + 1) % 16;
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.
Flow control client class.
bool setDucFreq(float ducFreq)
Sets the DUC frequency.
unsigned int sendFrame(short *samples)
Sends a number of samples as a VITA 49 frame.
bool setDebug(bool debug)
Sets whether or not to produce debug output.
bool setRadioHostName(const std::string &radioHostName)
Sets the radio host name.
bool setTxFreq(double txFreq)
Sets the transmitter frequency.
bool isConnected(void)
Gets whether or not the packetizer is connected.
bool setDucRate(unsigned int ducRate)
Sets the DUC rate index.
void start()
Starts the packetizer.
TransmitPacketizer(const std::string &radioHostName="", int radioTcpPort=8617, unsigned int ducChannel=1, const std::string &ifname="eth0", unsigned int tenGigIndex=1, int dipIndex=-1, unsigned int ducRate=0, unsigned int ducTxChannels=0, float ducFreq=900e6, float ducAtten=0, double txFreq=900, float txAtten=0, unsigned int streamId=40001, bool config_tx=false, bool debug=false)
Constructs a TransmitPacketizer object.
virtual ~TransmitPacketizer()
Destroys a TransmitPacketizer object.
bool setStreamId(unsigned int streamId)
Sets the stream ID.
void stop()
Stops the packetizer.
bool setRadioTcpPort(int radioTcpPort)
Sets the radio TCP port.
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 setDucInterface(const std::string &ifname, unsigned int tenGigIndex)
Sets the DUC interface parameters.
bool setRadioParameters(const std::string &radioHostName, int radioTcpPort)
Sets the radio parameters.
bool setTxAtten(float txAtten)
Sets the transmitter attenuation.
bool isReadyToReceive(void)
Gets whether or not the packetizer is ready to receive data.
bool setDucChannel(unsigned int ducChannel)
Sets the DUC channel number.
bool setDucTxinvMode(unsigned int txinvMode)
Sets the DUC TX Inversion Mode.
bool setDucAtten(float ducAtten)
Sets the DUC attenuation.
bool setDucTxChannels(unsigned int ducTxChannels)
Sets the DUC transmit channel bitmap.
Provides programming elements for controlling the CyberRadio Solutions NDR651 radio.
Defines functionality for LibCyberRadio applications.
VITA 49 transmit-over-UDP frame information.
struct ethhdr eth
Ethernet header.