1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-06-14 01:06:51 +00:00

Optimizing custom UDP packet source and applying code style

This commit is contained in:
Javier Arribas 2018-05-16 10:49:27 +02:00
parent bde6bd6cee
commit df0dd82843
8 changed files with 789 additions and 144 deletions

View File

@ -6,23 +6,25 @@
;######### GLOBAL OPTIONS ##################
;internal_fs_sps: Internal signal sampling frequency after the signal conditioning stage [Sps].
;GNSS-SDR.internal_fs_sps=3312500
GNSS-SDR.internal_fs_sps=2650000
GNSS-SDR.internal_fs_sps=13250000 ;//66.25/5
;GNSS-SDR.internal_fs_sps=6625000 ;//66.25/10
;GNSS-SDR.internal_fs_sps=3312500 ;//66.25/20
;GNSS-SDR.internal_fs_sps=2650000 ;//66.25/25
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=UDP_Signal_Source
;SignalSource.implementation=File_Signal_Source
SignalSource.filename=/home/javier/gnss/gnss-simulator/build/signal_out.bin ; <- PUT YOUR FILE HERE
;SignalSource.filename=/home/javier/gnss/gnss-simulator/build/signal_out.bin ; <- PUT YOUR FILE HERE
SignalSource.item_type=gr_complex
SignalSource.origin_address=0.0.0.0
SignalSource.capture_device=eth0
SignalSource.port=1234
SignalSource.payload_bytes=1472
SignalSource.sample_type=cbyte
;SignalSource.sample_type=cbyte
SignalSource.sample_type=c4bits
SignalSource.IQ_swap=false
SignalSource.RF_channels=1
SignalSource.select_single_channel=0
SignalSource.channels_in_udp=2
SignalSource.IQ_swap=true
SignalSource.dump=false
SignalSource.dump_filename=./signal_source.dat
@ -33,12 +35,22 @@ SignalConditioner.implementation=Pass_Through
;SignalConditioner1.implementation=Pass_Through
;######### CHANNELS GLOBAL CONFIG ############
Channels_1C.count=1
Channels_1C.count=8
Channels.in_acquisition=1
;# CHANNEL CONNECTION
Channel.signal=1C
;Channel0.RF_channel_ID=0
Channel0.RF_channel_ID=0
Channel1.RF_channel_ID=0
Channel2.RF_channel_ID=0
Channel3.RF_channel_ID=0
Channel4.RF_channel_ID=0
Channel5.RF_channel_ID=0
Channel6.RF_channel_ID=0
Channel7.RF_channel_ID=0
Channel8.RF_channel_ID=1
Channel9.RF_channel_ID=1
;Channel0.signal=1C
;Channel1.RF_channel_ID=1
;Channel1.signal=1C
@ -46,11 +58,11 @@ Channel.signal=1C
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.item_type=gr_complex
Acquisition_1C.threshold=60
Acquisition_1C.threshold=17
Acquisition_1C.use_CFAR_algorithm=false
Acquisition_1C.blocking=false
Acquisition_1C.doppler_max=5000
Acquisition_1C.doppler_step=500
Acquisition_1C.doppler_step=250
Acquisition_1C.dump=false
Acquisition_1C.dump_filename=./acq_dump.dat
@ -78,7 +90,7 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=Single ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100

View File

