Sie sind auf Seite 1von 44

Developing Signal Processing Blocks for

Software-defined Radios
by Gunjan Verma and Paul Yu

ARL-TR-5897

Approved for public release; distribution unlimited.

January 2012

NOTICES
Disclaimers
The findings in this report are not to be construed as an official Department of the Army position
unless so designated by other authorized documents.
Citation of manufacturers or trade names does not constitute an official endorsement or
approval of the use thereof.
Destroy this report when it is no longer needed. Do not return it to the originator.

Army Research Laboratory


Adelphi, MD 20783-1197

ARL-TR-5897

January 2012

Developing Signal Processing Blocks for


Software-defined Radios
Gunjan Verma and Paul Yu
Computational and Information Sciences Directorate, ARL

Approved for public release; distribution unlimited.

Form Approved
OMB No. 0704-0188

REPORT DOCUMENTATION PAGE

Public reporting burden for this collection of information is estimated to average 1 hour per response, including the time for reviewing instructions, searching existing data sources, gathering and maintaining the
data needed, and completing and reviewing the collection information. Send comments regarding this burden estimate or any other aspect of this collection of information, including suggestions for reducing the
burden, to Department of Defense, Washington Headquarters Services, Directorate for Information Operations and Reports (0704-0188), 1215 Jefferson Davis Highway, Suite 1204, Arlington, VA 22202-4302.
Respondents should be aware that notwithstanding any other provision of law, no person shall be subject to any penalty for failing to comply with a collection of information if it does not display a currently
valid OMB control number.

PLEASE DO NOT RETURN YOUR FORM TO THE ABOVE ADDRESS.


1. REPORT DATE (DD-MM-YYYY)

2. REPORT TYPE

January 2012

Final

3. DATES COVERED (From - To)

4. TITLE AND SUBTITLE

5a. CONTRACT NUMBER

Developing Signal Processing Blocks for Software-defined Radios


5b. GRANT NUMBER

5c. PROGRAM ELEMENT NUMBER

6. AUTHOR(S)

5d. PROJECT NUMBER

Gunjan Verma and Paul Yu


5e. TASK NUMBER

5f. WORK UNIT NUMBER

7. PERFORMING ORGANIZATION NAME(S) AND ADDRESS(ES)

8. PERFORMING ORGANIZATION
REPORT NUMBER

U.S. Army Research Laboratory


ATTN: RDRL-CIN-T
2800 Powder Mill Road
Adelphi, MD 20783-1197

ARL-TR-5897

9. SPONSORING/MONITORING AGENCY NAME(S) AND ADDRESS(ES)

10. SPONSOR/MONITOR'S ACRONYM(S)

11. SPONSOR/MONITOR'S REPORT


NUMBER(S)

12. DISTRIBUTION/AVAILABILITY STATEMENT

Approved for public release; distribution unlimited.


13. SUPPLEMENTARY NOTES

14. ABSTRACT

Software-defined radios (SDRs) provide researchers with a powerful and flexible wireless communications experimentation
platform. GNU Radio is the most popular open-source software toolkit for deploying SDRs, and is frequently used with the
Universal Software Radio Peripheral (USRP). After establishing a USRP testbed, the researcher will need to implement new
signal processing algorithms or modify existing ones. This document describes this process, highlighting those details that
have received minimal attention in the existing documentation.

15. SUBJECT TERMS

Software radios, CHU Radio, USRP Ubuntu


17. LIMITATION
OF ABSTRACT

16. SECURITY CLASSIFICATION OF:


a. REPORT

Unclassified

b. ABSTRACT

Unclassified

c. THIS PAGE

UU

18. NUMBER
OF PAGES

44

19a. NAME OF RESPONSIBLE PERSON

Gunjan Verma

19b. TELEPHONE NUMBER (Include area code)

(301) 394-3102

Unclassified

Standard Form 298 (Rev. 8/98)


Prescribed by ANSI Std. Z39.18

ii

Contents
1. Introduction

2. Implementation of Blocks

2.1 Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.2 Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.2.1

Block Signatures . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.2.2

Boost Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.3 Case Study: gr_block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.3.1

Function: general_work() . . . . . . . . . . . . . . . . . . . . . . . .

2.3.2

Functions: forecast() and set_history() . . . . . . . . . . . . . . . . .

2.3.3

Field: d_output_multiple . . . . . . . . . . . . . . . . . . . . . . . .

2.3.4

Field: d_relative_rate . . . . . . . . . . . . . . . . . . . . . . . . . .

3. Creation of SWIG Interfaces

3.1 Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.1.1

Block Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.1.2

Boost Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.2 SWIG Interface File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11

4. Installation of Blocks

12

4.1 Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

4.2 Preparing Makefile.am for Autotools . . . . . . . . . . . . . . . . . . . . . .

13

4.3 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

iii

5. Usage of Blocks

15

5.1 Invoking from Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15

5.2 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15

5.3 Simplifying the Build

16

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6. Conclusion

16

A. The gr_block.h Script

17

B. The blockWizard.py Script

25

Distribution

35

iv

List of Tables
1

Arguments of general_work() . . . . . . . . . . . . . . . . . . . . . . . . . .

Contents of newBlock directory in GNU Radio . . . . . . . . . . . . . . . . .

13

INTENTIONALLY LEFT BLANK

vi

1.

Introduction

Software-defined radios (SDRs) provide researchers with a powerful and flexible wireless
communications experimentation platform. GNU Radio is the most popular open-source
software toolkit for deploying. Every SDR is comprised of software and hardware. In this
document, we consider GNU Radio software coupled with Universal Software Radio
Peripheral (USRP) hardware. In GNU Radio, C++ blocks perform specific signal
processing processing tasks, while Python applications connect the blocks together to
form a functional software radio. For example, a basic transmitter can be implemented by
using Python to connect the following C++ blocks (which already exist in the GNU Radio
software library) together: modulator, mixer, and amplifier.
Each block specifies its input and output requirements, both in number and type. For
example, the gr_add_cc block adds two complex input streams and copies the results onto
one complex output stream. Blocks are generally implemented in C++ for computational
efficiency, but other possibilities exist (see below).
After writing a new block, a process is needed to expose these C++ blocks for use by
Python scripts. GNU Radio uses the Simplified Wrapper and Interface Generator (SWIG),
to generate the necessary components to make C++ blocks accessible from Python.
From the standpoint of Python applications, each block consumes its input stream(s),
performs a specific task, and generates output stream(s). As long as the connections
between blocks are compatible, there is no restriction to how many blocks can be chained
together. A single output stream can connect to multiple input streams, but multiple
outputs cannot connect to a single input due to ambiguity. A multiplexer can be used in
such a situation by interleaving many inputs onto a single output.
In summary, the stages of block creation in GNU Radio are the following:
1. Implementation of blocks (C++), the
(.h, .cc) files
2. Creation of SWIG interfaces between C++/Python, the
(.i) file
3. Installation of blocks into a shared library
4. Usage of blocks in an application (Python), the
(.py) file

In this report, we detail steps 14. This report is an updated and expanded presentation of
the material found in
http://www.gnu.org/software/gnuradio/doc/howto-write-a-block.html.

2.

Implementation of Blocks

Before diving into block implementation, we first introduce the naming conventions of
GNU Radio in section 2.1. Section 2.2 introduces the most commonly used data types, and
section 2.3 steps through the essential elements of block creation by using the illustrative
example of gr_block.
2.1

Naming Conventions

There are several strongly followed conventions in GNU Radio, and a familiarity with these
expedites code writing and understanding.
All words in identifiers are separated by an underscore, e.g., gr_vector_int.
All types in the GNU Radio package are preceded by gr, e.g., gr_float.
All class variables are preceded with d_, e.g., d_min_streams.
Each classes is implemented in a separate file, e.g., class gr_magic is implemented in
gr_magic.cc with the header file gr_magic.h.
All signal processing blocks contain their input and output types in their suffixes,
e.g., gr_fft_vcc requires complex inputs and complex outputs. The major types are
float (f), complex (c), short (s), integer (i). Any type may be vectorized (v).
2.2

Data Types

GNU Radio type defines the most commonly used data types to a set of names. The main
purpose of this is to create a common set of conventions for naming of data types. The list
is as follows:
typedef
typedef
typedef
typedef

std::complex<float>
std::complex<double>
std::vector<int>
std::vector<float>

gr_complex;
gr_complexd;
gr_vector_int;
gr_vector_float;
2

typedef
typedef
typedef
typedef
typedef
typedef
typedef
2.2.1

std::vector<double>
std::vector<void *>
std::vector<const void *>
short
int
unsigned short
unsigned int

gr_vector_double;
gr_vector_void_star;
gr_vector_const_void_star;
gr_int16;
gr_int32;
gr_uint16;
gr_uint32;

Block Signatures

A block signature is simply a specification of the data types that enter and exit a signal
processing block. In list 1, we can examine gr_io_signature.h for more detail.
Listing 1. gr_io_signature.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

class gr_io_signature {
d_min_streams ;
in t
d_max_streams ;
in t
d_si zeo f _strea m _i tem ;
s t d : : v e c t o r <int>
g r _ i o _ s i g n a tu r e ( in t min_streams , in t max_streams ,
const s t d : : v e c t o r <int> &s i z e o f _ s t r e a m _ i t e m s ) ;
f r ien d g r _ i o _ s i g na t ur e _ s p tr
gr_make_io_signa turev ( in t min_streams ,
in t max_streams ,
const s t d : : v e c t o r <int> &s i z e o f _ s t r e a m _i te m s ) ;
public :
s t a t i c const in t IO_INFINITE = 1;
~gr_io_signature ( ) ;
in t
in t
in t
std

min_streams ( ) const { return d_min_streams ; }


max_streams ( ) const { return d_max_streams ; }
si zeo f _s t r ea m _i t e m ( in t i ndex ) const ;
: : v e c t o r <int> s i z e o f _ s t r e a m _ i t e m s ( ) const ;

};

It is important to realize that our block has two signatures, one for the input interface and
one for the output interface. The header file makes it clear that, for a given interface,
gr_io_signature defines the minimum and maximum number of streams flowing through
that interface, as well as the number of bytes in a single element of the stream. Recall that
Python is used to connect multiple signal processing blocks together. The main purpose of
signatures is so Python can raise an error for improper connections.

