mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-10-31 23:26:22 +00:00
Adding c2bits sample stream to UDP custom source
This commit is contained in:
parent
e484e73eca
commit
be2e5d8d5e
@ -30,6 +30,11 @@
|
|||||||
const int FIFO_SIZE = 1472000;
|
const int FIFO_SIZE = 1472000;
|
||||||
|
|
||||||
|
|
||||||
|
struct byte_2bit_struct
|
||||||
|
{
|
||||||
|
signed two_bit_sample : 2; // <- 2 bits wide only
|
||||||
|
};
|
||||||
|
|
||||||
/* 4 bytes IP address */
|
/* 4 bytes IP address */
|
||||||
typedef struct gr_ip_address
|
typedef struct gr_ip_address
|
||||||
{
|
{
|
||||||
@ -120,6 +125,11 @@ Gr_Complex_Ip_Packet_Source::Gr_Complex_Ip_Packet_Source(std::string src_device,
|
|||||||
d_wire_sample_type = 1;
|
d_wire_sample_type = 1;
|
||||||
d_bytes_per_sample = d_n_baseband_channels * 2;
|
d_bytes_per_sample = d_n_baseband_channels * 2;
|
||||||
}
|
}
|
||||||
|
else if (wire_sample_type == "c2bits")
|
||||||
|
{
|
||||||
|
d_wire_sample_type = 5;
|
||||||
|
d_bytes_per_sample = d_n_baseband_channels;
|
||||||
|
}
|
||||||
else if (wire_sample_type == "c4bits")
|
else if (wire_sample_type == "c4bits")
|
||||||
{
|
{
|
||||||
d_wire_sample_type = 2;
|
d_wire_sample_type = 2;
|
||||||
@ -183,7 +193,8 @@ bool Gr_Complex_Ip_Packet_Source::stop()
|
|||||||
bool Gr_Complex_Ip_Packet_Source::open()
|
bool Gr_Complex_Ip_Packet_Source::open()
|
||||||
{
|
{
|
||||||
std::array<char, PCAP_ERRBUF_SIZE> errbuf{};
|
std::array<char, PCAP_ERRBUF_SIZE> errbuf{};
|
||||||
boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
|
//boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
|
||||||
|
gr::thread::scoped_lock guard(d_setlock);
|
||||||
// open device for reading
|
// open device for reading
|
||||||
descr = pcap_open_live(d_src_device.c_str(), 1500, 1, 1000, errbuf.data());
|
descr = pcap_open_live(d_src_device.c_str(), 1500, 1, 1000, errbuf.data());
|
||||||
if (descr == nullptr)
|
if (descr == nullptr)
|
||||||
@ -239,7 +250,7 @@ void Gr_Complex_Ip_Packet_Source::static_pcap_callback(u_char *args, const struc
|
|||||||
void Gr_Complex_Ip_Packet_Source::pcap_callback(__attribute__((unused)) u_char *args, __attribute__((unused)) const struct pcap_pkthdr *pkthdr,
|
void Gr_Complex_Ip_Packet_Source::pcap_callback(__attribute__((unused)) u_char *args, __attribute__((unused)) const struct pcap_pkthdr *pkthdr,
|
||||||
const u_char *packet)
|
const u_char *packet)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
|
//boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
|
||||||
|
|
||||||
const gr_ip_header *ih;
|
const gr_ip_header *ih;
|
||||||
const gr_udp_header *uh;
|
const gr_udp_header *uh;
|
||||||
@ -321,107 +332,164 @@ void Gr_Complex_Ip_Packet_Source::my_pcap_loop_thread(pcap_t *pcap_handle)
|
|||||||
|
|
||||||
void Gr_Complex_Ip_Packet_Source::demux_samples(const gr_vector_void_star &output_items, int num_samples_readed)
|
void Gr_Complex_Ip_Packet_Source::demux_samples(const gr_vector_void_star &output_items, int num_samples_readed)
|
||||||
{
|
{
|
||||||
for (int n = 0; n < num_samples_readed; n++)
|
if (d_wire_sample_type == 5)
|
||||||
{
|
{
|
||||||
switch (d_wire_sample_type)
|
//interleaved 2-bit I 2-bit Q samples packed in bytes: 1 byte -> 2 complex samples
|
||||||
|
int nsample = 0;
|
||||||
|
byte_2bit_struct sample{}; // <- 2 bits wide only
|
||||||
|
int real;
|
||||||
|
int imag;
|
||||||
|
for (int nbyte = 0; nbyte < num_samples_readed / 2; nbyte++)
|
||||||
{
|
{
|
||||||
case 1: // interleaved byte samples
|
|
||||||
for (const auto &output_item : output_items)
|
for (const auto &output_item : output_items)
|
||||||
{
|
{
|
||||||
int8_t real;
|
// Read packed input sample (1 byte = 2 complex samples)
|
||||||
int8_t imag;
|
// * Packing Order
|
||||||
real = fifo_buff[fifo_read_ptr++];
|
// * Most Significant Nibble - Sample n
|
||||||
imag = fifo_buff[fifo_read_ptr++];
|
// * Least Significant Nibble - Sample n+1
|
||||||
|
// * Bit Packing order in Nibble Q1 Q0 I1 I0
|
||||||
|
// normal
|
||||||
|
int8_t c = fifo_buff[fifo_read_ptr++];
|
||||||
|
|
||||||
|
// Q[n]
|
||||||
|
sample.two_bit_sample = (c >> 6) & 3;
|
||||||
|
imag = (2 * static_cast<int8_t>(sample.two_bit_sample) + 1);
|
||||||
|
// I[n]
|
||||||
|
sample.two_bit_sample = (c >> 4) & 3;
|
||||||
|
real = (2 * static_cast<int8_t>(sample.two_bit_sample) + 1);
|
||||||
|
|
||||||
if (d_IQ_swap)
|
if (d_IQ_swap)
|
||||||
{
|
{
|
||||||
static_cast<gr_complex *>(output_item)[n] = gr_complex(real, imag);
|
static_cast<gr_complex *>(output_item)[nsample] = gr_complex(real, imag);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static_cast<gr_complex *>(output_item)[n] = gr_complex(imag, real);
|
static_cast<gr_complex *>(output_item)[nsample] = gr_complex(imag, real);
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2: // 4-bit samples
|
|
||||||
for (const auto &output_item : output_items)
|
|
||||||
{
|
|
||||||
int8_t real;
|
|
||||||
int8_t imag;
|
|
||||||
uint8_t tmp_char2;
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Q[n+1]
|
||||||
|
sample.two_bit_sample = (c >> 2) & 3;
|
||||||
|
imag = (2 * static_cast<int8_t>(sample.two_bit_sample) + 1);
|
||||||
|
// I[n+1]
|
||||||
|
sample.two_bit_sample = c & 3;
|
||||||
|
real = (2 * static_cast<int8_t>(sample.two_bit_sample) + 1);
|
||||||
|
|
||||||
if (d_IQ_swap)
|
if (d_IQ_swap)
|
||||||
{
|
{
|
||||||
static_cast<gr_complex *>(output_item)[n] = gr_complex(imag, real);
|
static_cast<gr_complex *>(output_item)[nsample + 1] = gr_complex(real, imag);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static_cast<gr_complex *>(output_item)[n] = gr_complex(real, imag);
|
static_cast<gr_complex *>(output_item)[nsample + 1] = gr_complex(imag, real);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case 3: // interleaved float samples
|
|
||||||
for (const auto &output_item : output_items)
|
|
||||||
{
|
|
||||||
float real;
|
|
||||||
float imag;
|
|
||||||
memcpy(&real, &fifo_buff[fifo_read_ptr], sizeof(real));
|
|
||||||
fifo_read_ptr += 4; // Four bytes in float
|
|
||||||
memcpy(&imag, &fifo_buff[fifo_read_ptr], sizeof(imag));
|
|
||||||
fifo_read_ptr += 4; // Four bytes in float
|
|
||||||
if (d_IQ_swap)
|
|
||||||
{
|
|
||||||
static_cast<gr_complex *>(output_item)[n] = gr_complex(real, imag);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static_cast<gr_complex *>(output_item)[n] = gr_complex(imag, real);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 4: // interleaved short samples
|
|
||||||
for (const auto &output_item : output_items)
|
|
||||||
{
|
|
||||||
int16_t real;
|
|
||||||
int16_t imag;
|
|
||||||
memcpy(&real, &fifo_buff[fifo_read_ptr], sizeof(real));
|
|
||||||
fifo_read_ptr += 2; // two bytes in short
|
|
||||||
memcpy(&imag, &fifo_buff[fifo_read_ptr], sizeof(imag));
|
|
||||||
fifo_read_ptr += 2; // two bytes in short
|
|
||||||
if (d_IQ_swap)
|
|
||||||
{
|
|
||||||
static_cast<gr_complex *>(output_item)[n] = gr_complex(real, imag);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static_cast<gr_complex *>(output_item)[n] = gr_complex(imag, real);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
std::cout << "Unknown wire sample type\n";
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
if (fifo_read_ptr == FIFO_SIZE)
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int n = 0; n < num_samples_readed; n++)
|
||||||
{
|
{
|
||||||
fifo_read_ptr = 0;
|
switch (d_wire_sample_type)
|
||||||
|
{
|
||||||
|
case 1: // interleaved byte samples
|
||||||
|
for (const auto &output_item : output_items)
|
||||||
|
{
|
||||||
|
int8_t real;
|
||||||
|
int8_t imag;
|
||||||
|
real = fifo_buff[fifo_read_ptr++];
|
||||||
|
imag = fifo_buff[fifo_read_ptr++];
|
||||||
|
if (d_IQ_swap)
|
||||||
|
{
|
||||||
|
static_cast<gr_complex *>(output_item)[n] = gr_complex(real, imag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_cast<gr_complex *>(output_item)[n] = gr_complex(imag, real);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: // 4-bit samples
|
||||||
|
for (const auto &output_item : output_items)
|
||||||
|
{
|
||||||
|
int8_t real;
|
||||||
|
int8_t imag;
|
||||||
|
uint8_t tmp_char2;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
static_cast<gr_complex *>(output_item)[n] = gr_complex(imag, real);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_cast<gr_complex *>(output_item)[n] = gr_complex(real, imag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3: // interleaved float samples
|
||||||
|
for (const auto &output_item : output_items)
|
||||||
|
{
|
||||||
|
float real;
|
||||||
|
float imag;
|
||||||
|
memcpy(&real, &fifo_buff[fifo_read_ptr], sizeof(real));
|
||||||
|
fifo_read_ptr += 4; // Four bytes in float
|
||||||
|
memcpy(&imag, &fifo_buff[fifo_read_ptr], sizeof(imag));
|
||||||
|
fifo_read_ptr += 4; // Four bytes in float
|
||||||
|
if (d_IQ_swap)
|
||||||
|
{
|
||||||
|
static_cast<gr_complex *>(output_item)[n] = gr_complex(real, imag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_cast<gr_complex *>(output_item)[n] = gr_complex(imag, real);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4: // interleaved short samples
|
||||||
|
for (const auto &output_item : output_items)
|
||||||
|
{
|
||||||
|
int16_t real;
|
||||||
|
int16_t imag;
|
||||||
|
memcpy(&real, &fifo_buff[fifo_read_ptr], sizeof(real));
|
||||||
|
fifo_read_ptr += 2; // two bytes in short
|
||||||
|
memcpy(&imag, &fifo_buff[fifo_read_ptr], sizeof(imag));
|
||||||
|
fifo_read_ptr += 2; // two bytes in short
|
||||||
|
if (d_IQ_swap)
|
||||||
|
{
|
||||||
|
static_cast<gr_complex *>(output_item)[n] = gr_complex(real, imag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_cast<gr_complex *>(output_item)[n] = gr_complex(imag, real);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
std::cout << "Unknown wire sample type\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
if (fifo_read_ptr == FIFO_SIZE)
|
||||||
|
{
|
||||||
|
fifo_read_ptr = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -432,7 +500,7 @@ int Gr_Complex_Ip_Packet_Source::work(int noutput_items,
|
|||||||
gr_vector_void_star &output_items)
|
gr_vector_void_star &output_items)
|
||||||
{
|
{
|
||||||
// send samples to next GNU Radio block
|
// send samples to next GNU Radio block
|
||||||
boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
|
//boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
|
||||||
if (fifo_items == 0)
|
if (fifo_items == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -446,21 +514,24 @@ int Gr_Complex_Ip_Packet_Source::work(int noutput_items,
|
|||||||
int num_samples_readed;
|
int num_samples_readed;
|
||||||
int bytes_requested;
|
int bytes_requested;
|
||||||
|
|
||||||
bytes_requested = noutput_items * d_bytes_per_sample;
|
bytes_requested = static_cast<int>(static_cast<float>(noutput_items) * d_bytes_per_sample);
|
||||||
if (bytes_requested < fifo_items)
|
if (bytes_requested < fifo_items)
|
||||||
{
|
{
|
||||||
num_samples_readed = noutput_items; // read all
|
num_samples_readed = noutput_items; // read all
|
||||||
|
// update fifo items
|
||||||
|
fifo_items = fifo_items - bytes_requested;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
num_samples_readed = fifo_items / d_bytes_per_sample; // read what we have
|
num_samples_readed = static_cast<int>(static_cast<float>(fifo_items) / d_bytes_per_sample); // read what we have
|
||||||
|
bytes_requested = fifo_items;
|
||||||
|
// update fifo items
|
||||||
|
fifo_items = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes_requested = num_samples_readed * d_bytes_per_sample;
|
|
||||||
// read all in a single loop
|
// read all in a single loop
|
||||||
demux_samples(output_items, num_samples_readed); // it also increases the fifo read pointer
|
demux_samples(output_items, num_samples_readed); // it also increases the fifo read pointer
|
||||||
// update fifo items
|
|
||||||
fifo_items = fifo_items - bytes_requested;
|
|
||||||
|
|
||||||
for (uint64_t n = 0; n < output_items.size(); n++)
|
for (uint64_t n = 0; n < output_items.size(); n++)
|
||||||
{
|
{
|
||||||
|
@ -83,7 +83,7 @@ private:
|
|||||||
bool open();
|
bool open();
|
||||||
|
|
||||||
boost::thread *d_pcap_thread;
|
boost::thread *d_pcap_thread;
|
||||||
boost::mutex d_mutex;
|
//boost::mutex d_mutex;
|
||||||
struct sockaddr_in si_me
|
struct sockaddr_in si_me
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@ -98,7 +98,7 @@ private:
|
|||||||
int d_udp_port;
|
int d_udp_port;
|
||||||
int d_n_baseband_channels;
|
int d_n_baseband_channels;
|
||||||
int d_wire_sample_type;
|
int d_wire_sample_type;
|
||||||
int d_bytes_per_sample;
|
float d_bytes_per_sample;
|
||||||
bool d_IQ_swap;
|
bool d_IQ_swap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user