@ -1,13 +1,12 @@
/*!
* \file rtl_tcp_signal_source.cc
* \brief Signal source for the Realtek RTL2832U USB dongle DVB-T receiver
* over TCP.
* (see http://sdr.osmocom.org/trac/wiki/rtl-sdr for more information)
* \author Anthony Arnold, 2015. anthony.arnold(at)uqconnect.edu.au
* \file udp_signal_source.cc
*
* \brief Receives ip frames containing samples in UDP frame encapsulation
* using a high performance packet capture library (libpcap)
* \author Javier Arribas jarribas (at) cttc.es
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -30,6 +29,7 @@
* -------------------------------------------------------------------------
*/
#include "udp_signal_source.h"
#include "configuration_interface.h"
#include "GPS_L1_CA.h"
@ -64,58 +64,46 @@ UDPSignalSource::UDPSignalSource(ConfigurationInterface* configuration,
RF_channels_ = configuration->property(role + ".RF_channels", 1);
select_single_channel_ = configuration->property(role + ".select_single_channel", 0);
channels_in_udp_= configuration->property(role + ".channels_in_udp", 1);
IQ_swap_= configuration->property(role + ".IQ_swap", false);
channels_in_udp_ = configuration->property(role + ".channels_in_udp", 1);
IQ_swap_ = configuration->property(role + ".IQ_swap", false);
std::string default_sample_type = "cbyte";
std::string sample_type = configuration->property(role + ".sample_type", default_sample_type);
item_type_ = configuration->property(role + ".item_type", default_item_type);
if (sample_type.compare("cbyte")==0)
{
udp_gnss_rx_source_ = raw_ip_packet_source::make(capture_device, address, port, payload_bytes);
demux_=gr::blocks::deinterleave::make(sizeof(char),1);
}else{
std::cout<<"WARNING: Requested UDP sample type unsuported, setting sample type to cbyte\n";
udp_gnss_rx_source_ = raw_ip_packet_source::make(capture_device, address, port, payload_bytes);
demux_=gr::blocks::deinterleave::make(sizeof(char),1);
}
//create I, Q -> gr_complex type conversion blocks
for (int n = 0; n < (channels_in_udp_ * 2); n++)
{
char_to_float_.push_back(gr::blocks::char_to_float::make());
}
for (int n = 0; n < channels_in_udp_; n++)
{
float_to_complex_.push_back(gr::blocks::float_to_complex::make());
}
if (channels_in_udp_>RF_channels_)
{
for (int n = 0; n < channels_in_udp_; n++)
{
null_sinks_.push_back(gr::blocks::null_sink::make(sizeof(gr_complex)));
}
}else
{
std::cout<<"Configuration error: RF_channels<channels_in_use"<<std::endl;
exit(0);
}
//output item size is always gr_complex
item_size_ = sizeof(gr_complex);
udp_gnss_rx_source_ = gr_complex_ip_packet_source::make(capture_device,
address,
port,
payload_bytes,
channels_in_udp_,
sample_type,
item_size_,
IQ_swap_);
if (channels_in_udp_ >= RF_channels_)
{
for (int n = 0; n < channels_in_udp_; n++)
{
null_sinks_.push_back(gr::blocks::null_sink::make(sizeof(gr_complex)));
}
}
else
{
std::cout << "Configuration error: RF_channels<channels_in_use" << std::endl;
exit(0);
}
if (dump_)
{
for (int n = 0; n < channels_in_udp_; n++)
{
DLOG(INFO) << "Dumping output into file " << (dump_filename_+"c_h"+std::to_string(n)+".bin");
file_sink_.push_back(gr::blocks::file_sink::make(item_size_, (dump_filename_+"_ch"+std::to_string(n)+".bin").c_str()));
}
{
DLOG(INFO) << "Dumping output into file " << (dump_filename_ + "c_h" + std::to_string(n) + ".bin");
file_sink_.push_back(gr::blocks::file_sink::make(item_size_, (dump_filename_ + "_ch" + std::to_string(n) + ".bin").c_str()));
}
}
}
@ -126,92 +114,40 @@ UDPSignalSource::~UDPSignalSource()
void UDPSignalSource::connect(gr::top_block_sptr top_block)
{
top_block->connect(udp_gnss_rx_source_,0, demux_,0);
DLOG(INFO)<<"connected udp_source to demux"<<std::endl;
for (int n = 0; n < (channels_in_udp_ * 2); n++)
{
top_block->connect(demux_, n, char_to_float_.at(n), 0);
DLOG(INFO) << "connected demux to char_to_float CH" << n;
}
//connect null sinks to unused streams
for (int n = 0; n < channels_in_udp_; n++)
{
if (!IQ_swap_)
{
top_block->connect(char_to_float_.at(n * 2), 0, float_to_complex_.at(n), 0);
top_block->connect(char_to_float_.at(n * 2 + 1), 0, float_to_complex_.at(n), 1);
}
else
{
top_block->connect(char_to_float_.at(n * 2), 0, float_to_complex_.at(n), 1);
top_block->connect(char_to_float_.at(n * 2 + 1), 0, float_to_complex_.at(n), 0);
}
DLOG(INFO) << "connected char_to_float to float_to_complex_ CH" << n;
top_block->connect(udp_gnss_rx_source_, n, null_sinks_.at(n), 0);
}
//connect null sinks to unused streams
if (channels_in_udp_>RF_channels_)
{
for (int n = 0; n < channels_in_udp_; n++)
{
top_block->connect(float_to_complex_.at(n),0,null_sinks_.at(n),0);
}
}
DLOG(INFO) << "connected udp_source to null_sinks to enable the use of spare channels" << std::endl;
if (dump_)
{
for (int n = 0; n < channels_in_udp_; n++)
{
top_block->connect(float_to_complex_.at(n), 0, file_sink_.at(n), 0);
DLOG(INFO) << "connected source to file sink";
}
{
top_block->connect(udp_gnss_rx_source_, n, file_sink_.at(n), 0);
DLOG(INFO) << "connected source to file sink";
}
}
}
void UDPSignalSource::disconnect(gr::top_block_sptr top_block)
{
for (int n = 0; n < (channels_in_udp_ * 2); n++)
{
top_block->disconnect(demux_, n, char_to_float_.at(n), 0);
DLOG(INFO) << "disconnect demux to char_to_float CH" << n;
}
//disconnect null sinks to unused streams
for (int n = 0; n < channels_in_udp_; n++)
{
if (!IQ_swap_)
{
top_block->disconnect(char_to_float_.at(n * 2), 0, float_to_complex_.at(n), 0);
top_block->disconnect(char_to_float_.at(n * 2 + 1), 0, float_to_complex_.at(n), 1);
}
else
{
top_block->disconnect(char_to_float_.at(n * 2), 0, float_to_complex_.at(n), 1);
top_block->disconnect(char_to_float_.at(n * 2 + 1), 0, float_to_complex_.at(n), 0);
}
DLOG(INFO) << "disconnect char_to_float to float_to_complex_ CH" << n;
top_block->disconnect(udp_gnss_rx_source_, n, null_sinks_.at(n), 0);
}
//disconnect null sinks to unused streams
if (channels_in_udp_>RF_channels_)
{
for (int n = 0; n < channels_in_udp_; n++)
{
top_block->disconnect(float_to_complex_.at(n),0,null_sinks_.at(n),0);
}
}
if (dump_)
{
for (int n = 0; n < channels_in_udp_; n++)
{
top_block->disconnect(float_to_complex_.at(n), 0, file_sink_.at(n), 0);
DLOG(INFO) << "disconnected source to file sink";
for (int n = 0; n < channels_in_udp_; n++)
{
top_block->disconnect(udp_gnss_rx_source_, n, file_sink_.at(n), 0);
DLOG(INFO) << "disconnected source to file sink";
}
}
}
top_block->disconnect(udp_gnss_rx_source_,0, demux_,0);
DLOG(INFO)<<"disconnected udp_source to demux"<<std::endl;
DLOG(INFO) << "disconnected udp_source" << std::endl;
}
@ -224,11 +160,10 @@ gr::basic_block_sptr UDPSignalSource::get_left_block()
gr::basic_block_sptr UDPSignalSource::get_right_block()
{
return get_right_block(select_single_channel_);
return udp_gnss_rx_source_;
}
gr::basic_block_sptr UDPSignalSource::get_right_block(int RF_channel)
{
return float_to_complex_.at(RF_channel);
return udp_gnss_rx_source_;
}

