Coding Python GNU Radio Applicat…

来源:互联网 发布:外国直播软件 编辑:程序博客网 时间:2024/05/16 15:56

对GNURADIO编程需要的API:

http://gnuradio.org/redmine/projects/gnuradio/wiki/TutorialsWritePythonApplications#Coding-Python-GNU-Radio-Applications

Coding Python GNU Radio Applications¶

The example above already covers quite a lot of how to writePython GNU Radio applications. This chapter and the next will tryto show the possibilites of GNU Radio applications and how to usethem. From now on, there is no need to linearly read these chapterssection-for-section, it probably makes more sense to go over thetitles and find out what you want to know.

上面的例子已经覆盖了很多怎样使用Python 在GNURadio的应用(dial_tone.py的例子,前面做了很多讲解,没贴上来)。这章下半部分主要讲解GNU Radioapi和怎样使用它们。从现在开始,不需要把每章每个部分都看完,只需要对tiles就是标题有个熟悉的感觉,并且可以找出你想要知道什么就可以了。

GNU Radio Modules¶

GNU Radio 提供很多库和模块。你可以用下面语法包括这些模块

GNU Radio comes with quite a lot of libraries and modules. Youwill usually include modules with the following syntax:

1 from gnuradio import MODULENAME

Some modules work a bit differently, see the following list onthe most common modules.

一些模块作用不同,下面是一些通用模块:

grThe main GNU Radio library. You will nearly always needthis.GNU RADIO主要库函数,你会经常用到它

 

 

usrp

USRP sources and sinks and controls. USRP的source和sink还有control模块audio

Soundcard controls (sources, sinks). You can use this to send orreceive audio to the sound cards, but you can also use your soundcard as a narrow band receiver with an external RFfrontend.  声音控制。你可以用他们来发送和接收声音到声卡,你也可以用你的声卡和外部的RF前端来做窄带接收器

 

blks2

This module contains additional blocks written in Python whichinclude often-used tasks like modulators and demodulators, someextra filter code, resamplers, squelch and so on.

这个模块包括了额外增加的blocks。这些block是用python写的,像调制和解调,一些滤波器的代码,重抽样,噪声抑制等。

 

 

 

optfir

Routines for designing optimal FIR filters.

用来设计FIR滤波器的惯用模块

 

plot_data

Some functions to plot data with Matplotlib

一些用Matplotlib绘制数据的 functions

wxgui

 

This is actually a submodule, containing utilities to quicklycreate graphical user interfaces to your flow graphs. Usefrom gnuradio.wxgui import * to import

everything in the submodule or from gnuradio.wxgui importstdgui2, fftsink2 to import specific components. See thesection 'Graphical User Interfaces' for more information.

这个常用子模块包括 为你的流图快速建立图形接口的工具。 用fromgnuradio.wxgui import * 导入全部子模块或者用from gnuradio.wxgui import stdgui2, fftsink2导入一些自己需要的部分。可以从“Graphical User Interfaces”中找到更多信息

 

eng_notation

Adds some functions to deals with numbers in engineeringnotation such as @100M' for 100 * 10^6'.

增加一些处理工程上数字的表示函数,比如 @100M 表示 100*10^6'

eng_options

 

Use from gnuradio.eng_options import eng_options toimport this feature. This module extends Pythonsoptparse module to understand engineering notation(see above).

这个模块用来扩展optparse的模块去明白工程表示

gru

Miscellaneous utilities, mathematical and others.

不同种类的工具,数学和其他。

This is by far not a complete list, nor are the descriptions ofthe modules very useful by themselves. GNU Radio code changes alot, so creating a static documentation would not be verysensible.

以上的列表没有完全的完成,因为GNU Raadio的代码经常改变。所以很难去做一个固定的文档。

Instead, you will have to use the good old Star Wars motto todelve further into the details of the modules: "Use the source!".If you feel GNU Radio should really already have some functionalityyou want to use, either browse through the module directory Pythonuses or go through the source directory of GNU Radio. Inparticular, pay attention to the directories starting withgr- in the source directory, such as gr-sounder orgr-radar-mono. These produce their own code and, consequently,their own modules.

上面的话的意思就是,如果你想用好GNURADIO的东西,不如直接去看源码,因为里边的信息更多。可以找模块目录的PYTHON来使用或者GNURADIO的源码目录。你应该注意gr-开头的源码目录。

Of course, Python itself comes with a lotof modules, some of which are extremely useful - if not necessary -to write GNU Radio applications. Check the Python documentation andthe SciPy website for more information.

