discuss-gnuradio
[Top][All Lists]
Advanced

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

Re: [Discuss-gnuradio] First Post - Question - GRC Repeat Block


From: Francisco Albani
Subject: Re: [Discuss-gnuradio] First Post - Question - GRC Repeat Block
Date: Mon, 27 Jul 2015 16:21:09 -0300

Kevin: remember that the parameters available for changing during runtime are underlined in the block settings window.

2015-07-27 13:45 GMT-03:00 Marcus Müller <address@hidden>:
Hi Kevin,

On 27.07.2015 17:53, mcquiggi wrote:
Hi Marcus:

I’m just following up on my Repeat block question.  I figured that I would take this off-list but if you think it appropriate for all then feel free to cc it back on-list.
I'll do that :)

Thanks for the assistance, let me know if I am wasting your time.
Far from it, actually! I think discussions like these are immensely valuable for the community -- people with different backgrounds contributing is one of the strengths of the GNU Radio project, and you are freely investing your time in this; in fact, I think what you're addressing below will be of interest to a lot of mailing list archive readers later on!

I had a look at various source code modules yesterday.  I looked at 'repeat_impl.cc' and ‘repeat_impl.h’  What I understand so far is that the new version of the Repeat block may have to move to the “General” type of block from that of an “interpolator” block, as it will now be in the M:N samples realm, rather than 1:N.
That's halfway true; if I understand your intention correctly, the block would stay 1:N -- but that N would be subject to change over the lifetime of the block. As far as I know, the normal sync_interpolator mother class can deal with that.

I also think I see that there is a value ‘noutput_items’ that gets computed once, when the block/object is created.
oh, no, that's the amount of items that the scheduler allows you to produce, so it's different each time work() is called!
 What I need is for this value to be variable and re-calculated by a change in the parameter in the GRC block.
It's a parameter, not a result of your work -- what you in fact need to re-calculate is the ratio between number of items you consume and number of items a call to work() produced.
In fact, sync_interpolator just overrides general_work like you would in a general block, and calls work(..) from within there -- based on the items work produced (usually, that's just the number work() returns), it calculates the items consumed (by a simple division).
 As the work function (which is fairly simple) is just a for loop 1 to noutput_items, then this seems correct.
So what you need to do when changing the number of repititions is just
a) change the value of d_interp, so that repeat's work() does the "right thing" and
b) call the set_interpolation method [1] to change the factor that is used behind the scenes to keep the amount of samples flowing in and out correct.

I see repeat_impl and work functions.  I gather that the repeat_impl routine allocates a block of storage or a buffer or something based on the static value of noutput_items which has been pre-computed in a higher level block.  This (I think) is where the code has to change. 
repeat_impl is a subclass of repeat (which itself is a subclass of sync_interpolator, which is a sync_block subclass, which is a block subclass, which is a basic_block subclass; C++ inheritance :) ).

This is now a bit of a oversimplification of C++, but I think you can deal with this: here, think of these C++ classes as C structs, that inherit all the elements from their mother structs. Methods are basically function pointers in these structs, and when invoked they automatically (and hiddenly) set a parameter "this" to be a pointer to the indidual struct object. That way, you can work with methods that really only operate on a single object's state, and don't have to always carry around a handle to the object to modify (which is a very C thing to do). So, work is such a function, and d_interp is a member of the struct that automatically relates to the "this" parameter, ie. you could also use this->d_interp (which really is a valid alias for d_interp).

What happens is that C++ makes sure that when the GNU Radio scheduler calls the general_work of any block, the respective block's implementation's general_work is called (in this case, sync_interpolator has that implementation of general_work). In the case of sync_interpolator, that general_work computes the right in- and output item numbers, and calls its work(), which is overridden by repeat_impl::work.

Now that's more software design theory than the average GNU Radio user has. What you need to know is: you implement a work() method; GNU Radio calls that when there's new data available or when there's still data on the input but new output space has become available.

There's one caveat that we'll have to address later: GNU Radio is multithreaded, and heavily so. Imagine the segfaults that would happen if you were to change d_interp from 1 to 10^9 in the middle of the for loop in work() running, but there was only output space for input_items[0]*1! C++, boost and GNU Radio have methods of dealing with that problem, and I'll gladly help with it.

Would re-calculation of noutput_items imply that the object created for the delay block has to be destroyed and get re-created?  I do not know anything about the internal structure of gnuradio so I am obviously in the dark.  I was unsuccessful in locating the place where noutput_items is calculated, I am guessing that it is in a higher-level block.

