# Looping with work() function

**URL:** <https://www.ruby-forum.com/t/looping-with-work-function/239701>\
**Category:** GNU Radio\
**Created:** [March 11, 2014, 6:11am UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701 "2014-03-11T06:11:07Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![musicdenotation](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ea666f/32.png) [@musicdenotation](https://www.ruby-forum.com/u/musicdenotation)\
**Post date:** [March 11, 2014, 6:11am UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701/1 "2014-03-11T06:11:07Z")

</div>

Hello

I am executing a flowgraph where I pass different parameters to the  
work()  
function of my block in every iteration.

1. I would like my flowgraph to execute once with a certain set of  
parameters and on satisfying a certain condition, it should stop  
execution  
(even if the queue/buffer of the block is not empty).
2. The control should come back to the main() function and the next  
iteration should start with a new set of parameters and again upon  
satisfying a certain condition the flowgraph should exit.

_The work() function is of the block “test\_demo”:_  
_############new\_test\_tx.py#################_  
class test\_demo(gras.Block):  
def\_\_init\_\_(self,parameters):  
gras.Block. **init** (self,name=“test”,  
in\_sig = [numpy.uint8,numpy.uint8,numpy.uint8],  
out\_sig = [numpy.uint8,numpy.uint8])

def work(self, ins, outs):  
–some process here

_The top\_block is as following and has code for all the connections(not  
shown here):_

class top\_block(grc\_wxgui.top\_block\_gui):

def **init** (self,options,llr):  
grc\_wxgui.top\_block\_gui. **init** (self, title=“Top Block”)  
\_icon\_path = “/usr/share/icons/hicolor/32x32/apps/gnuradio-grc.png”  
self.SetIcon(wx.Icon(\_icon\_path, wx.BITMAP\_TYPE\_ANY))

```
      self.=new_test_tx.test_demo(options.parameters)

```

def main():

parser = OptionParser(option\_class=eng\_option,  
conflict\_handler=“resolve”)  
parser.add\_option("", “–args”,default="",  
help=“set the address of usrp\_device [default=’’]”)  
(options, args) = parser.parse\_args ()

# build the graph

tb=top\_block(options,param)  
tb.Run(True)  
if **name** ==“ **main** ”:  
main()

I am able to execute the flowgraph once and then the main() function  
exits.  
I would like to perform this action for some 1000 iterations. It is a  
kind  
of for loop that I use during C/Python programming. How can I use it  
with  
GNURadio and Python.

Thanks and Regards,  
Sumedha

---

<div class="post-metadata">

**Author:** ![Sumedha\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9bd4f/32.png) [@Sumedha\_G](https://www.ruby-forum.com/u/Sumedha_G)\
**Post date:** [March 11, 2014, 10:06am UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701/2 "2014-03-11T10:06:04Z")

</div>

On 03/11/2014 06:10 AM, Sumedha G. wrote:

> Hello
> 
> I am executing a flowgraph where I pass different parameters to the  
> work() function of my block in every iteration.

I’m not sure I’m understanding you correctly, but this is not how you  
use GNU Radio blocks.

Have a look at gr-digital/examples/berawgn.py. Is this what you want to  
do?

> 1. I would like my flowgraph to execute once with a certain set of  
> parameters and on satisfying a certain condition, it should stop  
> execution (even if the queue/buffer of the block is not empty).
> 2. The control should come back to the main() function and the next  
> iteration should start with a new set of parameters and again upon  
> satisfying a certain condition the flowgraph should exit.

You shut down a flow graph by returning WORK\_DONE (or -1) from the work  
function.

M

---

<div class="post-metadata">

**Author:** ![Sumedha\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9bd4f/32.png) [@Sumedha\_G](https://www.ruby-forum.com/u/Sumedha_G)\
**Post date:** [March 11, 2014, 10:44am UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701/3 "2014-03-11T10:44:27Z")

</div>

On Tue, Mar 11, 2014 at 5:04 PM, Martin B.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)wrote:

> On 03/11/2014 06:10 AM, Sumedha G. wrote:
> 
> > Hello
> > 
> > I am executing a flowgraph where I pass different parameters to the  
> > work() function of my block in every iteration.

If the “parameters” could be fed into work() as input elements, than  
that  
is possible.  
Please describe the parameters in details.

> 1. I would like my flowgraph to execute once with a certain set of
> 
> > parameters and on satisfying a certain condition, it should stop  
> > execution (even if the queue/buffer of the block is not empty).  
> > 2. The control should come back to the main() function and the next  
> > iteration should start with a new set of parameters and again upon  
> > satisfying a certain condition the flowgraph should exit.

In flow-graph there is no main() function, but only the scheduler in the  
background.  
Please give specific examples of what you are trying to accomplish.

Regards,  
Activecat

---

<div class="post-metadata">

**Author:** ![Sumedha\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9bd4f/32.png) [@Sumedha\_G](https://www.ruby-forum.com/u/Sumedha_G)\
**Post date:** [March 11, 2014, 1:50pm UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701/4 "2014-03-11T13:50:26Z")

</div>

On 03/11/2014 01:31 PM, Sumedha G. wrote:

> My top\_block class represents the whole flowgraph. The class “test\_demo”

No, it doesn’t. It doesn’t have any connect() calls or anything. This is  
not a flow graph.

> with scheduler. How can I use the scheduler to do this?  
> If you’re using a flow graph, you use the scheduler automatically, you  
> don’t need to set it up or anything.

Have a look at the file I recommended. If you feel you don’t understand  
something, first read the introductory documents on the wiki, as well as  
[http://gnuradio.org/redmine/projects/gnuradio/wiki/Simulations](http://gnuradio.org/redmine/projects/gnuradio/wiki/Simulations).

Good luck,  
Martin

---

<div class="post-metadata">

**Author:** ![Sumedha\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9bd4f/32.png) [@Sumedha\_G](https://www.ruby-forum.com/u/Sumedha_G)\
**Post date:** [March 11, 2014, 1:32pm UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701/5 "2014-03-11T13:32:43Z")

</div>

My top\_block class represents the whole flowgraph. The class “test\_demo”  
is  
one of the blocks of this flowgraph for which its own work() function is  
defined.  
The “test\_demo” checks for a “start sign”(given by the user) and  
participates in data transmission process and upon receiving an ACK for  
success should stop further transmission.  
At this point, the flowgraph should stop and start again with a new  
“start  
sign” for next iteration and so on. I am planning to plot the number of  
packets transmitted before receiving an ACK against this “start sign”.  
Therefore, I need my flowgraph to execute several times.  
I hope this description explains my intention. I am not very familiar  
with  
scheduler. How can I use the scheduler to do this?

---

<div class="post-metadata">

**Author:** ![Sumedha\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9bd4f/32.png) [@Sumedha\_G](https://www.ruby-forum.com/u/Sumedha_G)\
**Post date:** [March 11, 2014, 2:59pm UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701/6 "2014-03-11T14:59:57Z")

</div>

Dear Sumedha G.,

> The “test\_demo” checks for a “start sign”(given by the user) and  
> participates in data transmission process and upon receiving an ACK for  
> success should stop further transmission.

Q1: What do you mean by “participates in data transmission process”?  
Does it just send out what it receives, or insert any new data?  
Q2: For “upon receiving an ACK”:- from where the ACK will comes from,  
from upstream, downstream, or somewhere else?

> At this point, the flowgraph should stop and start again with a new “start  
> sign” for next iteration and so on. I am planning to plot the number of  
> packets transmitted before receiving an ACK against this “start sign”.

If I understand you requirement correctly, you need a block that  
continuously getting input from somewhere.  
This input contains “start sign” and later followed by “ACK”.  
Upon receiving “start sign”, this block will pass through all it  
receives to its output port.  
Upon receiving “ACK”, this block will stop the pass through (means no  
output), until it receive another “start sign” again.  
Meanwhile, you want the block to count the number of inputs between  
the “start sign” and “ACK”, and use this number to plot graph.

Is this what you want? If yes then I am able to help you.  
Let’s clarify your requirements first.

Regards,  
Activecat

---

<div class="post-metadata">

**Author:** ![Sumedha\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9bd4f/32.png) [@Sumedha\_G](https://www.ruby-forum.com/u/Sumedha_G)\
**Post date:** [March 11, 2014, 6:52pm UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701/7 "2014-03-11T18:52:15Z")

</div>

1. There is a file source that frames data packets for the test\_demo.  
This  
is part of a transmitter USRP.
2. I have another USRP as receiver that sends an ACK upon reception of  
data  
packets to the transmitter.
3. Start sign is a threshold value. If the packet information  
(calculated  
by some method) exceeds this threshold, transmission starts and upon  
receiving an ACK stops.
4. I change this threshold value for every new iteration and count how  
many  
packets were transmitted before receiving a success ACK.  
I can do this manually for every iteration but how to automate it for  
say  
some 1000 iterations?

I hope it explains everything.

---

<div class="post-metadata">

**Author:** ![Sumedha\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9bd4f/32.png) [@Sumedha\_G](https://www.ruby-forum.com/u/Sumedha_G)\
**Post date:** [March 12, 2014, 2:01am UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701/8 "2014-03-12T02:01:16Z")

</div>

Dear Sumedha G.,

On Wed, Mar 12, 2014 at 1:51 AM, Sumedha G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> 1. There is a file source that frames data packets for the test\_demo. This  
> is part of a transmitter USRP.
> 2. I have another USRP as receiver that sends an ACK upon reception of data  
> packets to the transmitter.
> 3. Start sign is a threshold value. If the packet information (calculated by  
> some method) exceeds this threshold, transmission starts and upon receiving  
> an ACK stops.

It sounds like you are trying to transfer file from PC#1 to PC#2,  
connected via USRPs.  
At PC#1, user payload is read from a file on harddisk. This data is  
fed into a custom block. This block will start transmitting when  
certain criteria is met. When PC#2 receive the packets, it will send  
ACK back to PC#1.

If this is what you try to accomplished, of course this could be  
implemented by gnuradio.  
There are thousands of such setup being tested using gnuradio.

You should have told us the big picture, let us figure out the  
implementation details for you, not the opposite way.  
Forget about your initial python code because that limit us to dead end.

> 1. I change this threshold value for every new iteration and count how many  
> packets were transmitted before receiving a success ACK.  
> I can do this manually for every iteration but how to automate it for say  
> some 1000 iterations?

When you automate it you must have a calculation formula or decision  
algorithm.  
Please give a simple example of such calculation formula.

Now I am still in the midst of trying to understand your requirements  
correctly.

Meanwhile, please do not top-post.  
Refer  
[http://gnuradio.org/redmine/projects/gnuradio/wiki/ReportingErrors#How-should-I-format-my-message](http://gnuradio.org/redmine/projects/gnuradio/wiki/ReportingErrors#How-should-I-format-my-message)

Regards,  
Activecat

---

<div class="post-metadata">

**Author:** ![Sumedha\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9bd4f/32.png) [@Sumedha\_G](https://www.ruby-forum.com/u/Sumedha_G)\
**Post date:** [March 12, 2014, 8:09am UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701/9 "2014-03-12T08:09:07Z")

</div>

Please stay on the mailing list.

On 03/11/2014 02:37 PM, Sumedha G. wrote:

> I haven’t shown the whole code here but the top\_class has all the  
> connect() functions required to connect the various blocks. I’ve gone  
> through the link that you have sent me. In this example, the work()  
> function is not used anywhere. I would like to do a similar thing but  
> cannot avoid work(). Is there a way around?

work() is called in every single block. This is how blocks work. Have a  
look at the “out of tree module” tutorial.

Martin

---

<div class="post-metadata">

**Author:** ![Sumedha\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9bd4f/32.png) [@Sumedha\_G](https://www.ruby-forum.com/u/Sumedha_G)\
**Post date:** [March 13, 2014, 8:01am UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701/10 "2014-03-13T08:01:32Z")

</div>

Dear Sumedha,

My idea is to create a custom block of type “general”.  
This block takes an input from a File Source. It has an output connect  
to USRP (for transmitting signal).  
It has another input port connected to USRP for receiving ACK.

See below inline answers for further elaboration.

On Thu, Mar 13, 2014 at 1:42 PM, Sumedha G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > Hi Activecat,
> 
> This is true that I am trying to accomplish the same task that you have  
> mentioned . But the difference is:
> 
> 1. I pass a threshold value to my “test\_demo” block from the  
> “top\_block”(Example: top\_block(options, 0.4)). A random number is generated  
> inside the “test\_demo” block and compared to this threshold.
> 2. If the random number is more than threshold, the transmission process  
> starts.

We make this threshold value an argument to the constructor of the  
custom block. The block will store this threshold value as its class  
variable.  
The random number could be generated inside the general\_work() function.  
Hence, before transmission of packet starts, a random number will be  
generated each time the general\_work() is called.  
If the random number is lower than the threshold, then the  
general\_work() just return without performing any other action.  
But make sure the returned value will make this general\_work() to be  
continuously called repeatedly.

> 1. The block makes transmitter USRP to send data packets in a specified  
> format(source\_address+destination\_address+packet\_sequence\_no+message).
> 2. Upon receiving a packet, the receiver USRP sends an ACK.

Hence the transmitting USRP needs to have the hardware capability to  
receive signal. We feed this signal from USRP back to the custom  
block.  
In alternative, you could use the 3rd USRP attaching to PC#1 to  
receive the ACK, but this is not likely the preferable way.

> 1. Meanwhile, the transmitter USRP counts number of data packets sent before  
> receiving an ACK. As soon as the transmitter USRP receives first ACK, it  
> should stop data transmission and reception of further packets from anywhere  
> (from the user payload from a file source on harddisk).

Data packet counting can be done on this custom block.  
When not transmitting data packets, the output of the block to USRP is  
just a series of zeros.  
We need to set\_max\_noutput\_items() to a small value, so that the block  
response fast enough to the ACK signal.  
This block should continuously consuming input from USRP (to detect  
ACK) while sending output (either data packets, or a series of zero)  
to the USRP.  
I think these two ports (the input and output connecting to USRP)  
should have the same data rate as they are connecting to the same  
USRP.

> 1. At this point, I want to be able to change the threshold value for the  
> block and start the process again. The random number will be generated again  
> and so on.

Without interrupting the flow graph, we can change this threshold  
value using WX GUI Slider, because the threshold value is stored as a  
class variable of the custom block.

> 1. I want to continue this process for several number of times and plot a  
> graph between the threshold and the number of packets transmitted.

As the custom block is doing the counting of data packets, it can save  
the packet counts information into a file. You could later retrieve  
data from this file to plot graph, after stopping the flow graph.  
If you insist to plot graph in real time, then this block could send  
the packet counts information to another output port. Be careful here  
because all output ports must have same data rate. Nevertheless there  
is a workaround for overcome this issue.

> How should I proceed?

If this confirms what you want, I could then send you a sample code.  
Make sure the requirements is correct first.

Additional question to you:  
When PC#1 transmit packets, PC#2 may miss the few packets before  
detecting the first one.  
That’s why you want PC#1 to count the number of packets transmitted  
before receiving ACK.  
But have you ever think that, the ACK sent by PC#2 may also be missed  
out by PC#1.  
Then how would you handle this ..?

Regards,  
Activecat

---

<div class="post-metadata">

**Author:** ![Sumedha\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9bd4f/32.png) [@Sumedha\_G](https://www.ruby-forum.com/u/Sumedha_G)\
**Post date:** [March 13, 2014, 6:43am UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701/11 "2014-03-13T06:43:40Z")

</div>

> Hi Activecat,

This is true that I am trying to accomplish the same task that you have  
mentioned . But the difference is:

1. I pass a threshold value to my “test\_demo” block from the  
“top\_block”(Example: top\_block(options, 0.4)). A random number is  
generated  
inside the “test\_demo” block and compared to this threshold.
2. If the random number is more than threshold, the transmission process  
starts.
3. The block makes transmitter USRP to send data packets in a specified  
format(source\_address+destination\_address+packet\_sequence\_no+message).
4. Upon receiving a packet, the receiver USRP sends an ACK.
5. Meanwhile, the transmitter USRP counts number of data packets sent  
before receiving an ACK. As soon as the transmitter USRP receives first  
ACK, it should stop data transmission and reception of further packets  
from  
anywhere (from the user payload from a file source on harddisk).
6. At this point, I want to be able to change the threshold value for  
the  
block and start the process again. The random number will be generated  
again and so on.
7. I want to continue this process for several number of times and plot  
a  
graph between the threshold and the number of packets transmitted.

How should I proceed?

---

<div class="post-metadata">

**Author:** ![Sumedha\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9bd4f/32.png) [@Sumedha\_G](https://www.ruby-forum.com/u/Sumedha_G)\
**Post date:** [March 25, 2014, 10:12pm UTC](https://www.ruby-forum.com/t/looping-with-work-function/239701/12 "2014-03-25T22:12:36Z")

</div>

Hi Activecat

The description that you have given matches quite closely to my  
requirements. Kindly send me the sample code. I will try it out with my  
setup.

> We need to set\_max\_noutput\_items() to a small value, so that the block  
> response fast enough to the ACK signal.  
> This block should continuously consuming input from USRP (to detect  
> ACK) while sending output (either data packets, or a series of zero)  
> to the USRP.  
> I think these two ports (the input and output connecting to USRP)  
> should have the same data rate as they are connecting to the same  
> USRP.

What should be done to make all these settings?

> When PC#1 transmit packets, PC#2 may miss the few packets before  
> detecting the first one.  
> That’s why you want PC#1 to count the number of packets transmitted  
> before receiving ACK.  
> But have you ever think that, the ACK sent by PC#2 may also be missed  
> out by PC#1.  
> Then how would you handle this ..?

I am trying to start my experiment from the transmitter side first. I’ll  
handle the missed ACKs later.

Regards,  
Sumedha