Choosing, defining and configuring blocks¶

GNU Radio comes with an abundance of pre-defined blocks, so forbeginners, it is often quite confusing to find the correct blocksfor their applications and set them up correctly.

As with modules, the GNU Radio code changes around quite a bit,so a static documentation doesn't really make sense. However, thesituation is a bit different with blocks. First of all, there's theunofficial GNU Radio manual (based on GNU Radio 3.1.1) which can bedownloaded at

http://rapidshare.com/files/72169239/Simple-Gnuradio-User-Manual-v1.0.pdf

以上是一个非官方的GNU RADIO手册。

Thanks to the author for the massive effort!

Then, there's the automatically generated documentation. This iscreated by Doxygen from the source code. I recommend making thesedocs the same time as building the rest. Run./configure with the --enable-doxygenswitch for to create the docs when running make. Thelatter is particularly useful as it consists of multiple HTMLdocuments which can be browsed easily. If you don't want to createthe documents yourself or don't have topossibility to do so, you can find a version (although not anup-to-date one) on the web at http://gnuradio.org/doc/doxygen/hierarchy.html.The auto-generated docs are in your source directory beneathgnuradio-core/doc/html.
Learning how to use these documentations is a major part oflearning how to use GNU Radio!

Let's get practical. Here's the three lines from the previousexample which define the blocks:

1 src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, ampl)2 src1 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 440, ampl)3 dst  = audio.sink (sample_rate, "")

Here's a simplified version of what happens when this code isexecuted: First, a function called sig_source_f in themodule gr is executed. It receives four functionarguments:

  • sample_rate, which is a Python variable,
  • gr.GR_SIN_WAVE, which is a constant defined in the @gr'module,
  • 350, a normal literal constant,
  • ampl, another variable.

This function creates a class which is subsequently assigned tosrc0. The same happens on the other two lines,although the sink is fetched from a different module(audio).

So how did I know which block to use and what to pass togr.sig_source_f()? This is where the documentationcomes in. If you use the Doxygen-generated docs, click on the topleft tab called "Modules". Proceed to "Signal Sources". You willfind a list of signal generators, including thesig_source_* family. The suffix defines the data typeat the output:

  • f = float
  • c = complex float
  • i = int
  • s = short int
  • b = bits (actually an integer type)

These suffixes are used for all types of blocks, e.g.gr.fir_filter_ccf() will define an FIR filter withcomplex input, complex output and float taps, andgr.add_const_ss() will define a block which addsincoming short values with another, constant, short int.

后缀经常用来做各种block的类型,比如 gr.filter_ccf()表示FIR滤波器,复数输入,复数输出,和浮点tap

 

A list of all classes with a short description can be obtainedby clicking on the top tab called "Classes". The unofficial GNURadio manual lists all classes sorted by module and can be searchedusing your PDF reader of choice.
Most blocks you'll be using at the beginning are either from thegr, audio or usrp modules.So if you find a class called gr_sig_source_f in theauto-generated docs, you can create this class in Python by callinggr.sig_source_f().

At this point it is worth having a closer look behind thecurtains of GNU Radio. The reason you can easily use the blocks -written in C++ - in your Python code is because GNU Radio uses atool called SWIG to create an interface between Python and C++.Every block in C++ comes with a creating function, calledgr_make_*** (gr_make_sig_source_f() inthe example mentioned above). This function is always documented onthe same page as the matching class, and this function is what getsexported to Python, so gr.sig_source_f() in Pythoncalls gr_make_sig_source_f() in C++. For the samereason, it takes the same arguments - that's how you know how toinitialise a block in Python.

Once you're browsing the Doxygen documentation of the classgr_sig_source_f, you might notice many other classmethods, such as set_frequency(). These functions getexported to Python as well. So if you have created a signal sourceand want to change the frequency (say your application has a userfrequency control) you can use this method on your Python definedblock:

1     # We're in some cool application here2 3         src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, ampl)4     # Other, fantastic things happen here5 6     src0.set_frequency(880) # Change frequency

will change the frequency of the first signal generator to880Hz.

Hopefully, GNU Radio documentation will grow and become more andmore complete. But to completely understand the workings of blocksin detail, you will probably have to have a look at the code sooneror later, no matter how good the documentation gets.

Connecting blocks¶

Use the connect() method ofgr.top_block to connect blocks. Some things are worthmentioning:

  • You can only connect inputs and outputs if the data typesmatch. If you try to connect a float output with a complex input,you will get an error.
  • One output can be connected to several inputs; you don't needan extra block to duplicate signal paths.

