Tuesday, March 24, 2020

Re: MPSK SNR Estimation block shifts input by one

Dear Marcus,

thank you very much for your reply. Please see my comments inline.

On 24.03.20 16:38, Marcus Müller wrote:
> Really quick answer:
>
> // at least 1 estimator has to look back
> set_history(2);
I totally forgot about the history feature. That makes a lot of sense
and explains the leading zero. Plus it helps to restore my sanity :)

>
> i.e. "works as designed"; whether that is "works as intended" is up for
> discussion.

I would argue that the SNR Estimation block should skip the first
history()-1 input samples, such that the blocks output becomes exactly
the input without any shift.

The corresponding doc comment in
https://github.com/gnuradio/gnuradio/blob/07741c1e5c7693a2a240bacfc5828f455fe20482/gr-digital/include/gnuradio/digital/mpsk_snr_est_cc.h#L28
says

"It [...] passes all incoming data along to its output"

While that does not explicitly says 1:1 copy I think it is fair to say
that a shift might come as a surprise to a user.

Is there any benefit to keeping the additional zero in the output, or
was this simply not considered when writing the block? If the latter is
true, I'd be happy to write a patch for it.

> However, you'll see the last symbol as the first symbol of
> your coming call to work!
I am not entirely sure what you mean by that. Are you explaining what a
history of 2 does to a block? In that case this is clear to me.

But I am wondering what happened to my last input symbol.

Input: ((1+0j), (-1+0j), (1+0j), (1+0j))
I got: (0j, (1+0j), (-1+0j), (1+0j))
I would expect: (0j, (1+0j), (-1+0j), (1+0j), (1+0j))

Could it be that the last history()-1 number of samples are cut away
from a blocks input?

Or asked in a different way: Will a block that has a history of 5 that
gets 10 input samples (in total, might be over different calls to work)
see 10, 14 or 15 unique (as in not counting them twice) symbols?

Yours
Martin


From the example
>
> Best regards,
> Marcus
>
> On 24.03.20 10:33, Martin Luelf wrote:
>> Hi everybody,
>>
>> I stumbled over a strange behavior while writing unittests for a frame
>> synchronization block.
>>
>> The MPSK SNR Estimation block from GNURadio will output a complex zero
>> sample before outputting the (shifted by one) input samples.
>>
>> To show this problem I use a Vector source with a sequence of BPSK
>> symbols and connect this source to a vector sink and the MPSK SNR
>> estimation block. The SNR estimation block is connected to a second sink
>> (the python script for this is attached at the bottom of this email).
>> After the flowgraph completes I print out the input data and the data
>> collected by the two sinks and it looks like this:
>>
>> Original input data:............. ((1+0j), (-1+0j), (1+0j), (1+0j))
>> Data from source (SNR Est input): ((1+0j), (-1+0j), (1+0j), (1+0j))
>> Data from SNR Est:............... (0j, (1+0j), (-1+0j), (1+0j))
>>
>> Note that the data from the SNR estimator has an additional 0j at the
>> front before the input sequence and the last symbol from the input data
>> is dropped.
>>
>> However looking at the source code of the SNR Estimation block the first
>> line of the work function
>> (https://github.com/gnuradio/gnuradio/blob/351a22cc0e2fc05f4ca6ccb08de6ca1e83b62a70/gr-digital/lib/mpsk_snr_est_cc_impl.cc#L77)
>> reads:
>>
>> memcpy(output_items[0], input_items[0], noutput_items *
>> sizeof(gr_complex));
>>
>> which looks perfectly correct to me. So what is happening here? Am I
>> missing something? I tried searching the mailing list for shifted
>> samples but the results all resolve around actually wanting to shift
>> samples around.
>>
>> Any help/hint would be greatly appreciated.
>>
>> Yours
>> Martin
>>
>>
>>
>> Example code to reproduce the problem (tested on maint-3.7 branch
>> currently at commit 351a22cc0e2fc05f4ca6ccb08de6ca1e83b62a70):
>>
>> #!/usr/bin/env python2
>> # -*- coding: utf-8 -*-
>>
>> from gnuradio import blocks
>> from gnuradio import digital
>> from gnuradio import gr
>>
>> tb = gr.top_block("Test MPSK SNR Estimation")
>>
>> ##################################################
>> # Variables
>> ##################################################
>> data_in = (1.0+0j, -1.0+0j, 1.0+0j, 1.0+0j)
>>
>> ##################################################
>> # Blocks
>> ##################################################
>> blocks_vector_source = blocks.vector_source_c(data_in, False, 1, [])
>> digital_mpsk_snr_est_cc = digital.mpsk_snr_est_cc(0, 10000, 0.001)
>> blocks_vector_sink1 = blocks.vector_sink_c(1, 1024)
>> blocks_vector_sink2 = blocks.vector_sink_c(1, 1024)
>>
>> ##################################################
>> # Connections
>> ##################################################
>>
>> # Source -> Sink 1
>> tb.connect((blocks_vector_source, 0), (blocks_vector_sink1, 0))
>>
>> # Source -> MPSK SNR Est -> Sink 2
>> tb.connect((blocks_vector_source, 0), (digital_mpsk_snr_est_cc, 0))
>> tb.connect((digital_mpsk_snr_est_cc, 0), (blocks_vector_sink2, 0))
>>
>> tb.run()
>>
>> print('Original input data:............. {}'.format(data_in))
>> print('Data from source (SNR Est input):
>> {}'.format(blocks_vector_sink1.data()))
>> print('Data from SNR Est:...............
>> {}'.format(blocks_vector_sink2.data()))
>>
>

No comments:

Post a Comment