Test-bed application: how to control GUI app and gr_vector_source

Hello, dear GNU-Radio community,
Some last weeks I am coping with how to run and reconfigure gr.top_block
on the fly, didn’t manage, so I thought, maybe someone out there could
give me some hint.

I am writing an application which is expected to send different test
signal through USRP2 - to test some other embedded receivers. So I need
to reconfigure top_block an different parameters on the fly.
I can do the nonGUI case, its OK. I just use wait() to identify when
vector with test data is empty, to generate a new one and restart the
flowgraph.
But I can’t wrap around how to involve the wxPython GUI - after starting
MainLoop() I’ve no control any more on the top_block.
What is needed:

  1. during software run, change gr.vector_source data (get some
    notification, when its empty, then fill with new test-case-data, start
    again)
  2. on each test-case, be able to adjust frequency, and gain of USRP2
  3. give some graphical output of signal, for example, FFT.

Q1)Is there some callback, when vector is empty (I didn’t find one) or
flowgraph is stopped due finished-data-stream? Or at least parameter?
(the gr_vector_source.detail().done() just rises an error)
Q2)Is there some callback from MainLoop() which “usually” is used?
Q3)does it in general make sense to reconfigure and readjust flowgraph
“fluently” or it is recommended some sleep time inbetween. Like, maybe,
the gain of USRP2 just impossible to switch from 0 to 35 within 1ms. Or
notification done() can be issued between data samples are really sent
out by USRP, thus changing frequency at that time would be wrong.

I also tried to start the grc_wxgui.top_block_gui in new thread and
after run() tried to adjust parameters, without efforts. Also MainLoop()
in different thread, no luck.

Here down some very basic sample - if somebody can give hint to attach
Scope to it, I would appreciate it a lot.

Best regards from Bremen,
diehortusxana

==================
#!/usr/bin/env python

from gnuradio import audio
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.gr import firdes
from optparse import OptionParser
import time
import math

class my_basic_tb(gr.top_block):
def init(self):
gr.top_block.init(self)
self.samp_rate = samp_rate = 32000
self.audio_sink_0 = audio.sink(48000, “”, True)
self.gr_vector_source_x_0 = gr.vector_source_f(gen_freq(41,1),
False, 1)
self.connect((self.gr_vector_source_x_0, 0), (self.audio_sink_0,
0))

def gen_freq(freq,len_s):
nv = []
for i in range(1,48000*len_s):
if math.fmod(i,freq) == 0:
nv.append(1)
else:
nv.append(0)
return nv

if name == ‘main’:
parser = OptionParser(option_class=eng_option, usage="%prog:
[options]")
(options, args) = parser.parse_args()

tb = my_basic_tb()
tb.start()
tb.wait()
print(“done_part_1”)
tb.lock()
tb.disconnect(tb.gr_vector_source_x_0)
tb.gr_vector_source_x_0 = gr.vector_source_f(gen_freq(11,1), False,
1)
tb.connect((tb.gr_vector_source_x_0, 0), (tb.audio_sink_0, 0))
tb.unlock()
tb.start()
print(“reconfigured”)
tb.wait()

print(“Done”)

On Wed, Nov 10, 2010 at 12:52 PM, Andis D.
[email protected] wrote:

But I can’t wrap around how to involve the wxPython GUI - after starting
Q2)Is there some callback from MainLoop() which “usually” is used?
Here down some very basic sample - if somebody can give hint to attach Scope
from gnuradio import gr
self.audio_sink_0 = audio.sink(48000, “”, True)
return nv
tb.lock()
tb.disconnect(tb.gr_vector_source_x_0)
tb.gr_vector_source_x_0 = gr.vector_source_f(gen_freq(11,1), False, 1)
tb.connect((tb.gr_vector_source_x_0, 0), (tb.audio_sink_0, 0))
tb.unlock()
tb.start()
print(“reconfigured”)
tb.wait()

print(“Done”)

Instead of disconnecting the source, rebuilding it, and reconnecting
it, try to use the rewind() function on the source.

Also, yes, you’ll want to put in some pause time when you update the
frequency/gain of the USRP.

Tom

On 11/11/2010 03:46 PM, Tom R. wrote:

reconfigure top_block an different parameters on the fly.
Q1)Is there some callback, when vector is empty (I didn’t find one) or
run() tried to adjust parameters, without efforts. Also MainLoop() in

def init(self):
nv.append(1)
tb.start()

Tom

Hello everybody, I found solution to the problem stated above, so I
share it with everybody - so people like me, searching to make
testing-purpose applications, could find the answer here.

There are 2 main points to care about:

  1. the top_block was wrapped in grc_wxgui.top_block_gui [to get wx GUI]
    and that again in Thread [to be able call Run() and have return of
    execution
  2. the vector and Scope are reconnected [the just “rewind() + unlock() +
    start()” doesn’t start the flowgraph with new values. If scope isn’t
    reattached, it doesn’t update its GUI (just freezes for a while and
    shows end-state)

And thanks to Tom for the notes. I put some pause now inside :slight_smile:
If someone knows another way how the same target could be achieved in
better way, please post here.
Enjoy :slight_smile:

=========================
#!/usr/bin/env python

from gnuradio import audio
from gnuradio import gr
import time
import math
from gnuradio.wxgui import scopesink2
from grc_gnuradio import wxgui as grc_wxgui
from threading import Thread

class my_basic_tb_gui(grc_wxgui.top_block_gui):
def init(self):
grc_wxgui.top_block_gui.init(self, title=“my_basic_tb_gui”)
self.samp_rate = samp_rate = 32000
self.audio_sink_0 = audio.sink(48000, “”, True)
self.gr_vector_source_x_0 = gr.vector_source_f(gen_freq(41,2),
False, 1)
self.wxgui_scopesink2_0 = scopesink2.scope_sink_f(
self.GetWin(),
title=“Scope Plot”,
sample_rate=samp_rate,
v_scale=0,
v_offset=0,
t_scale=0,
ac_couple=False,
xy_mode=False,
num_inputs=1,
)
self.Add(self.wxgui_scopesink2_0.win)
self.connect((self.gr_vector_source_x_0, 0), (self.audio_sink_0,
0))
self.connect((self.gr_vector_source_x_0, 0),
(self.wxgui_scopesink2_0, 0))

def gen_freq(freq,len_s):
nv = []
for i in range(1,48000*len_s):
if math.fmod(i,freq) == 0:
nv.append(1)
else:
nv.append(0)
return nv

class GUIapp(Thread):
def init (self):
Thread.init(self)
self.tb = my_basic_tb_gui()
def run(self):
self.tb.Run(False)
#self.tb.start()

if name == ‘main’:
app = GUIapp()
app.start()
app.tb.start()
app.tb.wait()
print(“done_part_1”)
app.join(1.1) #wait for case real world is not so far yet
app.tb.lock()
app.tb.disconnect_all()
app.tb.gr_vector_source_x_0 = gr.vector_source_f(gen_freq(11,2),
False, 1)
app.tb.connect((app.tb.gr_vector_source_x_0, 0),
(app.tb.audio_sink_0, 0))
app.tb.connect((app.tb.gr_vector_source_x_0, 0),
(app.tb.wxgui_scopesink2_0, 0))
app.tb.unlock()
app.tb.start()
print(“reconfigured”)
app.tb.wait()

print(“Done”)
app.tb.stop(); app.tb.wait(); app.tb._frame.Destroy()

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

diehortusxana