These are basic rules for connecting blocks and they work inmost cases. However, when mixing data types some more notes areworth mentioning.

  • GNU Radio checks if input and output types match by checkingtheir size. If you happen to connect up ports with different typesbut the same size, you will most definitely get data junk.
  • When processing single bits, be careful. In some cases, youwill work with binary data in a usual sense, in other cases youwant to handle a specific number of bits at a time. Have a look atthe packed_to_unpacked* andunpacked_to_packed* blocks for this.
  • Be careful with dynamic ranges. When you're using float orcomplex data types, you have a larger range than you'll ever needconcerning the machine, but some sinks and sources have specificranges you need to stick to. For example, audio sinks requiresamples within +-1 and will clip anything outside this interval.The USRP sink on the other hand needs samples in the +-32767 range(signed 16 bit values) because that's the dynamic range of theDAC.

Hierarchical blocks¶

Sometimes it makes sense to combine several blocks into a newblock. Say you have several applications which all have a commonsignal processing component which consists of several blocks. Theseblocks can be combined into a new block, which in turn can be usedin your applications is if it were a normal GNU Radio block.

Example: Say you have two different flow graphs, FG1 and FG2.Both use - among others - the blocks B1 and B2. You want to combinethem to a hierarchical block called HierBlock:

  +-------------------+  |  +-----+  +----+  |--+--+ B1  +--+ B2 +--+---  |  +-----+  +----+  |  |     [[HierBlock]]     |  +-------------------+

This is what you do: create a flow graph which derives fromgr.hier_block2 and use self as source and sink:

 1 class [[HierBlock]](gr.hier_block2): 2     def __init__(self, audio_rate, if_rate): 3         gr.hier_block2.__init__(self, "HierBlock", 4                        gr.io_signature(1, 1, gr.sizeof_float), 5                        gr.io_signature(1, 2, gr.sizeof_gr_complex)) 6  7         B1 = gr.block1(...) # Put in proper code here! 8         B2 = gr.block2(...) 9 10         self.connect(self, B1, B2, self)

As you can see, creating a hierarchical block is very similar tocreating a flow graph with gr.top_block. Apart fromusing self as source and sink,there is another difference: the constructor for the parent class(called in line 3) needs to receive additional information. Thecall to gr.hier_block2.+init+() takes fourparameters:

  • self (which is always passed to theconstructor as first argument),
  • a string with an identifier for the hierarchical block (changeat your convenience),
  • an input signature and an
  • output signature.

The last two require some extra explanation unless you havealready written your own blocks in C++. GNU Radio needs to knowwhat types of input and output the block uses. Creating aninput/output signature can be done by callinggr.io_signature(), as is done here. This function calltakes 3 arguments:

  • minimum number of ports,
  • maximum number of ports and
  • size of the input/output elements.

For the hierarchical block HierBlock, you can seethat it has exactly one input and one or two outputs. The incomingobjects are of size float, so the block processesincoming real float values. Somewhere in B1 or B2, the data isconverted to complex float values, so the output signature declaresoutgoing objects to be of size gr.sizeof_gr_complex.The 'gr.sizeof_float@ and gr.sizeof_gr_complex areequivalent to the C++ return values of the sizeof()call. Other predefined constants are

  • gr.sizeof_int
  • gr.sizeof_short
  • gr.sizeof_char

Use gr.io_signature(0, 0, 0) to create a null IO signature, i.e.for defining hierarchical blocks as sources or sinks.

That's all. You can now use HierBlock as you woulduse a regular block. For example, you could put this code in thesame file:

 1 class FG1(gr.top_block): 2     def __init__(self): 3         gr.top_block.__init__(self) 4  5     ... # Sources and other blocks are defined here 6     other_block1 = gr.other_block() 7     hierblock    = [[HierBlock]]() 8     other_block2 = gr.other_block() 9 10     self.connect(other_block1, hierblock, other_block2)11 12     ... # Define rest of FG1

Of course, to make use of Pythons modularity, you could also putthe code for HierBlock in an extra file calledhier_block.py. To use this block from another file,simply add an import directive to your code:

1 from hier_block import [[HierBlock]]

and you can use HierBlock as mentioned above.

Examples for hierarchical blocks:

gnuradio-examples/python/usrp/fm_tx4.pygnuradio-examples/python/usrp/fm_tx_2_daughterboards.pygnuradio-examples/python/digital/tx_voice.py