The following are examples of improper connections:


Too {many/few} {input/output} connections for a block
Type mismatch, e.g., gr_complex output connected to gr_int16 input
2.2.2

Boost Pointers

GNU Radio uses Boost smart pointers instead of regular C++ pointers. Boost is a
high-quality software library with many extensions to the basic C++ language. For our
purposes, Boost provides a smart implementation of C++ pointers that offers garbage
collection, i.e., it deletes dynamically allocated objects when they are no longer needed.
This simplifies our implementation efforts and improves block performance. There are
actually many different types of smart pointers, but GNU radio uses just one of them,
called a shared_ptr, which is used specifically when our dynamically allocated object has
ownership shared by several pointers.
In order to declare a regular C++ pointer to an object of type gr_io_signature, we
would use the followig command:
gr_io_signature* ptr;
Whereas with Boost, we would use this command:
typedef boost::shared_ptr<gr_io_signature> gr_io_signature_sptr;
gr_io_signature_sptr ptr;
to declare a Boost shared pointer.
As shown in the above code, GNU Radio uses the convention of type defining Boost smart
pointers to an object of type X as X_sptr. This format makes it explicit to the user that
X_sptr is a Boost smart pointer.
2.3

Case Study: gr_block

GNU Radio makes extensive use of the notion of inheritance, an object oriented (OO)
programming technique. For us, this simply means that every signal processing block is a
specialization of a general, high-level block, which GNU Radio calls gr_block. Our task is
to fill in the details of gr_block (referred to in OO-speak as deriving from the base
4

class) to create our own custom block. It is prudent to begin our study of writing a new
block by first examining gr_block.h.
The class gr_block is itself derived from the class gr_basic_block.h. We consider a few
of the fields that are of particular interest to programmer and discuss the fields inherited
from gr_basic_block.h and defined gr_block.h (lists 2 and 3). The entire gr_block.h
file is shown in appendix A.
Listing 2. gr_basic_block.h
70
71
72
73

std : : stri ng
g r _ i o _ s i g n a t u r e _s p t r
g r _ i o _ s i g n a t u r e _s p t r
long

d_name ;
d_i nput_si g na ture ;
d_o utput_si g na ture ;
d_unique_id ;

Listing 3. gr_block.h
229
230
231
232

private :
in t
double
input_rate

d_o utput_m ultiple ;


d_relative_rate ;

// appr ox o u t p u t _ r a t e /

The fields d_name and d_unique_id are unique identifiers (text and numeral, respectively)
for the block and can be used for debugging. The d_output_multiple and
d_relative_rate fields inform the schedule of the blocks rate of data consumption and
generation (see sections 2.3.3 and 2.3.4).
Note that d_input_signature, d_output_signature, and d_detail are all Boost smart
pointers, the former pointing to gr_io_signature objects, the latter to a
gr_block_detail object. The comments above highlight the purpose of the various fields;
we explain in more detail in what follows.
As seen in list 4, gr_block has the following important functions.
Listing 4. gr_block.h
82
105
106
122
123
124
125
157

void s e t _ h i s t o r y ( unsigned h i s t o r y ) { d_hi sto ry = h i s t o r y ; }


vir t u al void f o r e c a s t ( in t noutput_items ,
g r_vec to r _i n t &ni nput_i tem s_ re qu i re d ) ;
t
u
al
in
t
g
enera
l
_wo
rk
( in t noutput_items ,
vir
g r_vect o r _i n t &ni nput_items ,
g r_vecto r_co nst _vo i d_st a r &i nput_i tem s ,
g r_vecto r_vo i d_s ta r &o utput_i tem s ) = 0 ;
void consume ( in t which_input , in t how_many_items ) ;

In the remainder of this section, we detail each of these functions. It is useful to think of
the process of writing a new block as a two-way street between our block and the GNU
5

Radio internals, collectively referred to herein as the scheduler. The scheduler gives us
data from the USRP, on which our block performs signal processing. In turn, our block
tells the scheduler how much processing weve done and how much more input we need to
produce more output, so the scheduler knows what data it no longer needs to store, how
much buffer memory to allocate, when to schedule our block to execute next, etc. This, in
turn, determines when the scheduler will invoke our block next and with how much input.
2.3.1

Function: general_work()

The general_work() function plays a central role in new block creation. It implements the
process of converting the input stream(s) to the output stream(s). Table 1 explains the
purpose of the arguments to this function.
Table 1. Arguments of general_work().
Argument
noutput_items
ninput_items
input_items
output_items

Purpose
Number of output items to write on each output stream
Number of input items available on each input stream
Vector of pointers to elements of the input stream(s), i.e.,
element i of this vector points to the ith input stream
Vector of pointers to elements of the output stream(s), i.e.,
element i of this vector points to the ith output stream

Recall that we stated earlier that a signal processing block may have multiple input and/or
output streams. So, ninput_items is vector whose ith element is the number of available
items on the ith input stream. However, noutput_items is a scalar, not a vector, because
GNU Radio implementation forces the number of output items to write on each output
stream to be the same. The returned value of general_work() is the number of items
actually written to each output stream, or -1 on end of file (EOF).
To create a block, we simply define how to create output_items from input_items,
assuming that all parameters are provided to us. That is, we implement the signal
processing algorithm in this method. The scheduler invokes the concrete
implementation of general_work with the appropriate parameters. We do not have to
explicitly invoke general_work; we only need to define it.
After we have defined general_work for our custom signal processing block, we need to
invoke the consume() function to indicate to the scheduler how many items
(how_many_items) have been processed on each (which_input) input stream. Recall that
the scheduler is providing us all the appropriate parameters for us to write our own block;
we need to provide feedback to the scheduler so it knows which elements have been used,
6

so it can mark appropriate memory for deletion or reuse, and update pointers to point to
new data. This feedback of our signal processing progress is provided to the scheduler via
the consume function.
2.3.2

Functions: forecast() and set_history()

The forecast() function is our way of telling the scheduler our estimate of the number of
input elements that will be needed to create an output element. For example, a decimating
filter of order 5 requires five inputs to produce one output. The key argument is
ninput_items_required, which is a vector specifying the number of input items required
on each input stream to produce noutput_items number of outputs on each output
stream. In some cases, like the decimating filter of specified order, we may know this
number exactly. In other cases, we may need to estimate it. When the scheduler
determines it is ready to handle noutput_items more items on the output streams, it
invokes the forecast function to determine whether or not we have enough input items to
call general_work. For example, an interpolator will produce multiple outputs for a single
input, while a decimator will produce a single output for multiple inputs. If we have a
10-to-1 decimator but only 9 inputs are available, the scheduler will not call general_work
if the forecast function is correctly implemented.
There is an important distinction to make here. Another common requirement, such as for
a moving average filter that averages the five most recent inputs to produce a single
output, is the need to process multiple input samples to yield a single output sample. It
may seem as if our forecast function should specify this. However, in this case, while the
moving average filter uses five inputs to produce one output, it does not require five new
inputs; it still only consumes a single new input to produce a single new output. So, our
forecast function, in this case, would still call for a one-to-one relation of noutput_items
to ninput_items_required. In this case, the fact that we need the five most recent inputs
would be specified to GNU Radio via the set_history(5) function call.
2.3.3

Field: d_output_multiple

By now, we have seen that the GNU Radio scheduler is responsible for invoking
general_work and forecast. The forecast() function allows us to signal to the
scheduler to invoke our general_work function only when a sufficient number of input
elements are in the input buffer. But we have not seen any such mechanism to control the
number of outputs being produced. Recall the argument noutput_items in the forecast
function. It it specified by the scheduler and contains how many output items to produce
on each stream. While we cannot directly set this value (it is under the schedulers
control), there is a variable d_output_multiple that tells the scheduler that the value of
7

noutput_items must be an integer multiple of d_output_multiple. In other words, the


scheduler only invokes forecast() and general_work() if noutput_items is an integer
multiple of d_output_multiple. The default value of d_output_multiple is 1. Suppose,
for instance, we are interested in generating output elements only in 64-element chunks. By
setting d_output_multiple to 64, we can achieve this, but note that we may also get any
multiple of 64, such as 128 or 192, instead.
The following functions allow us to set and get the value of d_output_multiple:
void
int
2.3.4

gr_block::set_output_multiple (int multiple);


output_multiple ();

Field: d_relative_rate

Recall our description of block creation as involving a two-way communication with the
scheduler. The d_relative_rate field is the way we tell the scheduler the approximate
ratio of output rate to input rate at which we expect our signal processing algorithm to
operate. The key purpose of d_relative_rate is to allow the scheduler to optimize its use
memory and timings of invocation of general_work. For many blocks, d_relative_rate
is 1.0 (the default value), but decimators will have a value less than 1.0 and interpolators
greater than 1.0.
The functions used to set and get the value of d_relative_rate are given below:
void
gr_block::set_relative_rate (double relative_rate);
double relative_rate ();

3.

Creation of SWIG Interfaces

In what follows, we strongly urge the reader to download the file


gr-howto-write-a-block-3.3.0.tar.gz from ftp.gnu.org/gnu/gnuradio/ and extract the
archive. This archive contains sample code related to creating a new block, which we refer
to.
3.1

Naming Conventions

Before getting into the details of block creation, let us start with a note about some
important naming conventions.
8

3.1.1

Block Names

After we create our new block, the only way we can use it in GNU Radio is to create a
Python script, which loads the package/module containing the block, and then connect our
block into a GNU Radio flowgraph, as usual. This would involve Python code resembling
the following:
from package_name import module_name
...
nb = module_name.block_name()
...
There is a key coupling between the module and block names that we invoke in Python,
and the names used in coding blocks in C++. Namely, GNU Radio expects that all C++
source and header files are in the form [module_name]_[block_name].h and
[module_name]_[block_name].cc . That is, if we decided to name our C++ class
newModule_newBlock, then GNU Radios build system would make our block available
from Python in module newModule and with block name newBlock. So while in theory
there is no need for such a coupling of naming schemes, in practice, such a coupling does
exist.
3.1.2

Boost Pointers

