Developing Signal Processing Blocks for 

Software-defined Radios 

by Gunjan Verma and Paul Yu 

ARL-TR-5897 January 2012 

Approved for public release; distribution unlimited. 
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 manufacturer’s 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. 
ii

REPORT DOCUMENTATION PAGE Form Approved

OMB No. 0704-0188

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)

January 2012

2. REPORT TYPE

Final

3. DATES COVERED (From - To)

4. TITLE AND SUBTITLE

Developing Signal Processing Blocks for Software-defined Radios

5a. CONTRACT NUMBER

5b. GRANT NUMBER

5c. PROGRAM ELEMENT NUMBER

6. AUTHOR(S)

Gunjan Verma and Paul Yu

5d. PROJECT NUMBER

5e. TASK NUMBER

5f. WORK UNIT NUMBER

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

U.S. Army Research Laboratory

ATTN: RDRL-CIN-T

2800 Powder Mill Road

Adelphi, MD 20783-1197

8. PERFORMING ORGANIZATION

 REPORT NUMBER

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

16. SECURITY CLASSIFICATION OF:

17. LIMITATION

OF ABSTRACT

UU

18. NUMBER

OF PAGES

44

19a. NAME OF RESPONSIBLE PERSON

Gunjan Verma

a. REPORT

Unclassified

b. ABSTRACT

Unclassified

c. THIS PAGE

Unclassified

19b. TELEPHONE NUMBER (Include area code)

(301) 394-3102

Standard Form 298 (Rev. 8/98)

Prescribed by ANSI Std. Z39.18 
Contents

1. Introduction 1

2. Implementation of Blocks 2

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

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

2.2.1 Block Signatures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.2.2 Boost Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

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

2.3.1 Function: general_work() . . . . . . . . . . . . . . . . . . . . . . . . 6

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

2.3.3 Field: d_output_multiple . . . . . . . . . . . . . . . . . . . . . . . . 7

2.3.4 Field: d_relative_rate . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3. Creation of SWIG Interfaces 8

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

3.1.1 Block Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

3.1.2 Boost Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

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() . . . . . . . . . . . . . . . . . . . . . . . . . . 6

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

v
vi 

INTENTIONALLY LEFT BLANK
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

1
In this report, we detail steps 1–4. 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 std::complex<float> gr_complex;

typedef std::complex<double> gr_complexd;

typedef std::vector<int> gr_vector_int;

typedef std::vector<float> gr_vector_float;

2
typedef std::vector<double> gr_vector_double;

typedef std::vector<void *> gr_vector_void_star;

typedef std::vector<const void *> gr_vector_const_void_star;

typedef short gr_int16;

typedef int gr_int32;

typedef unsigned short gr_uint16;

typedef unsigned int gr_uint32;

2.2.1 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 cl a s s gr_io_signature {

2 int d_min_streams ;

3 int d_max_streams;

4 std : : vector<int> d_sizeof_stream_item ;

5

6 gr_io_signature (int min_streams , int max_streams ,

7 const std : : vector<int> &sizeof_stream_items ) ;

8

9 fr iend gr_io_signature_sptr

10 gr_make_io_signaturev ( int min_streams ,

11 int max_streams ,

12 const std : : vector<int> &sizeof_stream_items) ;

13

14 pub lic :

15

16 s t a t i c const int IO_INFINITE = −1;

17

18 ~gr_io_signature ( ) ;

19

20 int min_streams ( ) const { return d_min_streams ; }

21 int max_streams ( ) const { return d_max_streams; }

22 int sizeof_stream_item ( int index ) const ;

23 std : : vector<int> sizeof_stream_items ( ) const ;

24 } ;

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.

3
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 std : : st ri n g d_name;

71 gr_io_signature_sptr d_input_signature ;

72 gr_io_signature_sptr d_output_signature ;

73 long d_unique_id ;

Listing 3. gr_block.h

229 pr ivate :

230

231 int d_output_multiple ;

232 double d_relative_rate ; // appr ox o u t p u t _ r a t e /

i n 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 block’s 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 void set_hist ory (unsigned h i st o ry ) { d_history = h i st o ry ; }

105 virtua l void f o r e c a s t ( int noutput_items ,

106 gr_vector_int &ninput_items_required ) ;

122 virtua l int general_work (int noutput_items ,

123 gr_vector_int &ninput_items ,

124 gr_vector_const_void_star &input_items ,

125 gr_vector_void_star &output_items) = 0 ;

157 void consume ( int which_input , int 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 we’ve 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 Purpose

noutput_items Number of output items to write on each output stream

ninput_items Number of input items available on each input stream

input_items Vector of pointers to elements of the input stream(s), i.e.,

element i of this vector points to the i

th input stream

output_items Vector of pointers to elements of the output stream(s), i.e.,

element i of this vector points to the i

th 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 i

th element is the number of available

items on the i

th 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 scheduler’s

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 gr_block::set_output_multiple (int multiple);

int output_multiple ();

2.3.4 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 Radio’s 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 radio’s 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 pointer’s 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 one’s 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 h ich a l l o w s us t o i nv o k e our b l o c k

3 ∗ g r _m ul t i pl y_c o n s t _ f f _ f r om Py t h o n a s g r . m ul t i ply_ c on s t_ c c ( )

4 ∗ It 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 ∗ It s s e c o n d a r g um e n t ’ m ul t i pl 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 , multiply_const_ff )

11
9

10 /∗

11 ∗ gr_make_mul t i ply_co ns t_ f f i s t h e s u r r o g a t e c o n s t r u c t o r

12 ∗ i . e . t h e f r i e n d f u n c t i o n o f c l a s s g r _ m u l t i p l y _ c o n s t _ f f

13 ∗/