I’ve grabbed the source code and am building gnuradio (via the build-gnuradio script), so once I have all the source locally it will be easier to locate stuff.  I will look for where noutput_items is initially calculated.
It's calculated again, again and again, every time before calling your work() method.
The idea is that every block has it's (general_)work method, and GNU radio calls them, whenever the circumstances make that sensible, ie. when there is opportunity to generate/process items:
Assume you connect block A, B, C:
A->B->C
when the work method of B returns, the consumed input samples in its input buffer can be overwritten (GNU Radio implements circular buffers), since they already have been processed. Hence, in a different thread A's work() is called, with the info that noutput_items is now larger by exactly that amount of samples.
The same happens for C: B::work() returns, and GNU Radio calls C's work() with the info that there's new input available. When C::work() returns, B is notified again that there's output space available, and everything keeps flowing.


It may be a matter of you telling me how wrong I am, but otherwise I would ask if I am anywhere near the correct track?
You're pretty close to the real thing! The C coder is speaking through your questions, but that's absolutely not a bad thing; young "C++ folks" (I might consider myself that) often struggle with things like dealing with memory, pointer casting etc, where that's bread and butter techniques and patterns for C devs.
Have I pointed you to the guided tutorials?
https://gnuradio.org/redmine/projects/gnuradio/wiki/Guided_Tutorials
Especially chapter 4 will be of interest to you. It does assume that you're somewhat proficient with C++, but 4.3.2.4 / Interpolation
illustrates what we're dealing with pretty nicely, I think.

Best regards,
Marcus

[1] https://gnuradio.org/doc/doxygen/classgr_1_1sync__interpolator.html#ae4daef83760cfe1951c9cf8a83520352



On Jul 26, 2015, at 2:54 AM, Marcus Müller <address@hidden> wrote:

Hi Kevin,

this is everything but a dumb newbie question! In fact, it explains quite well what you want to do, you illustrate with a screenshot of the relevant things, and you describe what happens instead. That makes this a well-researched, well-presented and thought through question.

So the point is that the GRC repeat block is but a graphical alias for the gr::blocks::repeat block[1]. As the docs show, that doesn't allow dynamic setting of the interpolation.

So, this email thread could now address different things:

(0. You kind of reported a bug. Or at least a feature request. If you want to do this the right way, open a issue on gnuradio.org's issue tracker.)
1. Do you really need repeat functionality, or are you in fact trying to adjustably interpolate a band-limited signal, in which case interpolation with a filter might be the right thing to do? There's a block that just wraps that nicely (fractional interpolator).
2. Do you want us to help you add that functionality to the repeat block? I had a look, it's not that hard, and it could get you on the contributor's list by helping an awesome free software project :) ; I haven't added that functionality yet, so there might be some surprises while doing this, but it should work.

Best regards,
Marcus

[1]https://gnuradio.org/doc/doxygen/classgr_1_1blocks_1_1repeat.html

On 26.07.2015 06:07, Kevin McQuiggin wrote:
I should have added that I am running gnuradio version 3.7.7.1 under OSX 10.10.4.

On Jul 25, 2015, at 8:26 PM, Kevin McQuiggin <address@hidden> wrote:

Hi All:

I would like to use a repeat block to stretch the duration of vectored input dynamically.  For example, (0,1,0,1,…) input should become (0,0,0,1,1,1,0,0,0,…), the repeat count under control of a variable.  In this example the Interpolation parameter would be 3.

I observe that the “Interpolation” value in the Repeat block appears to be set initially, but does not respond to dynamic changes.  Here is a minimalist flowgraph that shows this behaviour:

<PastedGraphic-2.png>

I would like to be able to use the QT GUI Chooser to select other vales for variable “test1” and have this dynamically adjust the Repeat block “Interpolation” value.  This doesn’t work.  In the example flowgraph, “Interpolation” is initialized and remains at 2, despite selecting other values for “test1” when the flowgraph is run.

It is likely a dumb, newbie question, but how can I achieve the desired behaviour?  I have scoured the Wiki, docs, Google, etc, and having not found an answer, I thought I’d make my first post and ask.

Thanks in advance,

Kevin



_______________________________________________
Discuss-gnuradio mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio


_______________________________________________
Discuss-gnuradio mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio

_______________________________________________
Discuss-gnuradio mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio



_______________________________________________
Discuss-gnuradio mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio



reply via email to

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