We have mentioned earlier that all pointers to GNU Radio block objects must use Boost
shared pointers not regular C++ pointers. In other words, if we create a new C++
signal processing block called newModule_newBlock, then GNU radios internal
implementation will not work if we use a pointer to newBlock_newFunction in our code.
In other words, the command
newModule_newBlock* nb = new newModule_newBlock()
is not permitted. This is enforced by making all block constructors private and ensures
that a regular C++ pointer can never point to a block object. But if the constructor is
private, how do we create new instance of our block? After all, we need some sort of public
interface for creating new block instances. The solution is to declare a friend function,
which acts as a surrogate constructor. This is achieved by first declaring a friend function
of the class, so it has access to all private members, including the private constructor. This
friend function invokes the private constructor and returns a smart pointer to it. Second,
we invoke this friend function every time we want to construct a new object.
9

Suppose the name of our new signal processing block is newModule_newBlock_cc. Then,
we would create a file newModule_newBlock_cc.cc, in which we would include the
following function declaration:

typedef boost::shared_ptr<newModule_newBlock_cc> newModule_newBlock_cc_sptr;


friend newNodule_newBlock_cc_sptr newModule_make_newBlock_cc()
Now, the function newModule_newBlock_make_cc() has access to private members of the
class newModule_newBlock_cc. So from within this function, we call the private
constructor of newModule_newBlock_cc, in order to create a new instance of our block.
The final step is to cast the returned pointers data type from a raw C++ pointer to a
smart pointer
newNodule_newBlock_cc_sptr newModule_make_newBlock_cc() () {
return newNodule_newBlock_cc_sptr (new newModule_newBlock_cc());
}
The private constructor (which we cannot invoke directly), on the other hand, would look
something like this.
newNodule_newBlock_cc ()
{
gr_block (newBlock_cc",
gr_make_io_signature (1, 1, sizeof (gr_complex)),
gr_make_io_signature (1, 1, sizeof (gr_complex))
)
}
So to summarize, the private constructor is actually creating a new gr_block object. The
friend constructor, the public interface to the private constructor, acts as a surrogate by
wrapping the new object created by the private constructor into a Boost shared pointer.
This convoluted procedure guarantees that all pointers to blocks are Boost smart pointers.
The public interface to creating objects is not the object constructor
newModule_newBlock_cc, but rather the surrogate constructor
newModule_newBlock_make_cc.
Then, in our code, we must create a new block object using the code

10

newModule_newBlock_cc_sptr nb = newModule_make_newBlock_cc()
Here is an important point: if ones block name is newModule_newBlock_cc, then the name
of the shared pointer to this block MUST be newModule_newBlock_cc_sptr. Any other
choice, such as nb_nf_sptr, would lead to the block not working properly. This has
nothing to do with C++, since any valid name will work. Rather, when this C++ block is
invoked from Python in a GNU Radio program, GNU Radio expects the shared pointer
name to follow directly from the block name with an _sptr added on, or else it will
complain that it cannot find the block.
Also, the surrogate constructor that creates a shared pointer to newModule_newBlock_cc
must have signature
newModule_newBlock_cc_sptr newModule_make_newBlock_cc()
Note the presence of the word make between the newModule and newBlock words. Thus,
consider the naming of shared pointers to block objects, as well as the friend functions
(surrogate constructors) that create them, not as a convention but as rule to be followed.
3.2

SWIG Interface File

Once we have created our .cc and .h files, the next step is to create the SWIG (.i) file, so
we can expose our new block to Python. SWIG is used to generate the necessary glue, as
it is often called, to allow Python and C++ to stick together in a complete GNU Radio
application. The purpose of the .i file is to tell SWIG how it should go about creating this
glue.
A .i file is very similar to a .h file in C++ in that it declares various functions. However,
the .i file only declares the functions that we want to access from Python. As a result, the
.i file is typically quite short in length.
We illustrate an actual .i file in list 5, called gr_multiply_const_ff.i.
Listing 5. gr_multiply_const_ff.i
1 /
2
GR_SWIG_BLOCK_MAGIC is a f u n c t i o n w hi ch a l l o w s us t o i n v o k e our b l o c k
3
g r _ m u l t i p l y _c o n s t _ f f _f r o m P y t h o n a s g r . m u l t i p l y _ c on s t _ c c ( )
4
I t s f i r s t argument , gr , w i l l b e c o m e t h e p a c k a g e p r e f i x .
5
I t s s e c o n d a r g u m e n t m u l t i p l y _ c o n s t _ f f w i l l become t h e o b j e c t name .
6 /
7
8 GR_SWIG_BLOCK_MAGIC( gr , m u l t i p l y _ c o n s t _ f f )

11

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

/
i s t h e surrogate constructor
gr _ make_mul t i pl y_co nst _f f
i . e . the f r i end f unct i on of cl ass gr _mul t i pl y_co n st _f f
/
g r_m ul ti p l y_ co ns t _f f _ s pt r g r_m a ke_m ultiply_const_ff ( f l o a t k ) ;

c l a s s g r_m ul ti pl y _c o ns t _f f : public g r_sync_block


{
private :
g r_m ul ti p l y_ c o n st _ f f ( f l o a t k ) ; // t h e " t r u e " , p r i v a t e c o n s t r u c t o r
public :
f l o a t k ( ) const { return d_k ; }
void set_k ( f l o a t k ) { d_k = k ; }
};

There are some important aspects to note from the above choices of names. First, the fact
that we have invoked GR_SWIG_BLOCK_MAGIC with parameters gr and
multiply_const_ff has direct relevance to how we invoke the block from Python.
Practically, this means that in Python, when we seek to invoke our blocks, we would first
use the command
import gr
When we wish to instantiate our block, we would use the Python command
block = gr.multiply_const_ff()
In summary, from within Python, gr is a package and multiply_const_ff is a function
within this package. The way we have created the .i file specifies the particular names that
Python ascribes to the package (gr) and function (multiply_const_ff).

4.

Installation of Blocks

4.1

Directory

The next step involves placing various files in the correct locations to ensure a successful
build. We assume that we have finished writing all the necessary files and now make our
12

new blocks accessible from Python. In this section, we outline the key steps needed to
build new signal processing applications in GNU radio.
A sample block is available from the GNU Radio online package archive [?], where each
block is version numbered as X.Y.Z to correspond to the analogous version of GNU Radio.
Download and unpack this block to a directory of your choice, e.g., newBlock. The
directory structure and significance of each folder is explained in table 2.
Table 2. Contents of newBlock directory in GNU Radio.
Directory
/home/user/newBlock
/home/user/newBlock/config
/home/user/newBlock/src
/home/user/newBlock/src/lib

Contents
Top level Makefile, documentation
Files for GNU Autotools
Top level folder for C++ and Python files
Folder for C++ source/header files

As we write our own blocks, keep in mind that all files (.h, .cc, and .i) for the new signal
processing block should go in the newBlock/src/lib directory.
4.2

Preparing Makefile.am for Autotools

The final step before compilation is to edit the Makefile.am file (located in the previous
example in the root directory, i.e., /home/user/newBlock). Makefile.am specifies which
libraries to build, the source files that comprise those libraries, and the appropriate flags to
use. This file contains relevant information to configure the build process that is to follow
to correctly compile our code. Open this file and edit two sections. The first, shown below,
identifies the name of SWIGs .i file:
# Specify the .i file below
LOCAL_IFILES = newModule.i
The next tells SWIG which files to build and what to name them for use by Python:
BUILT_SOURCES =
newModule.cc
newModule.py

\
\

The next set of commands ensures that our new blocks Python code is installed in the
proper location.
13

ourPython_PYTHON =
newModule.py
ourlib_LTLIBRARIES = _newModule.la

The next set of commands specify which source files are included in the shared library that
SWIG exposes to Python:
_newModule_la_SOURCES =
newModule.cc
newModule_newBlock_cc.cc

\
\

The final set of commands specify key flags to ensure that our new signal processing block
shared library compiled and linked correctly against SWIG and the C++ standard library:
_newModule_la_LDFLAGS = -module -avoid-version
_newModule_la_LIBADD =
\
-lgrswigrunpy
\
-lstdc++
newModule.cc newModule.py: newModule.i $(ALL_IFILES)
$(SWIG) $(SWIGCPPPYTHONARGS) -module newModule -o newModule.cc $<
grinclude_HEADERS =
\
newModule_newBlock_cc.h
4.3

Installation

After we finish coding our block, we need to install it. Fortunately, this process is made
easy by the included makefile in the archive downloaded earlier. With the editing of the
Makefile.am file as above, we are now ready to build our new block. Simply use the
following commands:
./bootstrap
./configure --prefix=prefix
make
sudo make install
sudo touch install_path/package_name/__init__.py
Here, prefix is the root of our GNU radio installation (default is /usr/local). Also,
install_path is the directory where our package is being installed (default is
14

prefix/lib/Python/Python-version/site-packages, where Python-version is the version of


Python being used). Finally, package_name is the name of the Python package under
which our block will be available. This would have been specified in Makefile.am by us
during build time, so we just enter that name here. The creation of an __init__.py file is
necessary since Python expects every directory containing a package to have this file.
If subsequently we make changes to our code, we can repeat the above steps but omit the
bootstrap and configure steps.

5.

Usage of Blocks

5.1

Invoking from Python

Our final step is to use our new block from Python as part of a GNU Radio flowgraph.
This is easy using the following commands:.
from gnuradio import newModule
.....
block = newModule.newBlock_cc ()
....
5.2

Debugging

The challenge of debugging our new block is that we are not executing C++ code directly.
Rather, our block, comprised of C++ code, is loaded dynamically into Python and
executed through a Python process. Therefore, the most convenient debugging option
involves inserting print statements through the block source code to monitor its status
during execution. For those familiar with GDB (and often, many graphical debuggers use
GDB under the covers), the following code can be used:
from gnuradio import newModule
import os #package providing blocking function
print My process id is (pid = %d) % (os.getpid(),)
raw_input (Please attach GDB to this process ID, then hit enter: )
# now continue using our block
block = newModule.newBlock_cc();

15

The idea of this code is simply to discover the process ID of the Python process, which
invokes our new block, and then in another terminal, have GDB attach to this process ID.
Now, GDB can be used as usual (to set breakpoints, watch points, etc.) When we have
configured GDB as we like, we can return to the terminal executing the Python process,
and hit Enter to have it proceed.
5.3

Simplifying the Build