View File

@ -1,12 +1,12 @@
/*!
* \file rtl_tcp_signal_source.h
* \brief Signal source which reads from rtl_tcp.
* (see http://sdr.osmocom.org/trac/wiki/rtl-sdr for more information)
* \author Anthony Arnold, 2015. anthony.arnold(at)uqconnect.edu.au
* \file udp_signal_source.h
*
* \brief Receives ip frames containing samples in UDP frame encapsulation
* using a high performance packet capture library (libpcap)
* \author Javier Arribas jarribas (at) cttc.es
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -29,18 +29,16 @@
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_UDP_SIGNAL_SOURCE_H
#define GNSS_SDR_UDP_SIGNAL_SOURCE_H
#include "gnss_block_interface.h"
#include "raw_ip_packet_source.h"
#include "gr_complex_ip_packet_source.h"
#include <boost/shared_ptr.hpp>
#include <gnuradio/msg_queue.h>
#include <gnuradio/blocks/char_to_float.h>
#include <gnuradio/blocks/file_sink.h>
#include <gnuradio/blocks/null_sink.h>
#include <gnuradio/blocks/deinterleave.h>
#include <gnuradio/blocks/float_to_complex.h>
#include <stdexcept>
#include <string>
#include <vector>
@ -90,7 +88,6 @@ private:
bool IQ_swap_;
int RF_channels_;
int select_single_channel_;
int channels_in_udp_;
unsigned int in_stream_;
unsigned int out_stream_;
@ -99,12 +96,8 @@ private:
size_t item_size_;
bool dump_;
std::string dump_filename_;
std::vector<boost::shared_ptr<gr::block>> char_to_float_;
std::vector<boost::shared_ptr<gr::block>> float_to_complex_;
std::vector<boost::shared_ptr<gr::block>> null_sinks_;
raw_ip_packet_source::sptr udp_gnss_rx_source_;
gr::blocks::deinterleave::sptr demux_;
gr_complex_ip_packet_source::sptr udp_gnss_rx_source_;
std::vector<boost::shared_ptr<gr::block>> file_sink_;
boost::shared_ptr<gr::msg_queue> queue_;
};

View File

@ -20,12 +20,14 @@
set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
unpack_byte_2bit_samples.cc
unpack_byte_2bit_cpx_samples.cc
unpack_byte_4bit_samples.cc
unpack_intspir_1bit_samples.cc
rtl_tcp_signal_source_c.cc
unpack_2bit_samples.cc
unpack_spir_gss6450_samples.cc
labsat23_source.cc
raw_ip_packet_source.cc
gr_complex_ip_packet_source.cc
)
include_directories(

View File

@ -0,0 +1,439 @@
/*!
* \file gr_complex_ip_packet_source.cc
*
* \brief Receives ip frames containing samples in UDP frame encapsulation
* using a high performance packet capture library (libpcap)
* \author Javier Arribas jarribas (at) cttc.es
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include <gnuradio/io_signature.h>
#include "gr_complex_ip_packet_source.h"
#include <string.h>
#include <stdlib.h>
#define FIFO_SIZE 1472000
/* 4 bytes IP address */
typedef struct gr_ip_address
{
u_char byte1;
u_char byte2;
u_char byte3;
u_char byte4;
} gr_ip_address;
/* IPv4 header */
typedef struct gr_ip_header
{
u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits)
u_char tos; // Type of service
u_short tlen; // Total length
u_short identification; // Identification
u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
u_char ttl; // Time to live
u_char proto; // Protocol
u_short crc; // Header checksum
gr_ip_address saddr; // Source address
gr_ip_address daddr; // Destination address
u_int op_pad; // Option + Padding
} gr_ip_header;
/* UDP header*/
typedef struct gr_udp_header
{
u_short sport; // Source port
u_short dport; // Destination port
u_short len; // Datagram length
u_short crc; // Checksum
} gr_udp_header;
gr_complex_ip_packet_source::sptr
gr_complex_ip_packet_source::make(std::string src_device,
std::string origin_address,
int udp_port,
int udp_packet_size,
int n_baseband_channels,
std::string wire_sample_type,
size_t item_size,
bool IQ_swap_)
{
return gnuradio::get_initial_sptr(new gr_complex_ip_packet_source(src_device,
origin_address,
udp_port,
udp_packet_size,
n_baseband_channels,
wire_sample_type,
item_size,
IQ_swap_));
}
/*
* The private constructor
*/
gr_complex_ip_packet_source::gr_complex_ip_packet_source(std::string src_device,
__attribute__((unused)) std::string origin_address,
int udp_port,
int udp_packet_size,
int n_baseband_channels,
std::string wire_sample_type,
size_t item_size,
bool IQ_swap_)
: gr::sync_block("gr_complex_ip_packet_source",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(1, 4, item_size)) //1 to 4 baseband complex channels
{
// constructor code here
std::cout << "Start Ethernet packet capture\n";
d_n_baseband_channels = n_baseband_channels;
if (wire_sample_type.compare("cbyte") == 0)
{
d_wire_sample_type = 1;
d_bytes_per_sample = d_n_baseband_channels * 2;
}
else if (wire_sample_type.compare("c4bits") == 0)
{
d_wire_sample_type = 2;
d_bytes_per_sample = d_n_baseband_channels;
}
else
{
std::cout << "Unknown wire sample type\n";
exit(0);
}
std::cout << "d_wire_sample_type:" << d_wire_sample_type << std::endl;
d_src_device = src_device;
d_udp_port = udp_port;
d_udp_payload_size = udp_packet_size;
d_fifo_full = false;
//allocate signal samples buffer
fifo_buff = new char[FIFO_SIZE];
fifo_read_ptr = 0;
fifo_write_ptr = 0;
fifo_items = 0;
d_item_size = item_size;
d_IQ_swap = IQ_swap_;
d_sock_raw = 0;
d_pcap_thread = NULL;
descr = NULL;
}
//Called by gnuradio to enable drivers, etc for i/o devices.
bool gr_complex_ip_packet_source::start()
{
std::cout << "gr_complex_ip_packet_source START\n";
//open the ethernet device
if (open() == true)
{
// start pcap capture thread
d_pcap_thread = new boost::thread(boost::bind(&gr_complex_ip_packet_source::my_pcap_loop_thread, this, descr));
return true;
}
else
{
return false;
}
}
//Called by gnuradio to disable drivers, etc for i/o devices.
bool gr_complex_ip_packet_source::stop()
{
std::cout << "gr_complex_ip_packet_source STOP\n";
if (descr != NULL)
{
pcap_breakloop(descr);
d_pcap_thread->join();
pcap_close(descr);
}
return true;
}
bool gr_complex_ip_packet_source::open()
{
char errbuf[PCAP_ERRBUF_SIZE];
boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
/* open device for reading */
descr = pcap_open_live(d_src_device.c_str(), 1500, 1, 1000, errbuf);
if (descr == NULL)
{
std::cout << "Error openning Ethernet device " << d_src_device << std::endl;
printf("Fatal Error in pcap_open_live(): %s\n", errbuf);
return false;
}
//bind UDP port to avoid automatic reply with ICMP port ureacheable packets from kernel
d_sock_raw = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (d_sock_raw == -1)
{
std::cout << "Error openning UDP socket" << std::endl;
return false;
}
// zero out the structure
memset((char *)&si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(d_udp_port);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
//bind socket to port
if (bind(d_sock_raw, (struct sockaddr *)&si_me, sizeof(si_me)) == -1)
{
std::cout << "Error openning UDP socket" << std::endl;
return false;
}
return true;
}
gr_complex_ip_packet_source::~gr_complex_ip_packet_source()
{
if (d_pcap_thread != NULL)
{
delete d_pcap_thread;
}
delete fifo_buff;
std::cout << "Stop Ethernet packet capture\n";
}
void gr_complex_ip_packet_source::static_pcap_callback(u_char *args, const struct pcap_pkthdr *pkthdr,
const u_char *packet)
{
gr_complex_ip_packet_source *bridge = (gr_complex_ip_packet_source *)args;
bridge->pcap_callback(args, pkthdr, packet);
}
void gr_complex_ip_packet_source::pcap_callback(__attribute__((unused)) u_char *args, __attribute__((unused)) const struct pcap_pkthdr *pkthdr,
const u_char *packet)
{
boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
gr_ip_header *ih;
gr_udp_header *uh;
// eth frame parameters
// **** UDP RAW PACKET DECODER ****
if ((packet[12] == 0x08) & (packet[13] == 0x00)) //IP FRAME
{
/* retireve the position of the ip header */
ih = (gr_ip_header *)(packet +
14); //length of ethernet header
/* retireve the position of the udp header */
u_int ip_len;
ip_len = (ih->ver_ihl & 0xf) * 4;
uh = (gr_udp_header *)((u_char *)ih + ip_len);
/* convert from network byte order to host byte order */
//u_short sport;
u_short dport;
dport = ntohs(uh->dport);
//sport = ntohs(uh->sport);
if (dport == d_udp_port)
{
// print ip addresses and udp ports
// printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d\n",
// ih->saddr.byte1,
// ih->saddr.byte2,
// ih->saddr.byte3,
// ih->saddr.byte4,
// sport,
// ih->daddr.byte1,
// ih->daddr.byte2,
// ih->daddr.byte3,
// ih->daddr.byte4,
// dport);
// std::cout<<"uh->len:"<<ntohs(uh->len)<<std::endl;
int payload_lenght_bytes = ntohs(uh->len) - 8; //total udp packet lenght minus the header lenght
//read the payload bytes and insert them into the shared circular buffer
u_char *udp_payload = ((u_char *)uh + sizeof(gr_udp_header));
if (fifo_items <= (FIFO_SIZE - payload_lenght_bytes))
{
int aligned_write_items = FIFO_SIZE - fifo_write_ptr;
if (aligned_write_items >= payload_lenght_bytes)
{
//write all in a single memcpy
memcpy(&fifo_buff[fifo_write_ptr], &udp_payload[0], payload_lenght_bytes); //size in bytes
fifo_write_ptr += payload_lenght_bytes;
if (fifo_write_ptr == FIFO_SIZE) fifo_write_ptr = 0;
fifo_items += payload_lenght_bytes;
}
else
{
//two step wrap write
memcpy(&fifo_buff[fifo_write_ptr], &udp_payload[0], aligned_write_items); //size in bytes
fifo_write_ptr = payload_lenght_bytes - aligned_write_items;
memcpy(&fifo_buff[0], &udp_payload[aligned_write_items], fifo_write_ptr); //size in bytes
fifo_items += payload_lenght_bytes;
}
}
else
{
//notify overflow
std::cout << "O" << std::flush;
}
}
}
}
void gr_complex_ip_packet_source::my_pcap_loop_thread(pcap_t *pcap_handle)
{
pcap_loop(pcap_handle, -1, gr_complex_ip_packet_source::static_pcap_callback, (u_char *)this);
}
void gr_complex_ip_packet_source::demux_samples(gr_vector_void_star output_items, int num_samples_readed)
{
int8_t real;
int8_t imag;
uint8_t tmp_char2;
for (int n = 0; n < num_samples_readed; n++)
{
switch (d_wire_sample_type)
{
case 1: //interleaved byte samples
for (int i = 0; i < output_items.size(); i++)
{
real = fifo_buff[fifo_read_ptr++];
imag = fifo_buff[fifo_read_ptr++];
if (d_IQ_swap)
{
((gr_complex *)output_items[i])[n] = gr_complex(real, imag);
}
else
{
((gr_complex *)output_items[i])[n] = gr_complex(imag, real);
}
}
break;
case 2: // 4bits samples
for (int i = 0; i < output_items.size(); i++)
{
tmp_char2 = fifo_buff[fifo_read_ptr] & 0x0F;
if (tmp_char2 >= 8)
{
real = 2 * (tmp_char2 - 16) + 1;
}
else
{
real = 2 * tmp_char2 + 1;
}
tmp_char2 = fifo_buff[fifo_read_ptr++] >> 4;
tmp_char2 = tmp_char2 & 0x0F;
if (tmp_char2 >= 8)
{
imag = 2 * (tmp_char2 - 16) + 1;
}
else
{
imag = 2 * tmp_char2 + 1;
}
if (d_IQ_swap)
{
((gr_complex *)output_items[i])[n] = gr_complex(imag, real);
}
else
{
((gr_complex *)output_items[i])[n] = gr_complex(real, imag);
}
}
break;
default:
std::cout << "Unknown wire sample type\n";
exit(0);
}
if (fifo_read_ptr == FIFO_SIZE) fifo_read_ptr = 0;
}
}
int gr_complex_ip_packet_source::work(int noutput_items,
__attribute__((unused)) gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
// send samples to next GNU Radio block
boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
if (fifo_items == 0) return 0;
if (output_items.size() > d_n_baseband_channels)
{
std::cout << "Configuration error: more baseband channels connected than the available in the UDP source\n";
exit(0);
}
int num_samples_readed;
int bytes_requested;
switch (d_wire_sample_type)
{
case 1: //complex byte samples
bytes_requested = noutput_items * d_bytes_per_sample;
if (bytes_requested < fifo_items)
{
num_samples_readed = noutput_items; //read all
}
else
{
num_samples_readed = fifo_items / d_bytes_per_sample; //read what we have
}
break;
case 2: //complex 4 bits samples
bytes_requested = noutput_items * d_bytes_per_sample;
if (bytes_requested < fifo_items)
{
num_samples_readed = noutput_items; //read all
}
else
{
num_samples_readed = fifo_items / d_bytes_per_sample; //read what we have
}
break;
default: //complex byte samples
bytes_requested = noutput_items * d_bytes_per_sample;
if (bytes_requested < fifo_items)
{
num_samples_readed = noutput_items; //read all
}
else
{
num_samples_readed = fifo_items / d_bytes_per_sample; //read what we have
}
}
bytes_requested = num_samples_readed * d_bytes_per_sample;
//read all in a single loop
demux_samples(output_items, num_samples_readed); // it also increases the fifo read pointer
//update fifo items
fifo_items = fifo_items - bytes_requested;
for (int n = 0; n < output_items.size(); n++)
{
produce(n, num_samples_readed);
}
return this->WORK_CALLED_PRODUCE;
}

View File

@ -0,0 +1,117 @@
/*!
* \file gr_complex_ip_packet_source.h
*
* \brief Receives ip frames containing samples in UDP frame encapsulation
* using a high performance packet capture library (libpcap)
* \author Javier Arribas jarribas (at) cttc.es
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef INCLUDED_GR_COMPLEX_IP_PACKET_SOURCE_H
#define INCLUDED_GR_COMPLEX_IP_PACKET_SOURCE_H
#include <gnuradio/sync_block.h>
#include <boost/thread.hpp>
#include <pcap.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <netinet/if_ether.h>
#include <sys/ioctl.h>
class gr_complex_ip_packet_source : virtual public gr::sync_block
{
private:
boost::mutex d_mutex;
pcap_t *descr; //ethernet pcap device descriptor
char *fifo_buff;
int fifo_read_ptr;
int fifo_write_ptr;
int fifo_items;
int d_sock_raw;
int d_udp_port;
struct sockaddr_in si_me;
std::string d_src_device;
std::string d_origin_address;
int d_udp_payload_size;
bool d_fifo_full;
int d_n_baseband_channels;
int d_wire_sample_type;
int d_bytes_per_sample;
size_t d_item_size;
bool d_IQ_swap;
boost::thread *d_pcap_thread;
/*!
* \brief
* Opens the ethernet device using libpcap raw capture mode
* If any of these fail, the fuction retuns the error and exits.
*/
bool open();
void demux_samples(gr_vector_void_star output_items, int num_samples_readed);
void my_pcap_loop_thread(pcap_t *pcap_handle);
void pcap_callback(u_char *args, const struct pcap_pkthdr *pkthdr, const u_char *packet);
static void static_pcap_callback(u_char *args, const struct pcap_pkthdr *pkthdr, const u_char *packet);
public:
typedef boost::shared_ptr<gr_complex_ip_packet_source> sptr;
static sptr make(std::string src_device,
std::string origin_address,
int udp_port,
int udp_packet_size,
int n_baseband_channels,
std::string wire_sample_type,
size_t item_size,
bool IQ_swap_);
gr_complex_ip_packet_source(std::string src_device,
std::string origin_address,
int udp_port,
int udp_packet_size,
int n_baseband_channels,
std::string wire_sample_type,
size_t item_size,
bool IQ_swap_);
~gr_complex_ip_packet_source();
// Where all the action really happens
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
//Called by gnuradio to enable drivers, etc for i/o devices.
bool start();
//Called by gnuradio to disable drivers, etc for i/o devices.
bool stop();
};
#endif /* INCLUDED_GR_COMPLEX_IP_PACKET_SOURCE_H */