14 gr_multiply_const_ff_sptr gr_make_multiply_const_ff ( flo a t k ) ;

15

16

17 cl a s s gr_multiply_const_ff : pub lic gr_sync_block

18 {

19 pr ivate :

20 gr_multiply_const_ff ( flo a t k) ; // t h e " t r ue " , p r i v a t e c o n s t r u c t o r

21

22 pub lic :

23 flo a t k ( ) const { return d_k ; }

24 void set_k ( f lo a t k) { d_k = k ; }

25 } ;

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 Contents

/home/user/newBlock Top level Makefile, documentation

/home/user/newBlock/config Files for GNU Autotools

/home/user/newBlock/src Top level folder for C++ and Python files

/home/user/newBlock/src/lib 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 SWIG’s .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 block’s 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 Radio’s 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 ∗ Co py r i g h t 2004 , 2007 , 2009 , 2010 Free S o f tw a r e Foundat ion , Inc .

4 ∗

5 ∗ Th i 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 tw a r e ; you can r e d i s t r i b u t e i t and / or mod i fy

8 ∗ i t under t h e terms o f t h e GNU Gener al P ubl i c L i c e n s e as p u b l i s h e d by

9 ∗ th e Free S o f tw a r e Founda t 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 ∗ bu t WITHOUT ANY WARRANTY; w i t h o u t even t h e im pl i e d w ar r an ty o f

14 ∗ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See t h e

15 ∗ GNU Gener al P ubl 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 ul d have r e c e i v e d a copy o f t h e GNU Gener al P ubl i c L i c e n s e

18 ∗ al o ng w i t h GNU Radio ; s e e t h e f i l e COPYING. I f not , w r i t e t o

19 ∗ th e Free S o f tw a r e Founda t ion , Inc . , 51 F r a nkl 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 e f in e INCLUDED_GR_BLOCK_H

25

26 #include <gr_basic_block . 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 rm i n al ’ p r o c e s s i n g b l o c k s .

30 ∗ \ i ng r o u p b a s e_ bl k

31 ∗

32 ∗ A s i g n a l p r o c e s s i n g fl ow 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 bl o c k s , w h ich a t any l e v e l may a l s o c o n t a i n t e rm i n al nodes

34 ∗ t h a t a c t u a l l y implemen t 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 h i 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 ∗ Bl o c k s have a s e t o f i n p u t s treams and o u t p u t s treams . The

38 ∗ in 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 ∗ streams and o u t p u t s treams 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 da ta

40 ∗ it em s i n each s tream .

41 ∗

42 ∗ Al though b l o c k s may consume da ta on each i n p u t s tream 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 s treams must pr oduce da ta 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 ork ,

47 ∗ to implemen t 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 sys tem s c h e d u l e r t o de term ine how many i t em s are r e q u i r e d on

49 ∗ each i n p u t s tream 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 ∗ it em s .

17
51 ∗

52 ∗ gener al_w ork i s c a l l e d t o per f orm 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 .

53 ∗ It r e a d s t h e i n p u t i t em s and w r i t e s t h e o u t p u t i t em s .

54 ∗/

55