As we have mentioned previously, there are several caveats involved in the creation of a
new signal processing block. Beyond just writing the C++ code, we must create a
Makefile.am file and SWIG .i file, and be careful in the naming of various files and
functions so as to adhere to GNU Radios naming rules. These steps are a one-time cost
associated with writing a new block. Then, we have to ensure all files are placed in the
correct place, and then invoke a series of commands to compile, build, and deploy our
application. These latter steps are a recurring cost, which we must incur each time we go
through the debug-build-test cycle. Overall, the process of building and deploying the
block can be time-consuming and error-prone. To allow us to focus on creating new signal
processing blocks in C++ and avoid dealing directly with the complexities of the build
process and naming rules, we have created a script in Python. After the user has written a
new block in C++, this script automates the rest of the process, ensuring that all naming
rules are adhered to (and renaming accordingly when necessary) and all packages are
properly built and usable from Python. The script is given in the appendix B.

6.

Conclusion

In this report, we have provided the details of how to create a new signal processing block
using GNU Radio. We have highlighted important naming conventions; surveyed the
important functions to be overridden in gr_block, such as general_work and forecast;
and illustrated the importance of Boost smart pointers. Finally, we have discussed how to
compile a block, deploy it, and invoke it from Python.

16

A.

The gr_block.h Script

1 / c++ /
2 /
3
C o p y r i g h t 2004 , 2007 , 2009 , 2010 Free S o f t w a r e Foundat ion , Inc .
4

5
T hi s f i l e i s p a r t o f GNU Radio
6

7
GNU Radio i s f r e e s o f t w a r e ; you can r e d i s t r i b u t e i t and / or modi f y
8
i t under t h e t er ms o f t h e GNU Gener al P u b l i c L i c e n s e as p u b l i s h e d by
9
t h e Free S o f t w a r e Foundat i on ; e i t h e r v e r s i o n 3 , or ( a t your o p t i o n )
10
any l a t e r v e r s i o n .
11

12
GNU Radio i s d i s t r i b u t e d i n t h e hope t h a t i t w i l l be u s e f u l ,
13
b u t WITHOUT ANY WARRANTY; w i t h o u t even t h e i m p l i e d w ar r ant y o f
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See t h e
15
GNU Gener al P u b l i c L i c e n s e f o r more d e t a i l s .
16

17
You s h o u l d have r e c e i v e d a copy o f t h e GNU Gener al P u b l i c L i c e n s e
I f not , w r i t e t o
18
a l o n g w i t h GNU Radio ; s e e t h e f i l e COPYING.
19
t h e Free S o f t w a r e Foundation , Inc . , 51 F r a n k l i n S t r e e t ,
20
Boston , MA 02110 1301 , USA.
21
/
22
23 #i f n d e f INCLUDED_GR_BLOCK_H
24 #d ef in e INCLUDED_GR_BLOCK_H
25
26 #include <g r_ba si c_bl o c k . h>
27
28 / !
29
\ b r i e f The a b s t r a c t b a s e c l a s s f o r a l l t e r m i n a l p r o c e s s i n g b l o c k s .
30
\ ingroup base_blk
31

32
A s i g n a l p r o c e s s i n g f l o w i s c o n s t r u c t e d by c r e a t i n g a t r e e o f
33
h i e r a r c h i c a l b l o c k s , w hi ch a t any l e v e l may a l s o c o n t a i n t e r m i n a l nodes
34
t h a t a c t u a l l y i mpl ement s i g n a l p r o c e s s i n g f u n c t i o n s . T hi s i s t h e b a s e
35
c l a s s f o r a l l such l e a f nodes .
36
37
B l o c k s have a s e t o f i n p u t st r eams and o u t p u t st r eams . The
38
i n p u t _ s i g n a t u r e and o u t p u t _ s i g n a t u r e d e f i n e t h e number o f i n p u t
39
st r eams and o u t p u t st r eams r e s p e c t i v e l y , and t h e t y p e o f t h e dat a
40
i t e m s i n each st r eam .
41

42
Al t hough b l o c k s may consume dat a on each i n p u t st r eam a t a
43
d i f f e r e n t r a t e , a l l o u t p u t s st r eams must pr oduce dat a a t t h e same
44
r a t e . That r a t e may be d i f f e r e n t from any o f t h e i n p u t r a t e s .
45

46
User d e r i v e d b l o c k s o v e r r i d e two methods , f o r e c a s t and gener al _ w or k ,
47
t o i mpl ement t h e i r s i g n a l p r o c e s s i n g b e h a v i o r . f o r e c a s t i s c a l l e d
48
by t h e syst em s c h e d u l e r t o det er mi ne how many i t e m s ar e r e q u i r e d on
49
each i n p u t st r eam i n o r d e r t o pr oduce a g i v e n number o f o u t p u t
50
items .

17

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

