From be2e5d8d5e495665f0d4519d6299df9a5b63b8cf Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Fri, 9 Jun 2023 14:09:18 +0200 Subject: [PATCH] Adding c2bits sample stream to UDP custom source --- .../gr_complex_ip_packet_source.cc | 251 +++++++++++------- .../gr_complex_ip_packet_source.h | 4 +- 2 files changed, 163 insertions(+), 92 deletions(-) diff --git a/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.cc b/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.cc index 6cead4e46..20f829e6a 100644 --- a/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.cc +++ b/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.cc @@ -30,6 +30,11 @@ const int FIFO_SIZE = 1472000; +struct byte_2bit_struct +{ + signed two_bit_sample : 2; // <- 2 bits wide only +}; + /* 4 bytes 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_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") { d_wire_sample_type = 2; @@ -183,7 +193,8 @@ bool Gr_Complex_Ip_Packet_Source::stop() bool Gr_Complex_Ip_Packet_Source::open() { std::array 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 descr = pcap_open_live(d_src_device.c_str(), 1500, 1, 1000, errbuf.data()); 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, 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_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) { - 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) { - int8_t real; - int8_t imag; - real = fifo_buff[fifo_read_ptr++]; - imag = fifo_buff[fifo_read_ptr++]; + // Read packed input sample (1 byte = 2 complex samples) + // * Packing Order + // * Most Significant Nibble - Sample n + // * 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(sample.two_bit_sample) + 1); + // I[n] + sample.two_bit_sample = (c >> 4) & 3; + real = (2 * static_cast(sample.two_bit_sample) + 1); + if (d_IQ_swap) { - static_cast(output_item)[n] = gr_complex(real, imag); + static_cast(output_item)[nsample] = gr_complex(real, imag); } else { - static_cast(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; + static_cast(output_item)[nsample] = gr_complex(imag, real); } + + + // Q[n+1] + sample.two_bit_sample = (c >> 2) & 3; + imag = (2 * static_cast(sample.two_bit_sample) + 1); + // I[n+1] + sample.two_bit_sample = c & 3; + real = (2 * static_cast(sample.two_bit_sample) + 1); + if (d_IQ_swap) { - static_cast(output_item)[n] = gr_complex(imag, real); + static_cast(output_item)[nsample + 1] = gr_complex(real, imag); } else { - static_cast(output_item)[n] = gr_complex(real, imag); + static_cast(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(output_item)[n] = gr_complex(real, imag); - } - else - { - static_cast(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(output_item)[n] = gr_complex(real, imag); - } - else - { - static_cast(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(output_item)[n] = gr_complex(real, imag); + } + else + { + static_cast(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(output_item)[n] = gr_complex(imag, real); + } + else + { + static_cast(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(output_item)[n] = gr_complex(real, imag); + } + else + { + static_cast(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(output_item)[n] = gr_complex(real, imag); + } + else + { + static_cast(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) { // 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) { return 0; @@ -446,21 +514,24 @@ int Gr_Complex_Ip_Packet_Source::work(int noutput_items, int num_samples_readed; int bytes_requested; - bytes_requested = noutput_items * d_bytes_per_sample; + bytes_requested = static_cast(static_cast(noutput_items) * d_bytes_per_sample); if (bytes_requested < fifo_items) { num_samples_readed = noutput_items; // read all + // update fifo items + fifo_items = fifo_items - bytes_requested; } else { - num_samples_readed = fifo_items / d_bytes_per_sample; // read what we have + num_samples_readed = static_cast(static_cast(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 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++) { diff --git a/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.h b/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.h index c24ee5417..9f8939904 100644 --- a/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.h +++ b/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.h @@ -83,7 +83,7 @@ private: bool open(); boost::thread *d_pcap_thread; - boost::mutex d_mutex; + //boost::mutex d_mutex; struct sockaddr_in si_me { }; @@ -98,7 +98,7 @@ private: int d_udp_port; int d_n_baseband_channels; int d_wire_sample_type; - int d_bytes_per_sample; + float d_bytes_per_sample; bool d_IQ_swap; };