56 cl a s s gr_block : pub lic gr_basic_block {

57

58 pub lic :

59

60 // ! Magic r e t u r n v a l u e s from gener al_w ork

61 enum {

62 WORK_CALLED_PRODUCE = −2,

63 WORK_DONE = −1

64 } ;

65

66 enum tag_propagation_policy_t {

67 TPP_DONT = 0 ,

68 TPP_ALL_TO_ALL = 1 ,

69 TPP_ONE_TO_ONE = 2

70 } ;

71

72 virtua l ~gr_block ( ) ;

73

74 /∗ !

75 ∗ Assume b l o c k compu tes y_i = f ( x_i , x_i −1, x_i −2, x_i −3 . . . )

76 ∗ Hi s t o r y i s t h e number o f x_i ’ s t h a t are examined t o pr oduce one y_i .

77 ∗ Th i 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

78 ∗ ensure 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

79 ∗ f i l t e r . H i s t o r y s h o ul d be e q u al t o t h e number o f f i l t e r t a p s .

80 ∗/

81 unsigned h i st o ry ( ) const { return d_history ; }

82 void set_hist ory (unsigned h i st o ry ) { d_history = h i st o ry ; }

83

84 /∗ !

85 ∗ \ b r i e f Return t r ue 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 .

86 ∗

87 ∗ If tr ue , then f ixed_r a te_ in_ to_o u t and f ixed_r a te_ou t_ to_ in may be c a l l e d

.

88 ∗/

89 bool fixed_rate ( ) const { return d_fixed_rate ; }

90

91 // −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

92 // 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

93 // −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

94

95 /∗ !

96 ∗ \ b r i e f Es t ima te i n p u t r e q u i r em e n t s g i v e n o u t p u t r e q u e s t

97 ∗

98 ∗ \param nou tpu t_ i tems number o f o u t p u t i t em s t o pr oduce

99 ∗ \param n i n p u t _ i tems_re qu i red number o f i n p u t i t em s r e q u i r e d on each

i n p u t s tream

100 ∗

101 ∗ Given a r e q u e s t t o p r o d uc t \p nou tpu t_ i tems , e s t im a t e t h e number o f

102 ∗ da ta i t em s r e q u i r e d on each i n p u t s tream . The e s t im a t e doesn ’ t have

18
103 ∗ to be e x a c t , b u t s h o ul d be c l o s e .

104 ∗/

105 virtua l void f o r e c a s t ( int noutput_items ,

106 gr_vector_int &ninput_items_required ) ;

107

108 /∗ !

109 ∗ \ b r i e f compute o u t p u t i t em s from i n p u t i t em s

110 ∗

111 ∗ \param nou tpu t_ i tems number o f o u t p u t i t em s t o w r i t e on each o u t p u t

s tream

112 ∗ \param n inpu t_ i tems number o f i n p u t i t em s a v a i l a b l e on each i n p u t

s tream

113 ∗ \param inpu t_ i t ems 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 tems , one

e n t r y per i n p u t s tream

114 ∗ \param ou tpu t_ i t ems 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 tems , one

e n t r y per o u t p u t s tream

115 ∗

116 ∗ \ r e t u r n s number o f i t em 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.

117 ∗ It i s OK t o r e t u r n a v al ue l e s s than nou tpu t_ i tems . −1 <= r e t u r n v al ue

<= nou tpu t_ i tems

118 ∗

119 ∗ gener al_w ork must c a l l consume or consume_each t o i n d i c a t e how many i t em s

120 ∗ were consumed on each i n p u t s tream .

121 ∗/

122 virtua l int general_work (int noutput_items ,

123 gr_vector_int &ninput_items ,

124 gr_vector_const_void_star &input_items ,

125 gr_vector_void_star &output_items) = 0 ;

126

127 /∗ !

128 ∗ \ b r i e f C al l e d t o e n a bl e d r i v e r s , e t c f o r i /o d e v i c e s .

129 ∗

130 ∗ Th i s a l l o w s a b l o c k t o e n a bl 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

131 ∗ t r a n s f e r i n g da ta j u s t b e f o r e we s t a r t t o e xe c u t e t h e s c h e d u l e r .

132 ∗ The end r e s u l t i s t h a t t h i s r e d uc e s l a t e n c y i n t h e p i p e l i n e when

133 ∗ d e a l i n g w i t h aud i o d e v i c e s , usr ps , e t c .

134 ∗/

135 virtua l bool st a rt ( ) ;

136

137 /∗ !

138 ∗ \ b r i e f C al 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 .

139 ∗/

140 virtua l bool stop ( ) ;

141

142 // −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

143

144 /∗ !

145 ∗ \ b r i e f C ons tr a in t h e nou tpu t_ i tems argument p a s s e d t o f o r e c a s t and

gener al_w ork

146 ∗

147 ∗ s e t _ o u t p u t _m ul t i pl e c a u s e s t h e s c h e d u l e r t o ensure t h a t t he nou tpu t_ i tems

148 ∗ argument p a s s e d t o f o r e c a s t and gener al_w ork w i l l be an i n t e g e r m u l t i p l e

149 ∗ of \param m u l t i p l e The d e f a u l t v al ue o f o u t p u t m u l t i p l e i s 1 .

19
150 ∗/

151 void set_output_multiple (int multiple ) ;

152 int output_multiple ( ) const { return d_output_multiple ; }

153

154 /∗ !

155 ∗ \ 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 s tream \p

w h ich_ inpu t were consumed .

156 ∗/

157 void consume ( int which_input , int how_many_items) ;

158

159 /∗ !

160 ∗ \ 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

s tream .

161 ∗/

162 void consume_each (int how_many_items) ;

163

164 /∗ !

165 ∗ \ 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

s tream \p w h ich_ou tpu t .

166 ∗

167 ∗ If t h e b l o c k ’ s gener al_w ork method c a l l s pr oduce , \p gener al_w ork must

r e t u r n WORK_CALLED_PRODUCE.

168 ∗/

169 void produce ( int which_output , int how_many_items) ;

170

171 /∗ !

172 ∗ \ b r i e f Se t t h e appr ox ima te o u t p u t r a t e / i n p u t r a t e

173 ∗

174 ∗ Pr ov i 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 .

175 ∗ The d e f a u l t r e l a t i v e _ r a t e i s 1 . 0

176 ∗

177 ∗ de c im a t o r s have r e l a t i v e _ r a t e s < 1 . 0

178 ∗ 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

179 ∗/

180 void set _ rel a t i v e_ ra t e (double rel a t i v e_ ra t e ) ;

181

182 /∗ !

183 ∗ \ b r i e f r e t u r n t h e appr ox ima te o u t p u t r a t e / i n p u t r a t e

184 ∗/

185 double rel a t i v e_ ra t e ( ) const { return d_relative_rate ; }

186

187 /∗

188 ∗ 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

189 ∗ 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

190 ∗ r a t i o . gr_sync_bl ock , gr_sync_decima tor and g r _ sy nc_ i n t e r p ol a t o r

191 ∗ o v e r r i d e t h e s e . I f you ’ re 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 .

192 ∗/

193 /∗ !

194 ∗ \ b r i e f Given n i n p u t samples , r e t u r n number o f o u t p u t samples t h a t w i l l be

pr oduced .

195 ∗ N.B . t h i s i s o nl 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 ue .

196 ∗ Ge ne r al l y s p e a k i ng , you don ’ t need t o o v e r r i d e t h i s .

197 ∗/

198 virtua l int fixed_rate_ninput_to_noutput( int ninput ) ;

20
199

200 /∗ !

201 ∗ \ b r i e f Given n o u t p u t samples , r e t u r n number o f i n p u t samples r e q u i r e d t o

pr oduce n o u t p u t .

202 ∗ N.B . t h i s i s o nl 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 ue .

203 ∗ Ge ne r al l y s p e a k i ng , you don ’ t need t o o v e r r i d e t h i s .

204 ∗/

205 virtua l int fixed_rate_noutput_to_ninput( int noutput ) ;

206

207 /∗ !

208 ∗ \ b r i e f Return t h e number o f i t em s read on i n p u t s tream w h ich_ inpu t

209 ∗/

210 uint64_t nitems_read( unsigned int which_input ) ;

211

212 /∗ !

213 ∗ \ b r i e f Return t h e number o f i t em s w r i t t e n on o u t p u t s tream w h ich_ou tpu t

214 ∗/

215 uint64_t nitems_written (unsigned int which_output ) ;

216

217 /∗ !

218 ∗ \ 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

.

219 ∗/

220 tag_propagation_policy_t tag_propagation_policy ( ) ;

221

222 /∗ !

223 ∗ \ b r i e f Se 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 de term ine how t a g s are moved

downstream .

224 ∗/

225 void set_tag_propagation_policy ( tag_propagation_policy_t p ) ;

226

227 //

−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

228

229 pr ivate :

230

231 int d_output_multiple ;

232 double d_relative_rate ; // appr ox o u t p u t _ r a t e /

i n p u t _ r a t e

233 gr_block_detail_sptr d_detail ; // im pl em en t a t i o n d e t a i l s

234 unsigned d_history ;

235 bool d_fixed_rate ;

236 tag_propagation_policy_t d_tag_propagation_policy ; // p o l i c y f o r moving t a g s

downstream

237

238 protected:

239

240 gr_block ( const std : : st ri n g &name ,

241 g r_io_signature_sptr input_signature ,

242 g r_io_signature_sptr output_signature ) ;

243

244 void set_fixed_rate ( bool fixed_rate ) { d_fixed_rate = fixed_rate ; }

245

21
246

247 /∗ !

248 ∗ \ b r i e f Adds a new t a g on to t h e g i v e n o u t p u t b u f f e r .

249 ∗

250 ∗ \param w h ich_ou tpu t an i n t e g e r o f w h ich o u t p u t s tream t o a t t a c h t h e t a g

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

252 ∗ 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 em s_w r i t te n .

253 ∗ \param key t h e t a g key as a PMT symbol

254 ∗ \param v al ue any PMT h o l d i n g any v al ue f o r t h e g i v e n key

255 ∗ \param s r c i d 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

256 ∗/

257 void add_item_tag (unsigned int which_output ,

258 uint64_t abs_offset ,

259 const pmt : : pmt_t &key ,

260 const pmt : : pmt_t &value ,

261 const pmt : : pmt_t &srci d=pmt : :PMT_F) ;

262

263 /∗ !

264 ∗ \ 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 he r ange .

265 ∗

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

267 ∗

268 ∗ Tags are t u p l e s o f :

269 ∗ ( i tem coun t , s o u r c e i d , key , v al ue )

270 ∗

271 ∗ \param v a v e c t o r r e f e r e n c e t o r e t u r n t a g s i n t o

272 ∗ \param w h ich_ inpu t an i n t e g e r o f w h ich i n p u t s tream t o p u l l from

273 ∗ \param a b s_ s t a r t a u i n t 6 4 coun t 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

274 ∗ \param abs_end a u i n t 6 4 coun t o f t h e end o f t h e r ange o f i n t e r e s t

275 ∗/

276 void get_tags_in_range( std : : vector<pmt : : pmt_t> &v ,

277 unsigned int which_input ,

278 uint64_t abs_start ,

279 uint64_t abs_end ) ;

280

281 /∗ !

282 ∗ \ 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 he r ange

283 ∗ wi t h a g i v e n key .

284 ∗

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

286 ∗

287 ∗ Tags are t u p l e s o f :

288 ∗ ( i tem coun t , s o u r c e i d , key , v al ue )

289 ∗

290 ∗ \param v a v e c t o r r e f e r e n c e t o r e t u r n t a g s i n t o

291 ∗ \param w h ich_ inpu t an i n t e g e r o f w h ich i n p u t s tream t o p u l l from

292 ∗ \param a b s_ s t a r t a u i n t 6 4 coun t 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

293 ∗ \param abs_end a u i n t 6 4 coun t o f t h e end o f t h e r ange o f i n t e r e s t

294 ∗ \param key a PMT symbol key t o f i l t e r o nl y t a g s o f t h i s key

295 ∗/

296 void get_tags_in_range( std : : vector<pmt : : pmt_t> &v ,

297 unsigned int which_input ,

298 uint64_t abs_start ,

299 uint64_t abs_end ,

22
300 const pmt : : pmt_t &key ) ;

301

302 // These are r e a l l y o nl 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 ng t o work up an ever−v a r y i ng l i s t o f f r i e n d s

304

305 pub lic :

306 gr_block_detail_sptr d e t a i l ( ) const { return d_detail ; }

307 void set _ d et a i l ( gr_block_detail_sptr d e t a i l ) { d_detail = d e t a i l ; }

308 } ;