View File

@ -0,0 +1,86 @@
/*!
* \file unpack_byte_4bit_samples.cc
*
* \brief Unpacks byte samples to 4 bits samples.
* Packing Order
* Packing order in Nibble I0 I1 I2 I3 I0 I1 I2 I3
* \author Javier Arribas jarribas (at) cttc.es
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "unpack_byte_4bit_samples.h"
#include <gnuradio/io_signature.h>
unpack_byte_4bit_samples_sptr make_unpack_byte_4bit_samples()
{
return unpack_byte_4bit_samples_sptr(new unpack_byte_4bit_samples());
}
unpack_byte_4bit_samples::unpack_byte_4bit_samples() : sync_interpolator("unpack_byte_4bit_samples",
gr::io_signature::make(1, 1, sizeof(signed char)),
gr::io_signature::make(1, 1, sizeof(signed char)),
2)
{
}
unpack_byte_4bit_samples::~unpack_byte_4bit_samples()
{
}
int unpack_byte_4bit_samples::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const signed char *in = reinterpret_cast<const signed char *>(input_items[0]);
signed char *out = reinterpret_cast<signed char *>(output_items[0]);
int n = 0;
unsigned char tmp_char2;
for (int i = 0; i < noutput_items / 2; i++)
{
tmp_char2 = in[i] & 0x0F;
if (tmp_char2 >= 8)
{
out[n++] = 2 * (tmp_char2 - 16) + 1;
}
else
{
out[n++] = 2 * tmp_char2 + 1;
}
tmp_char2 = in[i] >> 4;
tmp_char2 = tmp_char2 & 0x0F;
if (tmp_char2 >= 8)
{
out[n++] = 2 * (tmp_char2 - 16) + 1;
}
else
{
out[n++] = 2 * tmp_char2 + 1;
}
}
return noutput_items;
}

View File

@ -0,0 +1,61 @@
/*!
* \file unpack_byte_4bit_samples.h
*
* \brief Unpacks byte samples to 4 bits samples.
* Packing Order
* Packing order in Nibble I0 I1 I2 I3 I0 I1 I2 I3
* \author Javier Arribas jarribas (at) cttc.es
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_unpack_byte_4bit_samples_H
#define GNSS_SDR_unpack_byte_4bit_samples_H
#include <gnuradio/sync_interpolator.h>
class unpack_byte_4bit_samples;
typedef boost::shared_ptr<unpack_byte_4bit_samples> unpack_byte_4bit_samples_sptr;
unpack_byte_4bit_samples_sptr make_unpack_byte_4bit_samples();
/*!
* \brief This class implements conversion between byte packet samples to 4bit_cpx samples
* 1 byte = 1 x complex 4bit I, + 4bit Q samples
*/
class unpack_byte_4bit_samples : public gr::sync_interpolator
{
private:
friend unpack_byte_4bit_samples_sptr make_unpack_byte_4bit_samples_sptr();
public:
unpack_byte_4bit_samples();
~unpack_byte_4bit_samples();
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
#endif