gener al _w or k i s c a l l e d t o per f or m t h e s i g n a l p r o c e s s i n g i n t h e b l o c k .
I t r e a d s t h e i n p u t i t e m s and w r i t e s t h e o u t p u t i t e m s .
/
c l a s s g r_bl o ck : public g r_ba si c_bl o ck {
public :
// ! Magic r e t u r n v a l u e s from gener al _ w or k
enum {
WORK_CALLED_PRODUCE = 2,
WORK_DONE = 1
};
enum ta g _pro pa g a ti o n_po l i cy_ t {
TPP_DONT = 0 ,
TPP_ALL_TO_ALL = 1 ,
TPP_ONE_TO_ONE = 2
};
vir t u al ~ g r_bl o ck ( ) ;
/ !
Assume b l o c k comput es y_i = f ( x_i , x_i 1, x_i 2, x_i 3 . . . )
H i s t o r y i s t h e number o f x_i s t h a t ar e examined t o pr oduce one y_i .
T hi s comes i n handy f o r FIR f i l t e r s , where we use h i s t o r y t o
ensur e t h a t our i n p u t c o n t a i n s t h e a p p r o p r i a t e " h i s t o r y " f o r t h e
H i s t o r y s h o u l d be e q u a l t o t h e number o f f i l t e r t a p s .
filter .
/
unsigned h i s t o r y ( ) const { return d_hi sto ry ; }
void s e t _ h i s t o r y ( unsigned h i s t o r y ) { d_hi sto ry = h i s t o r y ; }
/ !
\ b r i e f Return t r u e i f t h i s b l o c k has a f i x e d i n p u t t o o u t p u t r a t e .

I f t r ue , t hen f i xed_r at e_i n_ t o_ o ut and f i xed_ r at e_ ou t _ t o_ i n may be c a l l e d


.
/
bool f i x e d _ r a t e ( ) const { return d_f i xed_ra te ; }
//
o v e r r i d e t h e s e t o d e f i n e your b e h a v i o r
//
//
/ !
\ b r i e f Est i mat e i n p u t r e q u i r e m e n t s g i v e n o u t p u t r e q u e s t

number o f o u t p u t i t e m s t o pr oduce
\param nout put _i t ems
number o f i n p u t i t e m s r e q u i r e d on each
\param n i n p u t _ i t e ms _r e qu i r ed
i n p u t st r eam

Given a r e q u e s t t o p r o d u c t \ p nout put _ i t ems , e s t i m a t e t h e number o f


dat a i t e m s r e q u i r e d on each i n p u t st r eam . The e s t i m a t e doesn t have

18

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

t o be e x a c t , b u t s h o u l d be c l o s e .
/
vir t u al void f o r e c a s t ( in t noutput_items ,
g r_vec to r _i n t &ni nput_i tem s_ re qu i re d ) ;
/ !
\ b r i e f compute o u t p u t i t e m s from i n p u t i t e m s

number o f o u t p u t i t e m s t o w r i t e on each o u t p u t
\param nout put _i t ems
st r eam
number o f i n p u t i t e m s a v a i l a b l e on each i n p u t
\param ni nput _i t ems
st r eam
v e c t o r o f p o i n t e r s t o t h e i n p u t i t ems , one
\param i nput _i t ems
e n t r y per i n p u t st r eam
v e c t o r o f p o i n t e r s t o t h e o u t p u t i t ems , one
\param out put _i t ems
e n t r y per o u t p u t st r eam

\ r e t u r n s number o f i t e m s a c t u a l l y w r i t t e n t o each o u t p u t stream , or 1 on


EOF.
I t i s OK t o r e t u r n a v a l u e l e s s t han nout put _ i t ems . 1 <= r e t u r n v a l u e
<= nout put _i t ems

gener al _w or k must c a l l consume or consume_each t o i n d i c a t e how many i t e m s


were consumed on each i n p u t st r eam .
/
vir t u al in t g enera l _wo rk ( in t noutput_items ,
g r_vect o r _i n t &ni nput_items ,
g r_vecto r_co nst _vo i d_st a r &i nput_i tem s ,
g r_vecto r_vo i d_s ta r &o utput_i tem s ) = 0 ;
/ !
\ b r i e f C a l l e d t o e n a b l e d r i v e r s , e t c f o r i /o d e v i c e s .

T hi s a l l o w s a b l o c k t o e n a b l e an a s s o c i a t e d d r i v e r t o b e g i n
t r a n s f e r i n g dat a j u s t b e f o r e we s t a r t t o e x e c u t e t h e s c h e d u l e r .
The end r e s u l t i s t h a t t h i s r e d u c e s l a t e n c y i n t h e p i p e l i n e when
d e a l i n g w i t h audi o d e v i c e s , usr ps , e t c .
/
vir t u al bool s t a r t ( ) ;
/ !
\ b r i e f C a l l e d t o d i s a b l e d r i v e r s , e t c f o r i /o d e v i c e s .
/
vir t u al bool s t o p ( ) ;
//
/ !
\ b r i e f C onst r ai n t h e nout put _ i t ems argument p a s s e d t o f o r e c a s t and
gener al _w or k

s e t _ o u t p u t _ m u l t i p l e c a u s e s t h e s c h e d u l e r t o ensur e t h a t t h e nout put _ i t ems


argument p a s s e d t o f o r e c a s t and gener al _ w or k w i l l be an i n t e g e r m u l t i p l e
o f \ param m u l t i p l e The d e f a u l t v a l u e o f o u t p u t m u l t i p l e i s 1 .

19

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

/
void set_o ut put _ m ul ti p l e ( in t m u l t i p l e ) ;
in t o utput_m ul t i pl e ( ) const { return d_o utput_m ul ti ple ; }
/ !
\ b r i e f T e l l t h e s c h e d u l e r \ p how_many_items o f i n p u t st r eam \ p
w hi ch_i nput were consumed .
/
void consume ( in t which_input , in t how_many_items ) ;
/ !
\ b r i e f T e l l t h e s c h e d u l e r \ p how_many_items were consumed on each i n p u t
st r eam .
/
void consume_each ( in t how_many_items ) ;
/ !
\ b r i e f T e l l t h e s c h e d u l e r \ p how_many_items were pr oduced on o u t p u t
st r eam \ p w hi ch_out put .

I f t h e b l o c k s gener al _w or k method c a l l s pr oduce , \ p gener al _ w or k must


r e t u r n WORK_CALLED_PRODUCE.
/
void pro duce ( in t which_output , in t how_many_items ) ;
/ !
\ b r i e f S e t t h e appr oxi ma t e o u t p u t r a t e / i n p u t r a t e

Pr ovi de a h i n t t o t h e b u f f e r a l l o c a t o r and s c h e d u l e r .
The d e f a u l t r e l a t i v e _ r a t e i s 1 . 0

d e c i m a t o r s have r e l a t i v e _ r a t e s < 1 . 0
i n t e r p o l a t o r s have r e l a t i v e _ r a t e s > 1 . 0
/
void s e t _ r e l a t i v e _ r a t e ( double r e l a t i v e _ r a t e ) ;
/ !
\ b r i e f r e t u r n t h e appr oxi mat e o u t p u t r a t e / i n p u t r a t e
/
double r e l a t i v e _ r a t e ( ) const { return d _ r e l a t i v e _ r a t e ; }
/
The f o l l o w i n g two methods p r o v i d e s p e c i a l c a s e i n f o t o t h e
s c h e d u l e r i n t h e e v e n t t h a t a b l o c k has a f i x e d i n p u t t o o u t p u t
r a t i o . gr _sync_bl ock , gr _ sync_ deci mat or and g r _ s y n c _ i n t e r p o l a t o r
I f you r e f i x e d r a t e , s u b c l a s s one o f t h o s e .
override these .
/
/ !
\ b r i e f Given n i n p u t sampl es , r e t u r n number o f o u t p u t sampl es t h a t w i l l be
pr oduced .
N.B. t h i s i s o n l y d e f i n e d i f f i x e d _ r a t e r e t u r n s t r u e .
G e n e r a l l y s p e a k i n g , you don t need t o o v e r r i d e t h i s .
/
vir t u al in t f i xed_ra te_ni nput_to _noutput ( in t ni nput ) ;

20

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

/ !
\ b r i e f Given n o u t p u t sampl es , r e t u r n number o f i n p u t sampl es r e q u i r e d t o
pr oduce n o u t p u t .
N.B. t h i s i s o n l y d e f i n e d i f f i x e d _ r a t e r e t u r n s t r u e .
G e n e r a l l y s p e a k i n g , you don t need t o o v e r r i d e t h i s .
/
vir t u al in t f i xed_ra te_no utput_to _ninput ( in t no utput ) ;
/ !
\ b r i e f Return t h e number o f i t e m s r ead on i n p u t st r eam w hi ch_i nput
/
ui nt6 4 _t ni tem s_rea d ( unsigned in t which_input ) ;
/ !
\ b r i e f Return t h e number o f i t e m s w r i t t e n on o u t p u t st r eam w hi ch_ out put
/
ui nt6 4 _t ni tem s_w ri t te n ( unsigned in t which_output ) ;
/ !
\ b r i e f Asks f o r t h e p o l i c y used by t h e s c h e d u l e r t o moved t a g s downstream
.
/
ta g _pro pa g a ti o n_po l i c y_t t a g _ p r o p a g a t i o n_ p o l i c y ( ) ;
/ !
\ b r i e f S e t t h e p o l i c y by t h e s c h e d u l e r t o det er mi ne how t a g s ar e moved
downstream .
/
void set_t a g _ pr o p a g a ti o n_ po l i c y ( ta g _pro pa g a ti o n_po l i c y_t p ) ;
//

228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

private :
d_o utput_m ultiple ;
in t
d_relative_rate ;
// appr ox o u t p u t _ r a t e /
double
input_rate
gr_block_detail_sptr d_detail ;
// i m p l e m en t a t i o n d e t a i l s
d_hi sto r y ;
unsigned
d_f i xed_ra te ;
bool
ta g _pro pa g a ti o n_po l i c y_t d_ta g _pro pa g a ti o n_po l i cy ; // p o l i c y f o r moving t a g s
downstream
protected :
g r_bl o ck ( const s t d : : s t r i n g &name ,
g r _ i o _ s i g n a t u r e _ s pt r i n p u t _ s i g n a t u r e ,
g r _ i o _ s i g n a t u r e _ s pt r o u t p u t _ s i g n a t ur e ) ;
void s e t _ f i x e d _ r a t e ( bool f i x e d _ r a t e ) { d_f i xed_ra te = f i x e d _ r a t e ; }

21

246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

/ !
\ b r i e f Adds a new t a g ont o t h e g i v e n o u t p u t b u f f e r .

\param w hi ch_out put an i n t e g e r o f w hi ch o u t p u t st r eam t o a t t a c h t h e t a g


a u i n t 6 4 number o f t h e a b s o l u t e i t em number
\param a b s _ o f f s e t

a s s i c a t e d w i t h t h e t a g . Can g e t from n i t e m s _ w r i t t e n .
t h e t a g key as a PMT symbol
\param key
any PMT h o l d i n g any v a l u e f o r t h e g i v e n key
\param v a l u e
o p t i o n a l s o u r c e ID s p e c i f i e r ; d e f a u l t s t o PMT_F
\param s r c i d
/
void add_item_tag ( unsigned in t which_output ,
ui nt6 4 _t a b s _ o f f s e t ,
const pmt : : pmt_t &key ,
const pmt : : pmt_t &va l ue ,
const pmt : : pmt_t &s r c i d =pmt : :PMT_F) ;
/ !
\ b r i e f Given a [ s t a r t , end ) , r e t u r n s a v e c t o r o f a l l t a g s i n t h e r ange .

Range o f c o u n t s i s from s t a r t t o end 1.

Tags ar e t u p l e s o f :

( i t em count , s o u r c e i d , key , v a l u e )

a vect or r ef er ence to return t ags i nt o


\param v
\param w hi ch_i nput an i n t e g e r o f w hi ch i n p u t st r eam t o p u l l from
a u i n t 6 4 count o f t h e s t a r t o f t h e r ange o f i n t e r e s t
\param a b s _ s t a r t
a u i n t 6 4 count o f t h e end o f t h e r ange o f i n t e r e s t
\param abs_end
/
void g et_ta g s_i n_rang e ( s t d : : v e c t o r <pmt : : pmt_t> &v ,
unsigned in t which_input ,
ui nt6 4 _t a bs_sta rt ,
ui nt6 4 _t abs_end ) ;
/ !
\ b r i e f Given a [ s t a r t , end ) , r e t u r n s a v e c t o r o f a l l t a g s i n t h e r ange
w i t h a g i v e n key .

Range o f c o u n t s i s from s t a r t t o end 1.

Tags ar e t u p l e s o f :

( i t em count , s o u r c e i d , key , v a l u e )

a vect or r ef er ence to return t ags i nt o


\param v
\param w hi ch_i nput an i n t e g e r o f w hi ch i n p u t st r eam t o p u l l from
a u i n t 6 4 count o f t h e s t a r t o f t h e r ange o f i n t e r e s t
\param a b s _ s t a r t
a u i n t 6 4 count o f t h e end o f t h e r ange o f i n t e r e s t
\param abs_end
a PMT symbol key t o f i l t e r o n l y t a g s o f t h i s key
\param key
/
void g et_ta g s_i n_rang e ( s t d : : v e c t o r <pmt : : pmt_t> &v ,
unsigned in t which_input ,
ui nt6 4 _t a bs_sta rt ,
ui nt6 4 _t abs_end ,

22

300
const pmt : : pmt_t &key ) ;
301
302
// These ar e r e a l l y o n l y f o r i n t e r n a l use , b u t l e a v i n g them p u b l i c a v o i d s
303
// h a v i n g t o work up an ever v a r y i n g l i s t o f f r i e n d s
304
305
public :
306
g r _ b l o c k _ d e t a i l _ s p t r d e t a i l ( ) const { return d _ d e t a i l ; }
307
void s e t _ d e t a i l ( g r _ b l o c k _ d e t a i l _ s p tr d e t a i l ) { d _ d e t a i l = d e t a i l ; }
308 } ;
309
310 typedef s t d : : v e c t o r <g r_bl o ck_sptr> g r_bl o ck_vecto r_t ;
311 typedef s t d : : v e c t o r <g r_bl o ck_sptr > : : i t e r a t o r g r_bl o ck_vi ter _t ;
312
313 i n l i n e g r_bl o ck_sptr ca st_to _bl o ck_sp tr ( g r_ba si c_bl o ck_ sp tr p )
314 {
315
return b o o s t : : dyna m i c_po inter_ca st<g r_bl o ck , g r_ba si c_bl o ck >(p ) ;
316 }
317
318
319 s t d : : o strea m&
320 operator << ( s t d : : o strea m& os , const g r_bl o ck m) ;
321
322 #en d if / INCLUDED_GR_BLOCK_H /

23

INTENTIONALLY LEFT BLANK

24

B.

The blockWizard.py Script

1 #! / usr / b i n / env pyt hon