309

310 typedef std : : vector<gr_block_sptr> gr_block_vector_t ;

311 typedef std : : vector<gr_block_sptr >:: i t e r a t o r gr_block_viter_t ;

312

313 in l in e gr_block_sptr cast_to_block_sptr ( gr_basic_block_sptr p )

314 {

315 return boost : : dynamic_pointer_cast<gr_block , gr_basic_block >(p) ;

316 }

317

318

319 std : : ostream&

320 operator << ( std : : ostream& os , const gr_block ∗m) ;

321

322 #end i f /∗ INCLUDED_GR_BLOCK_H ∗/

23
24

INTENTIONALLY LEFT BLANK
B. The blockWizard.py Script

1 #! / usr / b i n / env py thon

2

3 #T h i 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 . S imply downl oad t h e

a r c h i v e " gr−howto−w r i t e−a−bl o c k −3 . 3 . 0 . t a r . g z " from

4 #f t p : / / f t p . gnu . org / gnu/ g n u r a d i o/ gr−howto−w r i t e−a−bl o c k −3 . 3 . 0 . t a r . g z , e x t r a c t

i t t o a d i r e c t o r y " t o p d i r " ,

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 nl y needs t o implemen t t h e bl o c k , f o r example

7 #p a r t i c u l a r l y " gener al_w ork " and " f o r e c a s t " f u n c t i o n s . I t h a n dl e s i n s t a l l a t i o n

