discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: forecast() function usage with static addition of bits


From: Jeff Long
Subject: Re: forecast() function usage with static addition of bits
Date: Thu, 25 Jan 2024 21:11:45 -0500

Take a look at the code in the built-in gr-fec module, for instance:
  https://github.com/gnuradio/gnuradio/blob/main/gr-fec/lib/encoder_impl.cc

Note that RS is implemented in gr-fec.

The forecast() function helps the scheduler, but it doesn't come with any guarantees.

On Thu, Jan 25, 2024 at 4:07 PM John Moon <john.moon@vts-i.com> wrote:
Hi,

I'm trying to write an OOT Python block which takes an input "packet" of bytes and outputs a longer "packet" of bytes. This is an implementation of an error-correcting code which adds a static 64 bytes to the input.

The input is able to operate on 1 byte up to 63 bytes. When it gets 1 byte in, I'd expect 65 bytes to come out. When it gets 63 bytes in, I'd expect 127 bytes to come out, so n_output_items should always be n_input_items + 64.

I'm having trouble expressing this kind of block in GR. Here's a minimal version of what I have:

============

class encoder(gr.basic_block):
    def __init__(self):
        gr.basic_block.__init__(self, name="encoder", in_sig=[np.uint8], out_sig=[np.uint8])

        self.logger = gr.logger(self.alias())

        self.msg_len = 63
        self.block_len = 127
        self.set_min_noutput_items(self.msg_len + 2)
        self.set_max_noutput_items(self.block_len)

    def fixed_rate(self):
        return True

    def fixed_rate_noutput_to_ninput(self, noutput_items):
        return noutput_items - self.msg_len - 1

    def fixed_rate_ninput_to_noutput(self, ninput_items):
        return ninput_items + self.msg_len + 1

    def forecast(self, noutput_items, ninputs):
        # This block will take in N bytes and output N + msg_len + 1 bytes, so the minimum
        # input we need is 1 + msg_len + 1 and the max is 1 + RS_BLOCK_LEN + 1. So, say
        # GR wants us to produce y output items. y = x + msg_len + 1, where x is the
        # number of input items. So, generally, x = y - msg_len - 1.
        ninput_items_required = self.fixed_rate_noutput_to_ninput(noutput_items)
        print(f"FORECAST: for {noutput_items} outputs, {ninput_items_required} inputs are required")
        return [ninput_items_required] * ninputs

    def general_work(self, input_items, output_items):
        in0 = input_items[0]
        out = output_items[0]
        self.logger.info(f"Input is {len(in0)} symbols")
        self.logger.info(f"Output buffer is {len(out)} symbols")

        out.fill(0)
        self.consume(0, len(in0))
        return len(out)

============

I believe the forecast() function is doing what it's supposed to be doing, but I'm puzzled by the inputs it's getting. From the debug prints, I can see that the "noutput_items" being passed to forecast() goes: 127, 63, 31, 15, 7, 3, 1. So, halving the number of outputs requested each time. I have three questions about this:

1. Why would the GR scheduler try to forecast for outputs smaller than the "min_noutput_items()" I set in the constructor?
2. Is there a way (from the forecast function) to tell the scheduler a particular noutput_items is invalid?
3. What happens to the buffer sizes for inputs that aren't forecasted for? E.g, if I pass in 1 byte to my block, I'd expect 65 outputs, but I don't see that output being forecasted.

I'm relatively new to GR, so apologies for any blatant misunderstandings and thank you so much for your time!

- John


reply via email to

[Prev in Thread] Current Thread [Next in Thread]