2
3 #T hi s code s i m p l i f i e s t h e p r o c e s s o f w r i t i n g new b l o c k s . Si mpl y dow nl oad t h e
a r c h i v e " grhowtow r i t eab l o c k 3 . 3 . 0 . t a r . g z " from
4 #f t p : / / f t p . gnu . or g / gnu/ g n u r a d i o/ grhowtow r i t eab l o c k 3 . 3 . 0 . t a r . g z , e x t r a c t
i t to a directory " topdir " ,
5 #and c r e a t e your custom b l o c k i n C++ , p l a c i n g i t i n t o p d i r / s r c / l i b . Then
run t h i s s c r i p t .
6 #The u s e r o n l y needs t o i mpl ement t h e b l o c k , f o r exampl e
7 #p a r t i c u l a r l y " gener al _w or k " and " f o r e c a s t " f u n c t i o n s . I t h a n d l e s i n s t a l l a t i o n
of shared l i br ar y ,
8 #and e n s u r e s v a r i o u s naming " c o n v e n t i o n s " ( r e a l l y r i g i d r u l e s ) , such as name
of sur r ogate f r i end constructor ,
9 #e x p e c t e d by t h e b u i l d syst em ar e f o l l o w e d . I t h a n d l e s t h e p r o p e r c r e a t i o n o f
the swig f i l e .
10
11 import o s
12 import r e
13 import s y s
14
15 print " \n ! ! ! "
16 print " Thi s wi za rd h e l p s b u i l d ( m u l t i p l e ) s i g n a l p r o c e s s i n g b l o c k s , and p l a c e s
them i n a s i n g l e module o f a s i n g l e pa cka g e "
17 print " You o nl y r e a l l y need to use t h i s the f i r s t ti m e you c r e a t e a new b l o c k ;
then , f o r subse qu e nt co de cha ng es to t h a t same bl o ck , j u s t use make and
sudo make i n s t a l l "
18 print " Thi s s c r i p t w i l l d e l e t e o l d a u t o t o o l s r e l a t e d f i l e s from t h i s d i r e c t o r y
and g e n e r a t e new o nes ; i f you have any co ncer ns , back up b e f o r e
proceeding "
19 print " ! ! ! "
20 raw_input ( " P r e s s e n t e r to co nti nue , Ctrl C to a b o r t : " )
21
22
23 print ( " \n Cl ea ni ng f i l e s from a bo rted p r e v i o u s runs . . . " )
24 o s . system ( " make c l e a n " )
25 o s . system ( " rm r f s r c / l i b / M a k e f i l e . am" )
26 o s . system ( " rm r f s r c / l i b / M a k e f i l e " )
27 o s . system ( " rm r f s r c / l i b / M a k e f i l e . i n " )
28 o s . system ( " rm r f s r c / l i b / . deps " )
29 o s . system ( " rm r f s r c / l i b / . i " )
30 o s . system ( " rm r f s r c / l i b / M a k e f i l e . swi g . gen " )
31
32 s r c _ h e a d e r s = l i s t ( )
33 s r c _ s o u r c e = l i s t ( )
34
35 c l a s s _ i n h e r i t a n c e = d i c t ( )
36 f r i e n d _ c o n s t r u c t o r = d i c t ( )
37 c o n s t r u c t o r = d i c t ( ) #maps header f i l e s t o t h e s i g n a t u r e o f t h e i r c o n s t r u c t o r s
38 d e s t r u c t o r = d i c t ( ) #maps header f i l e s t o t h e s i g n a t u r e o f t h e i r d e s t r u c t o r s
39

25

40
41
42
43
44
45
46
47
48
49
50
51
52
53

p r e f i x = raw_input ( \n\ n S p e c i f y p r e f i x : [ p r e f i x ] / l i b / python [ v e r s i o n ] / s i t e


pa cka g es ( d e f a u l t = / u s r / l o c a l ) : )
i f l e n ( p r e f i x ) == 0 :
p r e f i x=" / u s r / l o c a l "

v e r s i o n = raw_input ( \n\ n S p e c i f y python v e r s i o n : + p r e f i x + / l i b / python [


v e r s i o n ] / s i t e pa cka g es ( d e f a u l t = 2 . 6 ) : )
i f l e n ( v e r s i o n ) == 0 :
v e r s i o n=" 2 . 6 "
i n s t a l l _ p a t h = p r e f i x + " / l i b / python " + v e r s i o n + " / s i t e pa cka g es "
i n s t a l l _ p a t h _ a l t = p r e f i x + " / l i b / python " + v e r s i o n + " / d i s t pa cka g es " #
i n s t a l l a t i o n may occur t o h e r e i n s t e a d
print ( \nThe python command to i m po rt t h i s b l o c k w i l l be : from [ package_name ]
i m po rt [ module_name ] )
package_name = raw_input ( Enter d e s i r e d package_name ( d e f a u l t=t e s t p a c k a g e ) : )
i f l e n ( package_name ) == 0 :
package_name=" t e s t p a c k a g e "

54
55
56
57
58 module_name = raw_input ( Enter d e s i r e d module_name ( d e f a u l t=t e s t m o d u l e ) : )
59 i f l e n ( module_name ) == 0 :
60
module_name=" t e s t m o d u l e "
61
62 a l l _ f i l e s=o s . l i s t d i r ( o s . getcwd ( ) + " / s r c / l i b " )
63
64 #c r e a t e l i s t s o f t h e . h f i l e s and t h e . cc f i l e s
65 f o r f i l e n a m e in a l l _ f i l e s :
66
#h e a d e r _ p a t t er n = r e . c o m p i l e ( [ \ w] + . h )
67
#s u f f i x _ p a t t e r n = r e . c o m p i l e ( [ \ w] + . cc )
68
69
i f " . h " in f i l e n a m e :
70
s r c _ h e a d e r s . append ( f i l e n a m e )
71
72
i f " . cc " in f i l e n a m e :
73
s r c _ s o u r c e . append ( f i l e n a m e )
74
75
76
77 print ( \n\nThe python command to c r e a t e t h i s b l o c k w i l l be : o b j e c t = +
module_name + . [ block_name ] ( ) )
78 i = 0
79 block_names={} #d i c t i o n a r y mapping header f i l e t o b l o c k name
80 f o r f i l e n a m e in s r c _ h e a d e r s :
81
i = i + 1
82
block_name = raw_input ( Enter d e s i r e d block_name c o r r e s p o n d i n g to b l o c k
implemented i n + f i l e n a m e [ : 2 ] + ( d e f a u l t=t e s t _ b l o c k + s t r ( i ) +
, 0 f o r none ) : )
83
i f l e n ( block_name ) == 0 :
84
block_name=" t e s t _ b l o c k " + s t r ( i )
85
i f block_name == 0 :
86
block_name=" "

26

87
block_names [ f i l e n a m e ] = block_name
88
89
90
91 #f i g u r e out w hi ch c l a s s e s i n h e r i t from w hi ch b l o c k s ( e . g . from g r _ b l o c k or
gr _ sync_bl ock ( a l l o w f o r h e l p e r c l a s s e s w hi ch do not i n h e r i t a t a l l )
92 c l a s s _ d e c _ p a t t e r n = r e . co m pi l e ( [ \ s ] c l a s s [ \ s \w] + : )
93 f o r f i l e n a m e in s r c _ h e a d e r s :
94
f = open ( o s . getcwd ( ) + " / s r c / l i b / " + f i l e n a m e , r )
95
f o r l i n e in f :
96
i f c l a s s _ d e c _ p a t t e r n . match ( l i n e ) :
97
m = r e . s e a r c h ( [ \ s ] + [ \w]+$ , l i n e ) #f i n d t h e name o f t h e c l a s s
that is inherited
98
i f m:
99
c l a s s _ i n h e r i t a n c e [ f i l e n a m e ] = m. group ( ) . s t r i p ( )
100
else :
101
cl a ss_i nheri ta nce [ filename ] = " "
102
f . close ()
103
104
105
106 #f i g u r e out t h e s i g n a t u r e o f t h e c o n s t r u c t o r from each . h f i l e
" f i l e n a m e ( " ( where
107 # key i d e a i s t o l o o k f o r s t r i n g o f t h e form
filename i s without the . h)
108 f o r f i l e n a m e in s r c _ h e a d e r s :
109
110
c o n s t r u c t o r _ s t r i n g=" "
111
co nstructo r_na m e=f i l e n a m e [ : 2 ] #e v e r y t h i n g b u t t h e . h
112
m u l t i _ l i n e=0
113
114
f = open ( o s . getcwd ( ) + " / s r c / l i b / " + f i l e n a m e , r )
115
116
f o r l i n e in f :
117
i f ( ( co nstructo r_na m e + " ( " ) in l i n e ) or ( ( co nstructo r_na m e + " ( " ) in
l i n e ) : #t h i s l i n e c o n t a i n s a c o n s t r u c t o r d e c l a r a t i o n
118
c o n s t r u c t o r _ s t r i n g=l i n e
119
i f ( " p u b l i c " in p r e v i o u s _ l i n e ) or ( " p r i v a t e " in p r e v i o u s _ l i n e ) or
( " p r o t e c t e d " in p r e v i o u s _ l i n e ) :
120
co nstructo r_stri ng = previous_line + co nstructo r_string
121
i f " ; " in l i n e : #t h e c o n s t r u c t o r d e c l a r a t i o n i s a l l on one l i n e
122
m u l t i _ l i n e=0 #does t h e c o n s t r u c t o r d e c l a r a t i o n span m u l t i p l e
lines ?
123
break
124
else :
125
m u l t i _ l i n e=1
126
continue
127
128
i f m u l t i _ l i n e == 1 : #t h e c o n s t r u c t o r d e c l a r a t i o n i s o v e r m u l t i p l e
lines
129
constructor_string = constructor_string + l ine
130
i f " ; " in l i n e : #l o o k f o r end o f t h i s c o n s t r u c t o r d e c l a r a t i o n , i . e
a semicolon
131
break
132

27

133
134
135

p r e v i o u s _ l i n e = l i n e #s a v e t h e p r e v i o u s l i n e f o r f u t u r e use i n c a s e we
need t o l o o k back
c o n s t r u c t o r [ f i l e n a m e ] = c o n s t r u c t o r _ s t r i n g #t h e r e i s one c o n s t r u c t o r per
class obviously