o f s h a r e d l i b r a r y ,

8 #and e n s u r e s v a r i o u s naming " c o nv 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

o f s u r r o g a t e f r i e n d c o n s t r uc t o r ,

9 #e x p e c t e d by t h e b u i l d sys tem are f o l l o w e d . I t h a n dl e s t h e p r o p e r c r e a t i o n o f

t h e sw i g f i l e .

10

11 import os

12 import re

13 import sys

14

15 pr int " \n ! ! ! "

16 pr int " This wizard helps build ( multiple ) si g n a l p ro cessi n g blocks , and p l a ces

 them in a s i n g l e module of a s i n g l e package "

17 pr int "You only r e a l l y need to use t h i s the f i r s t time you crea t e a new block ;

 then , f o r subsequent code changes to that same block , j u st use make and 

sudo make i n s t a l l "

18 pr int " This s c r i p t w i l l d el et e old a u t o t o o l s rel a t ed f i l e s from t h i s d i rect o ry

 and generate new ones ; i f you have any concerns , back up b ef o re 

proceeding "

19 pr int " ! ! ! "

20 raw_input ( " Press enter to continue , Ctrl−C to abort : " )

21

22

23 pr int ( " \n Cleaning f i l e s from aborted previous runs . . . " )

24 os . system ( "make clean " )

25 os . system ( "rm −rf src / l i b / Makefile .am" )

26 os . system ( "rm −rf src / l i b / Makefile " )

27 os . system ( "rm −rf src / l i b / Makefile . in " )

28 os . system ( "rm −rf src / l i b / . deps " )

29 os . system ( "rm −rf src / l i b /∗ . i " )

30 os . system ( "rm −rf src / l i b / Makefile . swig . gen " )

31

32 src_headers = l i s t ( )

33 src_source = l i s t ( )

34

35 cl a ss_ i n h eri t a n ce = d i ct ( )

36 f ri en d _ con st ruct or = d i ct ( )

37 co n st ru ct o r = d i ct ( ) #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 est ru ct o r = d i ct ( ) #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 p r e f i x = raw_input ( ’ \n\ nSpecify p r e f i x : [ p r e f i x ] / l i b /python [ v ersi o n ] / si t e −

packages ( d ef a u l t = / usr / l o c a l ) : ’ )

42 i f len ( p r e f i x ) == 0 :

43 p r e f i x=" / usr / l o c a l "

44

45

46 v ersi o n = raw_input ( ’ \n\ nSpecify python v ersi o n : ’ + p r e f i x + ’ / l i b /python [

v ersi o n ] / si t e −packages ( d ef a u l t = 2 . 6 ) : ’ )

47 i f len ( v ersi o n ) == 0 :

48 v ersi o n=" 2.6 "

49

50 i n st a l l_ p at h = p r e f i x + " / l i b /python " + v ersi o n + " / si t e −packages "

51 i n st a ll_ pa th _ alt = p r e f i x + " / l i b /python " + v ersi o n + " / dist −packages " #

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

52

53 pr int ( ’ \nThe python command to import t h i s block w i l l be : from [ package_name ] 

import [ module_name ] ’ )

54 package_name = raw_input ( ’ Enter d esi red package_name ( d ef a u l t=testpack age ) : ’ )

55 i f len ( package_name ) == 0 :

56 package_name=" testpackage "

57

58 module_name = raw_input ( ’ Enter d esi red module_name ( d ef a u l t=testmodule ) : ’ )

59 i f len ( module_name ) == 0 :

60 module_name=" testmodule "

61