Multiple flow graphs¶

In some cases, you might want to have completely separate flowgraphs, e.g. for receive and transmit paths (see the example'Walkie-Talkie' above). Currently (June 2008), it is not possibleto have multiple top_blocks running at the same time, but what youcan do is create full flow graphs as hierarchical blocks usinggr.hier_block2 like in the section above. Then, createa top_block to hold the flow graphs.

Example:

 1 class transmit_path(gr.hier_block2): 2     def __init__(self): 3                 gr.hier_block2.__init__(self, "transmit_path", 4                                 gr.io_signature(0, 0, 0), # Null signature 5                                 gr.io_signature(0, 0, 0)) 6  7         source_block = gr.source() 8         signal_proc  = gr.other_block() 9         sink_block   = gr.sink()10 11         self.connect(source_block, signal_proc, sink_block)12 13 class receive_path(gr.hier_block2):14     def __init__(self):15                 gr.hier_block2.__init__(self, "receive_path",16                                 gr.io_signature(0, 0, 0), # Null signature17                                 gr.io_signature(0, 0, 0))18 19         source_block = gr.source()20         signal_proc  = gr.other_block()21         sink_block   = gr.sink()22 23         self.connect(source_block, signal_proc, sink_block)24 25 class my_top_block(gr.top_block):26     def __init__(self):27         gr.top_block.__init__(self)28 29     tx_path = transmit_path()30 31     rx_path = receive_path()32 33     self.connect(tx_path)34     self.connect(rx_path)

Now, when you start my_top_block, both flow graphsare started in parallel. Note that the hierarchical blocks haveexplicitly no inputs and outputs defined, they have a null IOsignature. Consequently, they don't connect to self as source or sink; they rather define theirown sources or sink (just as you would do when defining ahierarchical block as source or sink). The top block simplyconnects the hierarchical blocks to itself,but does not connect them up in any way.

Examples for multiple flow graphs:

gnuradio-examples/python/usrp/usrp_nbfm_ptt.py

GNU Radio extensions and tools¶

GNU Radio is more than blocks and flow graphs - it comes with alot of tools and code to help you write DSP applications.

A collection of useful GNU Radio applications designed to aidyou is in gr-utils/.
Browse the source code in gnuradio-core/src/python/gnuradio to findutilities you can use in your Python code such as filter designcode, modulation utilities and more.

Controlling flow graphs¶

If you have followed the tutorial so far, you will have noticedthat a flow graph has always been implemented as a class, derivedfrom gr.top_block. The question remains on how tocontrol one of these classes.

As mentioned before, deriving the class from gr.top_block bringsalong all the functionality you might need. To run or stop anexisting flow graph, use the following methods:

run()The simplest way to run a flow graph. Calls start(), thenwait(). Used to run a flow graph that will stop on its own, or torun a flow graph indefinitely until SIGINT is received.start()Start the contained flow graph. Returns to the caller once thethreads are created.stop()Stop the running flow graph. Notifies each thread created bythe scheduler to shutdown, then returns to caller.wait()Wait for a flow graph to complete. Flowgraphs complete wheneither (1) all blocks indicate that they are done, or (2) afterstop has been called to request shutdown.lock()Lock a flow graph in preparation for reconfiguration.unlock()Unlock a flow graph in preparation for reconfiguration. When anequal number of calls to lock() and unlock() have occurred, theflow graph will be restarted automatically.

See the documentation for gr_top_block for moredetails.

Example:

 1 class my_top_block(gr.top_block): 2     def __init__(self): 3         gr.top_block.__init__(self) 4     ... # Define blocks etc. here 5  6 if __name__ == '__main__': 7     my_top_block().start() 8     sleep(5) # Wait 5 secs (assuming sleep was imported!) 9     my_top_block().stop()10     my_top_block().wait() # If the graph is needed to run again, wait() must be called after stop11     ... # Reconfigure the graph or modify it12     my_top_block().start() # start it again13     sleep(5) # Wait 5 secs (assuming sleep was imported!)14     my_top_block().stop()  # since (assuming) the graph will not run again, no need for wait() to be called

These methods help you to control the flow graph from theoutside. For many problems this might not be enough: you don'tsimply want to start or stop a flow graph, you want to reconfigurethe way it behaves. For example, imagine your application has avolume control somewhere in your flow graph. This volume control isimplemented by inserting a multiplier into the sample stream. Thismultiplier is of type gr.multiply_const_ff. If youcheck the documentation for this kind of of block, you will find afunction gr.multiply_const_ff.set_k() which sets themultiplication factor.
You need to make the settings visible to the outside in order tocontrol it. The simplest way is to make the block an attribute ofthe flow graph class.

Example:

 1 class my_top_block(gr.top_block): 2     def __init__(self): 3         gr.top_block.__init__(self) 4     ... # Define some blocks 5     self.amp = gr.multiply_const_ff(1) # Define multiplier block 6     ... # Define more blocks 7  8         self.connect(..., self.amp, ...) # Connect all blocks 9 10     def set_volume(self, volume):11     self.amp.set_k(volume)12 13 if __name__ == '__main__':14     my_top_block().start()15     sleep(2) # Wait 2 secs (assuming sleep was imported!)16     my_top_block.set_volume(2) # Pump up the volume (by factor 2)17     sleep(2) # Wait 2 secs (assuming sleep was imported!)18     my_top_block().stop()

This example runs the flow graph for 2 seconds and then doublesthe volume by accessing the amp block through a memberfunction called set_volume(). Of course, one couldhave accessed the amp attribute directly, omitting themember function.

Hint: making blocks attributes of the flow graph is generally agood idea as it makes extending the flow graph with extra memberfunctions easier.

Non-flow graph centred applications¶

Up until now, GNU Radio applications in this tutorial havealways been centred around the one class derived fromgr.top_block. However, this is not necessarily how GNURadio needs to be used. GNU Radio was designed to develop DSPapplications from Python, so there's no reason to not use the fullpower of Python when using GNU Radio.

Python is an extremely powerful language, and new libraries andfunctionalities are constantly being added. In a way, GNU Radioextends Python with a powerful, real-time-capable DSP library. Bycombining this with other libraries you have immense functionalityright there at your fingertips. For example, by combining GNU Radiowith SciPy, a collection of scientific Python libraries, you canrecord RF signals in real time and do extensive mathematicaloperations off line, save statistics to a database and so on - allin the same application. Even expensive engineering software suchas Matlab might become unnecessary if you combine all theselibraries.

http://www.scipy.org/

Advanced Topics¶

If you have really read the previous sections, you already knowenough to write your first Python GNU Radio applications. Thissection will adress some slightly more advanced functionalities forPython GNU Radio applications.

Dynamic flow graph creation¶

For most cases, the aforementioned way to define flow graphs iscompletely adequate. If you need more flexibility in yourapplication, you might want to have even more control over the flowgraph from outside the class.
This can be achieved by taking the code out of the+init+() function and simply usinggr.top_block as a container. Example:

 1     ... # We are inside some application 2     tb = gr.top_block() # Define the container 3  4     block1 = gr.some_other_block() 5     block2 = gr.yet_another_block() 6  7     tb.connect(block1, block2) 8  9     ... # The application does some wonderful things here10 11     tb.start() # Start the flow graph12 13     ... # Do some more incredible and fascinating stuff here

If you are writing some application which needs to dynamicallystop a flow graph (reconfigure it, re-start it and so) on thismight be a more practical way to do it.

Examples for this kind of flow graph setup:

gnuradio-examples/python/apps/hf_explorer/hfx2.py

Command Line Options¶

Python has its own libraries to parse command line options. Seethe documentation for the module optparse to find outhow to use it.

GNU Radio extends optparse by new command line option types. Use@from gnuradio.eng_option import eng_option' to import thisextension. With eng_option, you have the following types:

eng_floatLike the original float option, but also accepts engineeringnotation like 101.8MsubdevOnly accepts valid subdevice descriptors such as A:0 (Tospecify a daughterboard on a USRP)intxOnly accepts integers

If your application supports command line options, it would beever so nice if you could stick to the GNU Radio conventions forcommand line options. You can find these (along with more hints fordevelopers) in README.hacking.

Nearly every GNU Radio example uses this feature. Trydial_tone.py for an easy example.

Graphical User Interfaces¶

If you are a Python expert and also have some experience inwriting GUIs for Python (using whatever GUI toolkit you like), youmight not even need this section. As mentioned before, GNU Radiomerely extends Python with DSP routines - so if you like, just goahead and write a GUI application, add a GNU Radio flow graph to itand define some interfaces to carry GNU Radio information to yourapplication and vice versa. If you want to plot your data, youcould use Matplotlib or Qwt.

However, sometimes you simply want to write a quick GUIapplication without bothering with setting up widgets, defining allthe menus etc. GNU Radio comes with some predefined classes to helpyou write graphical GNU Radio applications.

These modules are based on wxWidgets (or to be precise,wxPython), a platform-independent GUI toolkit. You will need somebackground in wxPython - but don't worry, it is not thatcomplicated and there are several tutorials available on the net.Check the wxPython website for documentation (http://www.wxpython.org/).

To use the GNU Radio wxWidgets tools, you need to import somemodules:

1 from gnuradio.wxgui import stdgui2, fftsink2, slider, form

Here, 4 components were imported from the gnuradio.wxguisubmodule. Here's a quick list of the modules (again, notnecessarily complete. You will have to browse the modules or thesource code in gr-wxgui/src/python).

stdgui2Basic GUI stuff, you always need thisfftsink2Plot FFTs of your data to create spectrum analyzers orwhateverscopesink2Oscilloscope outputwaterfallsink2Waterfall outputnumbersink2Displays numerical values of incoming dataformOften used input forms (see below)

Next, we have to define a new flow graph. This time, we don'tderive from gr.top_block but fromstdgui2.std_top_block:

1 class my_gui_flow graph(stdgui2.std_top_block):2         def __init__(self, frame, panel, vbox, argv):3                 stdgui2.std_top_block.__init__ (self, frame, panel, vbox, argv)

As you can see, there's another difference: the constructor getsa couple of new parameters. This is because astdgui2.std_top_block does not only include flow graphfunctionality (it is derived from gr.top_block itself), but also directly creates a window with somebasic components (like a menu). This is good news for all of thosewho just want to quickly hack a graphical application: GNU Radiocreates the window and everything, you just need to add thewidgets. Here's a list of what you can do with these new objects(this probably won't mean much to you if you have no idea about GUIprogramming):

frameThe wx.Frame of your window. You can get at the predefined menuby using frame.GetMenuBar()panelA panel, placed in @frame', to hold all your wxControlwidgetsvboxA vertical box sizer (wx.BoxSizer(wx.VERTICAL) is how it isdefined), used to align your widgets in the panelargvThe command line arguments

Now you have all you need to create your GUI. You can simply addnew box sizers and widgets to vbox, change the menu or whatever.Some typical functions have been simplified further in the GNURadio GUI library form.

form has a great number of input widgets:form.static_text_field() for static text field(display only), form.float_field(), to input floatvalues, form.text_field() to input text,form.checkbox_field() for checkboxes,form.radiobox_field() for radioboxes etc. Check thesource code of gr-wxgui/src/python/form.py for the complete list.Most of these calls pass most of their arguments to the appropriatewxPython objects, so the function arguments are quite self-explanatory.
See one of the examples mentioned below on how to add widgets usingform.

Probably the most useful part of gnuradio.wxgui isthe possibility to directly plot incoming data. To do this, youneed one of the sinks that come with gnuradio.wxgui,such as fftsink2. These sinks work just as any otherGNU Radio sink, but also have properties needed for use withwxPython. Example:

 1 from gnuradio.wxgui import stdgui2, fftsink2 2  3 # App gets defined here ... 4  5 # FFT display (pseudo-spectrum analyzer) 6 my_fft = fftsink2.fft_sink_f(panel, title="FFT of some Signal", fft_size=512, 7              sample_rate=sample_rate, ref_level=0, y_per_div=20) 8 self.connect(source_block, my_fft) 9 vbox.Add(my_fft.win, 1, wx.EXPAND)

First, the block is defined (fftsink2.fft_sink_f).Apart from typical DSP parameters such as the sampling rate, italso needs the panel object which is passed to theconstructor. Next, the block is connected to a source. Finally, theFFT window (my_fft.win) is placed inside thevbox BoxSizer to actually display it. Remember that asignal block output can be connected to any amount of inputs.

Finally, the whole thing needs to be started. Because we need anwx.App() to run the GUI, the startup code is a bitdifferent from a regular flow graph:

1 if __name__ == '__main__':2     app = stdgui2.stdapp(my_gui_flow_graph, "GUI GNU Radio Application")3     app.MainLoop()

stdgui2.stdapp() creates the wx.Appwith my_gui_flow_graph (the first argument). Thewindow title is set to "GUI GNU Radio Application".

Examples for simple GNU Radio GUIs:

gr-utils/src/python/usrp_fft.pygr-utils/src/python/usrp_oscope.pygnuradio-examples/python/audio/audio_fft.pygnuradio-examples/python/usrp/usrp_am_mw_rcv.py

And many more.

原创粉丝点击