136
137 f . c l o s e ( )
138
139
140
141
142
143
144
145
146
147 #f i g u r e out t h e s i g n a t u r e o f t h e d e s t r u c t o r from each . h f i l e
"~ f i l e n a m e " ( where
148 # key i d e a i s t o l o o k f o r s t r i n g o f t h e form
filename i s without the . h)
149 f o r f i l e n a m e in s r c _ h e a d e r s :
150
151
d e s t r u c t o r _ s t r i n g=" "
152
destructo r_na m e=f i l e n a m e [ : 2 ] #e v e r y t h i n g b u t t h e . h
153
m u l t i _ l i n e=0
154
155
f = open ( o s . getcwd ( ) + " / s r c / l i b / " + f i l e n a m e , r )
156
157
f o r l i n e in f :
158
i f ( " ~ " + destructo r_na m e ) in l i n e : #t h i s l i n e c o n t a i n s a d e s t r u c t o r
declaration
159
d e s t r u c t o r _ s t r i n g=l i n e
160
i f ( " p u b l i c " in p r e v i o u s _ l i n e ) or ( " p r i v a t e " in p r e v i o u s _ l i n e ) or
( " p r o t e c t e d " in p r e v i o u s _ l i n e ) :
161
destructo r_stri ng = previous_line + destructo r_stri ng
162
i f " ; " in l i n e : #t h e d e s t r u c t o r d e c l a r a t i o n i s a l l on one l i n e
163
m u l t i _ l i n e=0 #does t h e d e s t r u c t o r d e c l a r a t i o n span m u l t i p l e
lines ?
164
break
165
else :
166
m u l t i _ l i n e=1
167
continue
168
169
i f m u l t i _ l i n e == 1 : #t h e d e s t r u c t o r d e c l a r a t i o n i s o v e r m u l t i p l e l i n e s
170
destructor_string = destructor_string + l ine
171
i f " ; " in l i n e : #l o o k f o r end o f t h i s d e s t r u c t o r d e c l a r a t i o n , i . e
a semicolon
172
break
173
174
p r e v i o u s _ l i n e = l i n e #s a v e t h e p r e v i o u s l i n e f o r f u t u r e use i n c a s e we
need t o l o o k back
175
176
d e s t r u c t o r [ f i l e n a m e ] = d e s t r u c t o r _ s t r i n g #t h e r e i s one c o n s t r u c t o r per
class obviously
177

28

178 f . c l o s e ( )
179
180
181
182
183
184
185
186 #f i g u r e out t h e f r i e n d f u n c t i o n ( from . h f i l e ) a c t i n g as t h e p u b l i c i n t e r f a c e
f o r o b j e c t c o n s t r u c t i o n ( a l l o w f o r h e l p e r c l a s s e s t h a t do not have t h i s )
187 f o r f i l e n a m e in s r c _ h e a d e r s :
188
189
190
f r i e n d=" "
191
t a r g e t="+_)(&%%@#NNKSJAHFIUWEROIWEALSKJFD"
192
m u l t i _ l i n e=0
193
194
f = open ( o s . getcwd ( ) + " / s r c / l i b / " + f i l e n a m e , r )
195
196
f o r l i n e in f :
197
i f " b o o s t : : sha red_ptr " in l i n e : #t h i s l i n e c o n t a i n s a t y p e d e f , we want
t o know t h e name o f t h e a l i a s so we can f i n d i t s d e c l a r a t i o n
198
t a r g e t = l i n e . s t r i p ( ) . s p l i t ( " " ) [ 1 ] [ : 1 ] #g e t t h e l a s t word , t hen
dr op t h e s e m i c o l o n o f t h a t l a s t word
199
continue
200
201
i f t a r g e t in l i n e :
202
#f r i e n d s . append ( l i n e . s t r i p ( ) )
203
f r i e n d =l i n e
204
i f " ; " in l i n e : #t h e f r i e n d d e c l a r a t i o n i s a l l on one l i n e
205
m u l t i _ l i n e=0 #does t h e f r i e n d d e c l a r a t i o n span m u l t i p l e l i n e s ?
no
206
break
207
else :
208
m u l t i _ l i n e=1
209
continue
210
211
i f m u l t i _ l i n e == 1 : #t h e f r i e n d d e c l a r a t i o n i s o v e r m u l t i p l e l i n e s
212
#f r i e n d s . append ( l i n e . s t r i p ( ) )
213
friend = friend + l ine
214
i f " ; " in l i n e : #l o o k f o r end o f t h i s f r i e n d d e c l a r a t i o n , i . e a
semicolon
215
break
216
217
f ri end_co nstructor [ filename ] = f ri end
218
219 f . c l o s e ( )
220
221
222
223 print
224 print "

"

29

225
226
227
228
229
230
231
232
233
234
235
236
237
238
239

print " Bl o ck w i l l be i m po rted i n python a s :


+ " i m po rt " + module_name
f o r v a l u e in block_names . v a l u e s ( ) :
i f len ( value ) > 1 :
print "New o b j e c t s i n python w i l l be made a s :
module_name + " . " + v a l u e + " ( ) "

from " + package_name

object = " +

" , src_headers
print " D etected b l o c k hea der f i l e s a r e :
" , src_source
print " D etected b l o c k s o u r c e f i l e s a r e :
print " Bl o ck c l a s s e s i n h e r i t g nura di o ba se c l a s s e s a s : " , c l a s s _ i n h e r i t a n c e
" , constructor
print " C l a s s c o n s t r u c t o r s a r e :
" , destructor
print " C l a s s d e s t r u c t o r s a r e :
" , fri end_constructor
print " Fri end p u b l i c c o n s t r u c t o r s a r e :
" , i nstal l _path
print " I n s t a l l path o f t h i s pa cka g e i s :
print "

"