62 a l l _ f i l e s=os . l i s t d i r ( os . getcwd ( ) + " / src / 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 for filename in a l l _ f i l e s :

66 #h e a d e r _ p a t t ern = re . c om p il e ( ’ [ \w ]+ . h ’ )

67 #s u f f i x _ p a t t e r n = re . c om p il e ( ’ [ \w ]+ . cc ’ )

68

69 i f " . h " in filename :

70 src_headers . append( filename )

71

72 i f " . cc " in filename :

73 src_source . append( filename )

74

75

76

77 pr int ( ’ \n\nThe python command to crea t e t h i s block w i l l be : o b j ect = ’ +

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 for filename in src_headers :

81 i = i + 1

82 block_name = raw_input ( ’ Enter d esi red block_name corresponding to block 

implemented in ’ + filename [: −2 ] + ’ ( d ef a u l t=test_block ’ + st r ( i ) + ’

, 0 f o r none ) : ’ )

83 i f len ( block_name ) == 0 :

84 block_name=" test_block " + st r ( i )

85 i f block_name == 0 :

86 block_name=" "

26
87 block_names [ filename ] = block_name

88

89

90

91 #f i g u r e ou t w h ich c l a s s e s i n h e r i t from w h ich b l o c k s ( e . g . from g r _ bl 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 h ich do no t i n h e r i t a t a l l )

92 class_dec_pattern = re . compile ( ’ [ \ s ] ∗ c l a s s [ \ s \w]+: ’ )

93 for filename in src_headers :

94 f = open ( os . getcwd ( ) + " / src / l i b / " + filename , ’ r ’ )

95 for l i n e in f :

96 if class_dec_pattern . match ( l i n e ) :

97 m = re . search ( ’ [ \ s ]+[\w]+$ ’ , l i n e ) #f i n d t h e name o f t h e c l a s s

t h a t i s i n h e r i t e d

98 i f m:

99 c l a ss_ i n h eri t a n ce [ filename ] = m. group ( ) . s t r i p ( )

100 el s e :

101 c l a ss_ i n h eri t a n ce [ filename ] = " "

102 f . cl o se ( )

103

104

105

106 #f i g u r e ou t 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

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 " f il e n am e ( " ( where

f il e n am e i s w i t h o u t t h e . h )

108 for filename in src_headers :

109

110 co n st ru ct o r_ st ri n g=" "

111 constructor_name=filename [: −2 ] #e v e r y t h i n g b u t t h e . h

112 multi_line=0

113

114 f = open ( os . getcwd ( ) + " / src / l i b / " + filename , ’ r ’ )

115

116 for l i n e in f :

117 if ( ( constructor_name + " ( " ) in l i n e ) or ( ( constructor_name + " ( " ) 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 st ru ct o r_ st ri n g=l i n e

119 i f ( " p u b l i c " in previous_ line ) or ( " p ri v a t e " in previous_ line ) or

( " protect ed " in previous_ line ) :

120 c o n st ru ct o r_ st ri ng = previous_ line + co n st ru ct o r_ st rin g

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 multi_line=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

l i n e s ?

123 break

124 el s e :

125 multi_line=1

126 continue

127

128 if multi_line == 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

l i n e s

129 c o n st ru ct o r_ st rin g = co n st ru ct o r_ st rin g + l i n e

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 s em i c ol o n

131 break

132

27
133 previous_ line = 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

134

135 co n st ru ct o r [ filename ] = co n st ru ct o r_ st ri ng #t h e r e i s one c o n s t r u c t o r per

c l a s s o b v i o u s l y

136

137 f . cl o se ( )

138

139

140

141

142

143

144

145

146

147 #f i g u r e ou t 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

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 "~ f il e n am e " ( where

f il e n am e i s w i t h o u t t h e . h )

149 for filename in src_headers :

150

151 d est ru ct o r_ st ri n g=" "

152 destructor_name=filename [: −2 ] #e v e r y t h i n g b u t t h e . h

153 multi_line=0

154

155 f = open ( os . getcwd ( ) + " / src / l i b / " + filename , ’ r ’ )

156

157 for l i n e in f :

158 if ( "~" + destructor_name ) 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

d e c l a r a t i o n

159 d est ru ct o r_ st ri n g=l i n e

160 i f ( " p u b l i c " in previous_ line ) or ( " p ri v a t e " in previous_ line ) or

( " protect ed " in previous_ line ) :

161 d est ru ct o r_ st ri n g = previous_ lin e + d est ru ct o r_ st ri 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 multi_line=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

l i n e s ?

164 break

165 el s e :

166 multi_line=1

167 continue

168

169 if multi_line == 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 d est ru ct o r_ st ri n g = d est ru ct o r_ st ri n g + l i n e

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 s em i c ol o n

172 break

173

174 previous_ line = 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 est ru ct o r [ filename ] = d est ru ct o r_ st ri n g #t h e r e i s one c o n s t r u c t o r per

c l a s s o b v i o u s l y

177

28
178 f . cl o se ( )

179

180

181

182

183

184

185

186 #f i g u r e ou t 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 no t have t h i s )

187 for filename in src_headers :

188

189

190 f ri en d=" "

191 t a rg et="+_)(∗&%%@#NNKSJAHFIUWEROIWEALSKJFD"

192 multi_line=0

193

194 f = open ( os . getcwd ( ) + " / src / l i b / " + filename , ’ r ’ )

195

196 for l i n e in f :

197 if " boost : : shared_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 rg et = 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 , then

dr op t h e s em i c ol o n o f t h a t l a s t word

199 continue

200

201 if t a rg et in l i n e :

202 #f r i e n d s . append ( l i n e . s t r i p ( ) )

203 fri en 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 multi_line=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 el s e :

208 multi_line=1

209 continue

210

211 if multi_line == 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 fri en d = f ri en d + l i n e

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

s em i c ol o n

215 break

216

217 f ri en d _ co n stru ct or [ filename ] = f ri en d

218

219 f . cl o se ( )

220

221

222

223 pr int

224 pr int "

∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗∗

"

29
225 pr int " Block w i l l be imported in python as : from " + package_name

+ " import " + module_name

226

227 for value in block_names . values ( ) :

228 i f len ( value ) > 1 :

229 pr int "New o b j ect s in python w i l l be made as : o b j ect = " +

module_name + " . " + value + " ( ) "

230

231

232 pr int " Detected block header f i l e s are : " , src_headers

233 pr int " Detected block source f i l e s are : " , src_source

234 pr int " Block c l a s s e s i n h e r i t gnuradio base c l a s s e s as : " , cl a ss_ i n h eri t a n ce

235 pr int " Class co n st ru ct o rs are : " , co n st ru ct o r

236 pr int " Class d est ru ct o rs are : " , d est ru ct o r

237 pr int " Friend p u b l i c co n st ru ct o rs are : " , f ri en d _ co n stru ct or

238 pr int " I n s t a l l path of t h i s package i s : " , i n st a l l _ pa t h

239 pr int "

∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗∗

"

240

241 raw_input ( ’ \ nPress enter to continue , or Ctrl C to abort ’ )

242

243

244

245

246 #c r e a t e . i f i l e

247 sw i g _ i _f ile = open ( os . getcwd ( ) + " / src / l i b / " + module_name + " . i " , ’w ’ )

248 sw i g _ i _f ile . write ( ’ /∗ −∗− c++ −∗− ∗/ ’ )

249 sw i g _ i _f ile . write ( ’ \n%i n cl u d e " gnuradio . i " ’ )

250 sw i g _ i _f ile . write ( ’ \n%{ ’ )

251 for filename in src_headers :

252 sw i g _ i _ fil e . write ( ’ \n#i n cl u d e " ’ + filename + ’ " ’ )

253 sw i g _ i _f ile . write ( ’ \n%} ’ )

254

255 for filename in src_headers :

256 i f ( block_names [ filename ] != ’ 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 im pl em e n ta t i o n and no t h e l p e r f i l e s

257 sw i g _ i _ file . write ( ’ \n\nGR_SWIG_BLOCK_MAGIC( ’ + module_name + ’ , ’ +

block_names [ filename ] + ’ ) ; ’ )

258 sw i g _ i _ file . write ( ’ \n\n ’ + f ri en d _ co n st ru ct or [ filename ] )

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 sw i g _ i _ fil e . write ( ’ \n\n ’ + ’ c l a s s ’ + filename [: −2 ] + ’ : p u b l i c ’ +

cl a ss_ i n h eri t a n ce [ filename ] )

262 sw i g _ i _ fil e . write ( ’ \n{ ’ )

263 sw i g _ i _ fil e . write ( ’ \n\n ’ + co n st ru ct o r [ filename ] )

264 sw i g _ i _ fil e . write ( ’ \n\n ’ + d est ru ct o r [ filename ] )

265 sw i g _ i _ fil e . write ( ’ \n } ; ’ )

266

267 sw i g _ i _f ile . cl o se ( )

268

269

270 #c r e a t e M a k e f il e . am f i l e i n / s r c / l i b

271 Makefile_am_file = open ( os . getcwd ( ) + " / src / l i b / Makefile .am" , ’w ’ )

30
272

273 Makefile_am_file . write ( ’ i n cl u d e $ ( top_srcdir ) / Makefile .common ’ )

274 Makefile_am_file . write ( ’ \n\ngrinclude_HEADERS = \\ ’ )

275 i = 0

276 for filename in src_headers :

277 i = i + 1

278 Makefile_am_file . write ( ’ \n\ t ’ + filename )

279 i f ( i < len ( src_headers ) ) :

280 Makefile_am_file . write ( ’ \ ’ )

281

282 Makefile_am_file . write ( ’ \n\n\nTOP_SWIG_IFILES = \\ ’ )

283 Makefile_am_file . write ( ’ \n\ t ’ + module_name + ’ . i ’ )

284

285 Makefile_am_file . write ( ’ \n\n ’ + module_name + ’ _pythondir_category = \\ ’ )

286 Makefile_am_file . write ( ’ \n\ t ’ + package_name )

287

288 Makefile_am_file . write ( ’ \n\n ’ + module_name + ’ _la_swig_sources = \\ ’ )

289 i = 0

290 for filename in src_source :

291 i = i + 1

292 Makefile_am_file . write ( ’ \n\ t ’ + filename )

293 i f ( i < len ( src_source ) ) :

294 Makefile_am_file . write ( ’ \ ’ )

295

296 Makefile_am_file . write ( ’ \n\ ninclude $ ( top_srcdir ) / Makefile . swig ’ )

297 Makefile_am_file . write ( ’ \n\nBUILT_SOURCES = $ ( swig_built_sources ) ’ )

298 Makefile_am_file . write ( ’ \n\ nno_dist _files = $ ( swig_built_sources ) ’ )

299

300 Makefile_am_file . cl o se ( )

301

302 #c r e a t e M a k e f il e . am i n / s r c / py thon

303 Makefile_am_file = open ( os . getcwd ( ) + " / src /python/ Makefile .am" , ’w ’ )

304 Makefile_am_file . write ( ’ i n cl u d e $ ( top_srcdir ) / Makefile .common ’ )

305 Makefile_am_file . cl o se ( )

306

307

308 #c r e a t e M a k e f il e . sw i g . gen

309 os . system ( " cp src / l i b / Makefile . swig . gen .TEMPLATE src / l i b / Makefile . swig . gen " )

310 module_command = " sed −i s / testmodule/ " + module_name + " / gI src / l i b / Makefile .

swig . gen "

311 package_command = " sed −i s / gnuradio / " + package_name + " / gI src / l i b / Makefile .

swig . gen "

312 os . system (module_command)

313 os . system ( package_command )

314

315

316 #The b u i l d sys tem 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 [ module_name ]_[

block_name ] . h or [ module_name ]_[ block_name ] . cc

317 #T h i s i s based o f f a gnu r a d i o c o nv e n t i o n . I f our f i l e s are 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 are named a c c o r d i ng t o gnu r a d i o conven t i on , i . e .

modulename_blockname . h and . cc ( i n c a s e t h ey don ’ t e x i s t ) so t h a t make i s

31
happy

320 conforming_source_files = l i s t ( ) #l i s t o f s o u r c e f i l e s con f orm ing t o p r o p e r

gnu r a d i o naming c o nv e n t i o n

321 sw i g _ i _f ile = " src / l i b / " + module_name + " . i "

322 Makefile_am_file = " src / l i b / Makefile .am"

323

324 for 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

325 make_function=" "

326 ideal_make_function=" "

327

328 filename = " src / l i b / " + f

329 ideal_name = " src / l i b / " + module_name + "_" + block_names [ f ]

330

331 i f (not os . path . i s f i l e ( ideal_name + " . h " ) ) : #t h e con f orm ing , c o nv e n t i o n a l

name does no t e x i s t ; c r e a t e i t

332 raw_input ( " \ nSource names do not conform to GNU radio convention ! 

Press enter to continue with auto−renaming . . . . . \ n" )

333 tmp_file = ideal_name + " . h"

334 cmd = " cp " + filename [: −2] + " . h " + tmp_file

335 os . system (cmd)

336 conforming_source_ files . append( tmp_file )

337 rename_command = " sed −i s / " + f [: −2] + " / " + module_name + "_" +

block_names [ f ] + " / gI " + tmp_file

338 os . system (rename_command)

339

340 #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

341 if len ( f ri en d _ co n stru ct or [ f ] ) > 0 : #t h i s f i l e has a f r i e n d

c o n s t r u c t o r

342 tokens=f ri en d _ co nst ru cto 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 h ich are 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 h ich we want

343 make_function=tokens [ 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

f r i e n d c o n s t r u c t o r

344 i f " ( ) ; " in make_function :

345 make_function=make_function [: −3]

346 e l i f " ( ) " in make_function :

347 make_function=make_function [: −2]

348 ideal_make_function = module_name + "_make_" + block_names [ f ]

349 rename_command = " sed −i s / " + make_function + " / " +

ideal_make_function + " / gI " + tmp_file

350 os . system ( rename_command)

351

352 tmp_file = ideal_name + " . cc "

353 cmd = " cp " + filename [: −2] + " . cc " + tmp_file

354 os . system (cmd)

355 conforming_source_ files . append( tmp_file )

356 rename_command = " sed −i s / " + f [: −2] + " / " + module_name + "_" +

block_names [ f ] + " / gI " + tmp_file

357 os . system (rename_command)

358 rename_command = " sed −i s / " + make_function + " / " +

ideal_make_function + " / gI " + tmp_file

359 os . system (rename_command)

360

361 #t h e sw i g . i f i l e needs t o be upda ted t o r e f l e c t t h i s name change as

32
w e l l

362 rename_command = " sed −i s / " + f [: −2] + " / " + module_name + "_" +

block_names [ f ] + " / gI " + sw i g _ i _ fi le

363 os . system (rename_command)

364 rename_command = " sed −i s / " + make_function + " / " +

ideal_make_function + " / gI " + sw i g _ i _ file

365 os . system (rename_command)

366

367 #t h e M a k e f il e . am f i l e needs t o be upda ted t o r e f l e c t t h i s name change

as w e l l

368 rename_command = " sed −i s / " + f [: −2] + " / " + module_name + "_" +

block_names [ f ] + " / gI " + Makefile_am_file

369 os . system (rename_command)

370 rename_command = " sed −i s / " + make_function + " / " +

ideal_make_function + " / gI " + Makefile_am_file

371 os . system (rename_command)

372

373

374

375 raw_input ( ’ R eq u i sit e f i l e s f o r a u t o t o o l s have been created . Press enter to 

continue with bootstrap , configure , make , make i n s t a l l ; or Ctrl C to abort

’ )

376

377

378

379

380 pr int ( " \n\nRunning bootstrap . . . . . " )

381 os . system ( " . / bootstrap " )

382

383 pr int ( " \n\nRunning co n f i g u re . . . . . " )

384 os . system ( " . / co n f i g u re −−p r e f i x=" + p r e f i x )

385

386

387 pr int ( " \n\nRunning make . . . . . " )

388 os . system ( "make" )

389

390 pr int ( " \n\nRunning sudo make i n s t a l l . . . . . " )

391 os . system ( " sudo make i n s t a l l " )

392

393 pr int ( " \n\nMaking " + package_name + " a proper python package . . . . . " )

394

395 i f os . path . i s d i r ( i n st a l l _ pa t h + " / " + package_name ) :

396 os . system ( " sudo touch " + i n st a l l _p a th + " / " + package_name + " /__init__ .

py " )

397 el s e :

398 os . system ( " sudo touch " + i n st a ll_ p ath _ alt + " / " + package_name + " /

__init__ . py " )

399

400

401 cleanup = raw_input ( "Do you want to era se a l l temporary m a k ef i l es and swig 

f i l e s ? ( d ef a u l t=yes ) " )

402 i f ( " y " in cleanup ) or ( "Y" in cleanup ) or ( len ( cleanup ) == 0) :

403 pr int ( " \n\nDoing f i n a l cleanup . . . . . " )

404 os . system ( "make clean " )

33
405 os . system ( "rm −rf src / l i b / Makefile " )

406 os . system ( "rm −rf src / l i b / Makefile .am" )

407 os . system ( "rm −rf src / l i b / Makefile . in " )

408 os . system ( "rm −rf src / l i b / . deps " )

409 os . system ( "rm −rf src / l i b /∗ . i " )

410 os . system ( "rm −rf src / l i b / Makefile . swig . gen " )

411

412 i f len ( conforming_source_ files ) > 0 :

413 cleanup = raw_input ( "Do you want to era se a l l renamed source f i l e s ? (

d ef a u l t=yes ) " )

414 i f ( " y " in cleanup ) or ( "Y" in cleanup ) or ( len ( cleanup ) == 0) :

415 #remove re−named s o u r c e f i l e s , t h ey are no l o n g e r needed

416 for f in conforming_source_ files :

417 cmd = "rm −r f " + f

418 os . system (cmd)

419

420

421

422 pr int ( " \n\nYour block i s ready to use " )

34
35

NO. OF 

COPIES ORGANIZATION 

 1 ADMNSTR 

 ELEC DEFNS TECHL INFO CTR 

 ATTN DTIC OCP 

 8725 JOHN J KINGMAN RD STE 0944 

 FT BELVOIR VA 22060-6218 

 1 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 

 1 US ARMY INFO SYS ENGRG CMND 

 ATTN AMSEL IE TD A RIVERA 

 FT HUACHUCA AZ 85613-5300

 1 COMMANDER 

 US ARMY RDECOM 

 ATTN AMSRD AMR W C MCCORKLE 

 5400 FOWLER RD 

 REDSTONE ARSENAL AL 35898-5000

 1 US GOVERNMENT PRINT OFF 

 DEPOSITORY RECEIVING SECTION 

 ATTN MAIL STOP IDAD J TATE 

 732 NORTH CAPITOL ST NW

 WASHINGTON DC 20402 

 8 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 
36

INTENTIONALLY LEFT BLANK.