240
241 raw_input ( \ nPres s e n t e r to co nti nue , o r C t r l C to a b o r t )
242
243
244
245
246 #c r e a t e . i f i l e
247 s w i g _ i _ f i l e = open ( o s . getcwd ( ) + " / s r c / l i b / " + module_name + " . i " , w )
248 s w i g _ i _ f i l e . w r i t e ( / c++ / )
249 s w i g _ i _ f i l e . w r i t e ( \n%i n c l u d e " g nura di o . i " )
250 s w i g _ i _ f i l e . w r i t e ( \n%{ )
251 f o r f i l e n a m e in s r c _ h e a d e r s :
252
s w i g _ i _ f i l e . w r i t e ( \n#i n c l u d e " + f i l e n a m e + " )
253 s w i g _ i _ f i l e . w r i t e ( \n%} )
254
255 f o r f i l e n a m e in s r c _ h e a d e r s :
256
i f ( block_names [ f i l e n a m e ] != 0 ) : #check t h a t t h i s r e a l l y c o r r e s p o n d s t o
a b l o c k i m p l e m e n t a t i o n and not h e l p e r f i l e s
257
s w i g _ i _ f i l e . w r i t e ( \n\nGR_SWIG_BLOCK_MAGIC( + module_name + , +
block_names [ f i l e n a m e ] + ) ; )
258
s w i g _ i _ f i l e . w r i t e ( \n\n + f r i e n d _ c o n s t r u c t o r [ f i l e n a m e ] )
259
260
#w r i t e t h e c l a s s d e f i n i t i o n and c o n s t r u c t o r s / d e s t r u c t o r s i n i t
261
s w i g _ i _ f i l e . w r i t e ( \n\n + c l a s s + f i l e n a m e [ : 2 ] + : p u b l i c +
cl a ss_i nheri ta nce [ filename ] )
262
s w i g _ i _ f i l e . w r i t e ( \n{ )
263
s w i g _ i _ f i l e . w r i t e ( \n\n + c o n s t r u c t o r [ f i l e n a m e ] )
264
s w i g _ i _ f i l e . w r i t e ( \n\n + d e s t r u c t o r [ f i l e n a m e ] )
265
s w i g _ i _ f i l e . w r i t e ( \n } ; )
266
267 s w i g _ i _ f i l e . c l o s e ( )
268
269
270 #c r e a t e M a k e f i l e . am f i l e i n / s r c / l i b
271 Ma kef i l e_a m _f i l e = open ( o s . getcwd ( ) + " / s r c / l i b / M a k e f i l e . am" , w )

30

272
273 Ma kef i l e_a m _f i l e . w r i t e ( i n c l u d e $ ( t o p _ s r c d i r ) / M a k e f i l e . common )
274 Ma kef i l e_a m _f i l e . w r i t e ( \n\ngrinclude_HEADERS = \\ )
275 i = 0
276 f o r f i l e n a m e in s r c _ h e a d e r s :
277
i = i + 1
278
Ma kef i l e_a m _f i l e . w r i t e ( \n\ t + f i l e n a m e )
279
i f ( i < len ( src_headers ) ) :
280
Ma kef i l e_a m _f i l e . w r i t e ( \ )
281
282 Ma kef i l e_a m _f i l e . w r i t e ( \n\n\nTOP_SWIG_IFILES = \\ )
283 Ma kef i l e_a m _f i l e . w r i t e ( \n\ t + module_name + . i )
284
285 Ma kef i l e_a m _f i l e . w r i t e ( \n\n + module_name + _pytho ndi r_ca teg o ry = \\ )
286 Ma kef i l e_a m _f i l e . w r i t e ( \n\ t + package_name )
287
288 Ma kef i l e_a m _f i l e . w r i t e ( \n\n + module_name + _l a _swi g _so urces = \\ )
289 i = 0
290 f o r f i l e n a m e in s r c _ s o u r c e :
291
i = i + 1
292
Ma kef i l e_a m _f i l e . w r i t e ( \n\ t + f i l e n a m e )
293
i f ( i < len ( src_source ) ) :
294
Ma kef i l e_a m _f i l e . w r i t e ( \ )
295
296 Ma kef i l e_a m _f i l e . w r i t e ( \n\ n i n c l u d e $ ( t o p _ s r c d i r ) / M a k e f i l e . swi g )
297 Ma kef i l e_a m _f i l e . w r i t e ( \n\nBUILT_SOURCES = $ ( s w i g _ b u i l t _ s o u r c e s ) )
298 Ma kef i l e_a m _f i l e . w r i t e ( \n\ n n o _ d i s t _ f i l e s = $ ( s w i g _ b u i l t _ s o u r c e s ) )
299
300 Ma kef i l e_a m _f i l e . c l o s e ( )
301
302 #c r e a t e M a k e f i l e . am i n / s r c / pyt hon
303 Ma kef i l e_a m _f i l e = open ( o s . getcwd ( ) + " / s r c / python / M a k e f i l e . am" , w )
304 Ma kef i l e_a m _f i l e . w r i t e ( i n c l u d e $ ( t o p _ s r c d i r ) / M a k e f i l e . common )
305 Ma kef i l e_a m _f i l e . c l o s e ( )
306
307
308 #c r e a t e M a k e f i l e . s w i g . gen
309 o s . system ( " cp s r c / l i b / M a k e f i l e . swi g . gen .TEMPLATE s r c / l i b / M a k e f i l e . swi g . gen " )
310 module_command = " sed i s / t e s t m o d u l e/ " + module_name + " / g I s r c / l i b / M a k e f i l e .
swi g . gen "
311 package_command = " sed i s / g nura di o / " + package_name + " / g I s r c / l i b / M a k e f i l e .
swi g . gen "
312 o s . system ( module_command)
313 o s . system ( package_command )
314
315
[ module_name ]_[
316 #The b u i l d syst em e x p e c t s s o u r c e f i l e s t o be o f t h e form
block_name ] . h
or [ module_name ]_[ block_name ] . cc
317 #T hi s i s based o f f a gnu r a d i o c o n v e n t i o n . I f our f i l e s ar e NOT i n t h i s form ,
copy them o v e r i n t o t h a t form
318 #I t a l s o e x p e c t s t h e f r i e n d p u b l i c c o n s t r u c t o r t o be o f t h e form [ module_name ]
_make_ [ block_name ]
319 #c r e a t e s o u r c e f i l e s t h a t ar e named a c c o r d i n g t o gnu r a d i o convent i on , i . e .
modulename_blockname . h and . cc ( i n c a s e t h e y don t e x i s t ) so t h a t make i s

31

320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342

343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361

happy
c o n f o r m i n g _ s o u r c e _ f i l e s = l i s t ( ) # l i s t o f s o u r c e f i l e s conf or mi ng t o p r o p e r
gnu r a d i o naming c o n v e n t i o n
s w i g _ i _ f i l e = " s r c / l i b / " + module_name + " . i "
Ma kef i l e_a m _f i l e = " s r c / l i b / M a k e f i l e . am"
f o r f in block_names . keys ( ) : #l o o p o v e r a l l s o u r c e f i l e s
make_function=" "
i dea l _m a ke_f uncti o n=" "
filename = " src / l i b / " + f
ideal_name = " s r c / l i b / " + module_name + "_" + block_names [ f ]
i f ( not o s . path . i s f i l e ( ideal_name + " . h " ) ) : #t h e conf or mi ng , c o n v e n t i o n a l
name does not e x i s t ; c r e a t e i t
raw_input ( " \ nSo urce names do no t conform to GNU r a d i o c o n v e n t i o n !
P r e s s e n t e r to c o n t i n u e wi th autorenaming . . . . . \ n " )
p_f
i l e = ideal_name + " . h "
tm
=
" cp " + f i l e n a m e [ : 2 ] + " . h " + tm p_f i l e
cmd
s
.
system
(cmd)
o
o
n
f
o
r
m
i
n
g _ s o u r c e _ f i l e s . append ( tm p_f i l e )
c
rename_command = " sed i s / " + f [ : 2 ] + " / " + module_name + "_" +
block_names [ f ] + " / g I " + tm p_f i l e
o s . system ( rename_command)
#c o r r e c t t h e f r i e n d p u b l i c i n t e r f a c e name t o conform t o gnu r a d i o
i f l e n ( f r i e n d _ c o n s t r u c t o r [ f ] ) > 0 : #t h i s f i l e has a f r i e n d
constructor
t o k e n s=f r i e n d _ c o n s t r u c t o r [ f ] . s p l i t ( ) #s p l i t s on any w h i t e s p a c e ,
even c o n s e c u t i v e w h i t e s p a c e s w hi ch ar e t r e a t e d as a s i n g l e
w h i t e s p a c e , w hi ch we want
make_function=t o k e n s [ 1 ] . s t r i p ( ) #t h e name o f t h e p u b l i c i n t e r f a c e
friend constructor
i f " ( ) ; " in make_function :
make_function=make_function [ : 3 ]
e l i f " ( ) " in make_function :
make_function=make_function [ : 2 ]
i dea l _m a ke_f uncti o n = module_name + "_make_" + block_names [ f ]
rename_command = " sed i s / " + make_function + " / " +
i dea l _m a ke_f uncti o n + " / g I " + tm p_f i l e
o s . system ( rename_command)
tm p_f i l e = ideal_name + " . cc "
cmd = " cp " + f i l e n a m e [ : 2 ] + " . cc " + tm p_f i l e
o s . system (cmd)
c o n f o r m i n g _ s o u r c e _ f i l e s . append ( tm p_f i l e )
rename_command = " sed i s / " + f [ : 2 ] + " / " + module_name + "_" +
block_names [ f ] + " / g I " + tm p_f i l e
o s . system ( rename_command)
rename_command = " sed i s / " + make_functio n + " / " +
i dea l _m a ke_f uncti o n + " / g I " + tm p_f i l e
o s . system ( rename_command)
#t h e s w i g . i f i l e needs t o be updat ed t o r e f l e c t t h i s name change as

32

362
363
364
365
366
367
368
369
370
371
372
373
374
375

376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404

well
rename_command = " sed i s / " + f [ : 2 ] + " / " + module_name + "_" +
block_names [ f ] + " / g I " + s w i g _ i _ f i l e
o s . system ( rename_command)
rename_command = " sed i s / " + make_functio n + " / " +
i dea l _m a ke_f uncti o n + " / g I " + s w i g _ i _ f i l e
o s . system ( rename_command)
#t h e M a k e f i l e . am f i l e needs t o be updat ed t o r e f l e c t t h i s name change
as w e l l
rename_command = " sed i s / " + f [ : 2 ] + " / " + module_name + "_" +
block_names [ f ] + " / g I " + Ma kef i l e_a m _f i l e
o s . system ( rename_command)
rename_command = " sed i s / " + make_functio n + " / " +
i dea l _m a ke_f uncti o n + " / g I " + Ma kef i l e_a m _f i l e
o s . system ( rename_command)

raw_input ( R e q u i s i t e f i l e s f o r a u t o t o o l s have been c r e a t e d . P r e s s e n t e r to


c o n t i n u e wi th b o o t s t r a p , c o n f i g u r e , make , make i n s t a l l ; o r C t r l C to a b o r t
)

print ( " \n\ nRunning b o o t s t r a p . . . . . " )


o s . system ( " . / b o o t s t r a p " )
print ( " \n\ nRunning c o n f i g u r e . . . . . " )
o s . system ( " . / c o n f i g u r e p r e f i x=" + p r e f i x )
print ( " \n\ nRunning make . . . . . " )
o s . system ( " make" )
print ( " \n\ nRunning sudo make i n s t a l l . . . . . " )
o s . system ( " sudo make i n s t a l l " )
print ( " \n\ nMaking " + package_name + " a p r o p e r python pa ckag e . . . . . " )
i f o s . path . i s d i r ( i n s t a l l _ p a t h + " / " + package_name ) :
o s . system ( " sudo to uch " + i n s t a l l _ p a t h + " / " + package_name + " /__init__ .
py " )
else :
o s . system ( " sudo to uch " + i n s t a l l _ p a t h _ a l t + " / " + package_name + " /
__init__ . py " )

cl ea nu p = raw_input ( "Do you want to e r a s e a l l tem po ra ry m a k e f i l e s and swi g


f i l e s ? ( d e f a u l t=yes ) " )
i f ( " y " in cl ea nu p ) or ( "Y" in cl ea nup ) or ( l e n ( cl ea nup ) == 0 ) :
print ( " \n\ nDoing f i n a l cl ea nup . . . . . " )
o s . system ( " make c l e a n " )

33

405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

o s . system ( " rm
o s . system ( " rm
o s . system ( " rm
o s . system ( " rm
o s . system ( " rm
o s . system ( " rm

r f
r f
r f
r f
r f
r f

src / l i b / Makefile " )


s r c / l i b / M a k e f i l e . am" )
src / l i b / Makefile . in " )
s r c / l i b / . deps " )
src / li b /. i " )
s r c / l i b / M a k e f i l e . swi g . gen " )

i f len ( conforming_source_files ) > 0 :


cl ea nup = raw_input ( " Do you want to e r a s e a l l renamed s o u r c e f i l e s ? (
d e f a u l t=yes ) " )
i f ( " y " in cl ea nup ) or ( "Y" in cl ea nu p ) or ( l e n ( cl ea nup ) == 0 ) :
#remove renamed s o u r c e f i l e s , t h e y ar e no l o n g e r needed
f or f in c o n f o r m i n g _ s o u r c e _ f i l e s :
cmd = " rm r f " + f
o s . system ( cmd)

print ( " \n\ nYour b l o c k i s rea dy to use " )

34

NO. OF
COPIES
1
ELEC

ORGANIZATION
ADMNSTR
DEFNS TECHL INFO CTR
ATTN DTIC OCP
8725 JOHN J KINGMAN RD STE 0944
FT BELVOIR VA 22060-6218

US ARMY RSRCH DEV AND ENGRG CMND


ARMAMENT RSRCH DEV & ENGRG CTR
ARMAMENT ENGRG & TECHNLGY CTR
ATTN AMSRD AAR AEF T J MATTS
BLDG 305
ABERDEEN PROVING GROUND MD 21005-5001

US ARMY INFO SYS ENGRG CMND


ATTN AMSEL IE TD A RIVERA
FT HUACHUCA AZ 85613-5300

COMMANDER
US ARMY RDECOM
ATTN AMSRD AMR W C MCCORKLE
5400 FOWLER RD
REDSTONE ARSENAL AL 35898-5000

US GOVERNMENT PRINT OFF


DEPOSITORY RECEIVING SECTION
ATTN MAIL STOP IDAD J TATE
732 NORTH CAPITOL ST NW
WASHINGTON DC 20402

US ARMY RSRCH LAB


ATTN IMNE ALC HRR MAIL & RECORDS MGMT
ATTN RDRL CI J PELLEGRINO
ATTN RDRL CIN A KOTT
ATTN RDRL CIN T B RIVERA
ATTN RDRL CIN T G VERMA
ATTN RDRL CIN T P YU
ATTN RDRL CIO LL TECHL LIB
ATTN RDRL CIO MT TECHL PUB
ADELPHI MD 20783-1197

35

INTENTIONALLY LEFT BLANK.

36

Das könnte Ihnen auch gefallen