Showing posts with label Gnuradio Documentation. Show all posts
Showing posts with label Gnuradio Documentation. Show all posts

Sunday, October 14, 2012

File Descriptors in GNU Radio


When a program opens a file, the operating system returns a corresponding file descriptor that the program refers to in order to process the file. A file descriptor is a low positive integer.

The first three file descriptors (0,1, and 2,) are associated with the standard input (stdin), the standard output (stdout), and the standard error (stderr), respectively.


Lets take following example in GNU Radio :

# open socket output :
         port=7001
         self.fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 


# socket() is also an operator which returns the file descriptor number

# fd will contain the value 1 as it is related to output at port 7001
# this value of fd is used as input argument to the gr_file_descriptor_source/sink
 
         self.fd.connect(('192.168.1.53',7001))  
         self.file = gr.file_descriptor_sink(gr.sizeof_gr_complex,self.fd.fileno() )
         self.connect(self.u,self.file


file descriptor can also be obtained in python by

seld.fid = open(....)

example :

self.file = open(filename,"w")  
self.save = gr.file_descriptor_sink(gr.sizeof_short,self.file.fileno()) 


To use a gr_file_descriptor, you need to open the file  yourself beforehand, the closing should thus happen in the same scope.

Reference : http://gnuradio.4.n7.nabble.com/Passing-file-descriptors-via-SWIG-tc26287.html#a26288

Here is the wikipedia link about file descriptors, here you can see the general operators which create a file descriptors as well the common operation which can be done on file descriptors

http://en.wikipedia.org/wiki/File_descriptor  


details of gr_file_descriptor are at :

http://gnuradio.org/doc/doxygen/classgr__file__descriptor__sink.html#details

http://gnuradio.org/doc/doxygen/gr__file__descriptor__source_8h.html


       




Using File source & File sinks in GNU Radio

Source
Usage:

src = gr.file_source ( type_t type, char *filename, bool repeat )

valid types are
  • gr.sizeof_char
  • gr.sizeof_double
  • gr.sizeof_float
  • gr.sizeof_gr_complex
  • gr.sizeof_int
  • gr.sizeof_short

The above are gnuradio customized data types which can be found in /usr/local/include/gnuradio
gr_types.h & gr_complex.h




http://gnuradio.org/doc/doxygen/gr__types_8h_source.html

http://gnuradio.org/doc/doxygen/gr__complex_8h_source.html


Example:

    src = gr.file_source ( gr.sizeof_gr_complex, "/home/sumit/input_wave", 1)

Doing this a file source object src  is created which can then be connected to other object using connect method.

src will read a file named "input_wave" situated in /home/sumit as a complex signal and repeat it continuously.

For last parameter given as zero there wont be repeat of the data.

Example:

    disk_src = gr.file_source ( gr.sizeof_short, "/home/sumit/burst", 0)
reads a file named "burst" situated in /home/sumit  as short (2 byte) integers one time.

Sink
Usage:

    dst = gr.file_sink ( type_t type, char *filename )

Example:

    sig_cap = gr.file_sink ( gr.sizeof_float, "/home/sumit/capture")
Creates and records to a floating point file named "capture" situated in /home/sumit/



Reference : http://www.swigerco.com/gnuradio/file_io.html


Saturday, October 13, 2012

GNURADIO Documentation : Suggested Readings

I would personally suggest following readings before you take GNU Radio seriously :


Python basics : There is a very good tutorial by Bucky on his youtube channel, and he almost covers all the Python we need. Its very quick and effective. Click here to go to his channel Python tutorial

Once you are done follow up my python tutorial where I will link up everything you have learned in python , with GNU Radio

C++ basics : Here also I would suggest Bucky’s channel for quick and fast C++ Here is the link
C++ Tutorial-1,  C++ Tutorial-2
Both are by Bucky.

Regarding Digital communication and Signal processing part, refer to any standard books. In my opinion Understanding Digital Signal processing by Richard G. Lyons is a very good book.



http://www.amazon.com/Understanding-Digital-Signal-Processing-2nd/dp/0131089897

 For Digital communications you can refer to video tutorials by IIT-Bombay , NPTEL, here is the link http://nptel.iitm.ac.in/video.php?subjectId=117101051

Apart from this you may not need anything as you will learn many things on the fly :)

Friday, October 12, 2012

Understanding a Singal Processing Block in GNU Radio : SWIG Interface : Files

SWIG Interface files :

Once we have created our .cc and .h files its the time to create the SWIG (.i) file, so that our new block can be called form python 

SWIG is used as a necessary "glue ", 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 .cc or .h file where several functions are declared
However in .i file only those functions are declared which we want to access from python

Its typically quite short in length

lets see an example of an .i file gr_multiply_const_ff.i

GR_SWIG_BLOCK_MAGIC(gr,multiply_const_ff)

gr_multiply_const_ff_sptr
gr_make_multiply_const_ff (float k, size_t vlen=1);

class gr_multiply_const_ff : public gr_sync_block
{
public:
  float k() const;
  void set_k(float k);
};

Lets notice some important facts ,

we have invoked GR_SWIG_BLOCK_MAGIC with parameters "gr" and "multiply_const_ff" and it 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

and 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 multiply_const_ff is a function within this package

The way which we have created the .i files specifies the particular names that python ascribes to the package (gr) and function (multiply_const_ff)


Reference : http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA556803



Understanding a Singal Processing Block in GNU Radio : SWIG Interface : Naming Conventions

Download the file gr-howto-write-a-block-3.3.0.tar.gz from
http://gnuradio.org/releases/gnuradio/gr-howto-write-a-block-3.3.0.tar.gz

Naming convention for block names :

After we create our block the only way we can use it in GNU Radio is to create a python script which loads the package/module containing the our block, and then connect our block to the GNU Radio flow graph

It will be something like this :

from package_name import module_name

new_block = module_name.block_name()

There is an important key coupling between the module and block names which we invoke in python, and the names used in the coding blocks of C++

GNU Radio expects that all the C++ source and header files are in the form [module_name]_[block_name].h  and [module_name]_[block_name].cc

Hence if we decided to name our C++ class as newModule_newBlock, then GNU Radio's build system would make our block available from python in module "newModule" and with block name "newBlock"

Naming convention for boost smart pointers :

All pointers to the GNU Radio blocks must use boost shared pointers and not the regular C++ pointers

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 regular C++ pointer to newBlock_newFunction in our code

In other words the command

newModule_newBlock* ptr newBlock_newFunction() wont work in GNU Radio

This rule is enforced by making all the 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 pubic interface for creating new block instances

The solution is to declare a friend function !!

This is done by first declaring a friend function of the class, so that it has access to all the private members of the class including the private constructor

This friend function invokes the private constructor and returns a smart pointer to it 

We invoke this friend function everytime we want to construct a new object of the class

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_sptr

friend newModule_newBlock_cc_sptr newModule_make_newBlock_cc()

Now the function newModule_make_newBlock_cc has access to the private members of the class newModule_newBlock_cc

The final step is to cast the return pointer's data type from raw C++ pointer to a smart pointer

newModule_newBlock_cc_sptr newModule_make_newBlock_cc() () {
   return newModule_newBlock_cc_sptr (new newModule_newBlock_cc());
      }

By the way the private constructor which can be invoked directly is some thing like as follows :

newModule_newBlock_cc() {
            gr_block("newBlock_cc",
            gr_makeio_signature (1,1, sizeof (gr_complex)),
            gr_make_iosignature (1,1, sizeof (gr_complex))
)
}

So to summarize, the private constructor is actually creating a new gr_block object

The "friend constructor" which is 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 complex procedure ensures that all the pointers to the block are boost smart pointers

The public interface for creating objects is actually not the  object constructor newModule_newBlock_cc but rather the "surrogate" constructor newModule_make_newBlock_cc

So in our code we must use the following code to create a new block object nb :

newModule_newBlock_cc_sptr nb = newModule_make_newBlock_cc()

One important point to be mentioned here : 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 would lead to code not working properly

The above naming  has nothing to do with the C++ , but when this C++ block is invoked from python in a GNU Radio program , GNU Radio expects the name of shared pointer to follow directly from the block name with an appended _sptr to it, or else it will complain that it couldn't find the block


Also the surrogate constructor which creates a shared pointer to newModue_newBlock_cc must have signature

newModule_newBlock_cc_sptr newModule_make_newBlock_cc()

*Note the presence of the word make between newModule and newBlock






Reference : http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA556803

Understanding a Singal Processing Block in GNU Radio : d_output_multiple & d_relative_rate

Now we know that the GNU Radio scheduler is responsible for invoking general_work() and forecast() functions

The forecast() function allows us to signal to the scheduler to invoke our general_work() only when a sufficient number input elements are in the input buffer

Till now we haven't seen any such mechanism to control the number of outputs being produced

the argument noutput_items in the forecast() function, which is specified by the scheduler, contains the number of output items on each of the output stream

We cannot directly set this value as it is under the scheduler's control but there is a variable d_output_multiple which tells the scheduler that the value of noutput_items must be an integer multiple of d_output_multiple

In other words the scheduler only invokes forecast() and general_work() when noutput_items is an integer multiple of d_output_multiple

default value of d_output_multiple is 1

Say we want to generate outputs only in a 64 elements chunk, by setting d_output_multiple to 64 we can achieve this, but note that we can also get multiples of 64 i.e. 128, 256 etc

The to set the value of d_output_multiple we have set_output_multiple() function the definition of which can be found in gnuradio/gnuradio-core/src/lib/runtime
gr_block.cc as follows :

void
gr_block::set_output_multiple (int multiple)
{
  if (multiple < 1)
    throw std::invalid_argument ("gr_block::set_output_multiple");

  d_output_multiple_set = true;
  d_output_multiple = multiple;
}

There is always 2 way communication with the scheduler. The d_relative_rate is the way we tell the scheduler the approximate ratio of the output rate to the input rate at which we expect our signal processing algorithm to operate.

The key purpose of the d_relative_rate is to allow the scheduler ti optimize its use memory and timings of invocation of general_work()

For many blocks the value of d_relative_rate is 1 but for decimators it is less than 1 and for interpolators it is  greater than 1

The function definition used to set the value of d_relative_rate can be found in gr_block.cc as follows :

void
gr_block::set_relative_rate (double relative_rate)
{
  if (relative_rate < 0.0)
    throw std::invalid_argument ("gr_block::set_relative_rate");

  d_relative_rate = relative_rate;
}


Reference : http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA556803

Understanding a Singal Processing Block in GNU Radio : forecast() & set_history()

forecast() function is our way to tell the scheduler about our estimate of input elements that will be needed to create an output element.

For example a decimating filter of order 5 requires 5 inputs to give an output.

Definition of forecast() in gr_block.h is as follows :

  virtual void forecast (int noutput_items,
             gr_vector_int &ninput_items_required);

The key is argument ninput_items_required which tells number of input items required at each input stream to produce  noutput_items number of output items at each output stream

Mostly this quantity can be estimated but there may happen some cases where we cannot estimate this quantity exactly

When the scheduler determines that it is ready to handle noutput_items number of 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 10-to-1 decimatorwill requires 10 inputs to produce one output but if only 9 inputs are available it will not call the general_work() if the forecast function is correctly implemented

But the case of of a moving average filter is a bit different. Say we have a moving average filter of length 5, it does not require 5 new inputs to create the single output, it still takes only one input to produce a new output

But our forecast() function would still call for a one to one relation of noutput_items to ninput_items_required

In this case, the fact that we need five most recent inputs would be specified to the GNU Radio via the set_history(5) function call

Its definition is given in gr_block.h as follows :

void  set_history (unsigned history) { d_history = history; }

Reference : http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA556803



Understanding a Singal Processing Block in GNU Radio : general_work()

Function : general_work()

The function general_work() implements the process of converting the input streams to output streams

Following are the arguments to this function :

virtual int general_work (
                 int                                             noutput_items,
                 gr_vector_int                            &ninput_items,
                 gr_vector_const_void_star        &input_items,
                 gr_vector_void_star                   &output_items) = 0;


The above definition can be found in gr_block.h and it is a virtual function hence can be redefined in the derived class.

Its a pure virtual function and we definitely need to override in case we are making our won signal processing block

Lets see what these different arguments do

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 the elements of the input(s) streams i.e. element i of this vector points to the ith input stream

output_items : vector of pointers to the elements of the output(s) streams i.e. element i of this vector points to ith output stream

A signal processing block can have multiple inputs and multiple outputs

ninput_items is a vector whose ith element is the number of available items on the ith input stream

However noutput_items is not a vector but scalar because GNU Radio implementation forces the number of output items to write on each output stream to be the same

Return value of the general_work() is the number of items actually written to each output stream, or -1 for EOF(end of file)

It is OK to return a value less than noutput_items.  -1 <= return value <= noutput_items

To create a signal processing block we simple define how to create output_items from input_items assuming that all the parameters are provided to us. i.e. we implement the signal processing algorithm in this method i.e. general_work()

After we have defined general_work() for our custom signal processing block, we need to invoke the consume() function

void consume (int which_input, int how_many_items);

to indicate to the scheduler how many items (how_many_items) have been processed on each input stream (which_input)

Since the scheduler is providing us all the appropriate parameters for us to write our own block , we need to feedback the scheduler so it knows which element have been used , so it can mark appropriate memory for deletion or reuse, and update pointers to point to the new data.

This feedback of our signal processing process to the scheduler is provided via the consume function

Reference : http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA556803


Understanding a Singal Processing Block in GNU Radio : gr_block.h

A signal processing flow is constructed by creating a tree of hierarchical blocks, which at any level may also contain terminal nodes that actually implement signal processing functions. gr_block.h is the base class for all such leaf nodes.

You can find it at /usr/local/include/gnuradio/gr_block.h
or http://gnuradio.org/doc/doxygen/gr__block_8h_source.html

Blocks have a set of input streams and output streams.

The input_signature and output_signature define the number of input streams and output streams respectively, and the type of the data items in each stream.

Although blocks may consume data on each input stream at a different rate, all outputs streams(of the same block) must produce data at the same rate.  That rate may be different from any of the input rates.

All the signal processing blocks are derived from the gr_block.h

User derived blocks override two methods, forecast and general_work, to implement their signal processing behavior.

forecast is called by the system scheduler to determine how many items are required on each input stream in order to produce a given number of output
items.

general_work is called to perform the signal processing in the block. It reads the input items and writes the output items.

As you can see in the definition, gr_block is itself a (public)derived class of the base class of gr_basic_block

Lets see the important fields and those which are inherited from the gr_basic_block and redefined in the gr_block

gr_basic_block.h has following protected variables :

std::string                       d_name;
gr_io_signature_sptr      d_input_signature;
gr_io_signature_sptr      d_output_signature;
long                                d_unique_id;

gr_block.h has following private variables :

int                                   d_output_multiple;                                     double                            d_relative_rate;    // approx output_rate / input_rate
gr_block_detail_sptr      d_detail;        // implementation details

d_name and d_unique_id (text and numeral respectively )are unique identifiers for the block and can be used for debugging

d_output_multiple and d_relative_rate informs the scheduler of the block about block's rate of data consumption and generation

d_input_signature, d_output_signature, d_detail are all boost smart pointers.

d_input_signature, d_output_signature pointing towards gr_io_signature type objects

d_detail pointing towards gr_block_detail type objects

Lets look at some important functions in gr_block.h

void  set_history (unsigned history) { d_history = history; }

virtual void forecast (int noutput_items,
             gr_vector_int &ninput_items_required);

virtual int general_work (int noutput_items,
                gr_vector_int &ninput_items,
                gr_vector_const_void_star &input_items,
                gr_vector_void_star &output_items) = 0;

void consume (int which_input, int how_many_items);

A block tell the scheduler how much processing has been done so far and how much more input the block needs to produce more output.
It is done so that the scheduler knows what data it no longer needs to store, how much buffer memory to allocate, when to schedule the block to execute next etc.

This in turn, determines when the scheduler will invoke the next of the block and with how much input.


Reference : http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA556803

Thursday, October 11, 2012

Understanding a Singal Processing Block in GNU Radio : Boost Smart/Shared Pointers

Boost Smart 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.

Smart pointers are particularly useful in the face of exceptions as they ensure proper destruction of dynamically allocated objects. They can also be used to keep track of dynamically allocated objects shared by multiple owners. Conceptually, smart pointers are seen as owning the object pointed to, and thus responsible for deletion of the object when it is no longer needed.

In fact, the smart pointers are defined as class templates(a class template provides a specification for generating classes based on parameters)

The library smart_ptr provides five smart pointer class templates, but in GNU Radio, we only use one of them: shared_ptr, defined in

To use the smarter pointer shared_ptr in GNU Radio, first we need to include the header file . Then we can use it to define a smart pointer as:

typedef boost::shared_ptr   pointer_name


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_sptr;
 

gr_io_signature_sptr ptr;

Now ptr is a boost smart pointer to the type of object gr_io_signature

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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.

Lets open gr_runtime_types.h You can find it in /usr/local/include/gnuradio/gr_runtime_types.h
or (http://gnuradio.org/doc/doxygen/gr__runtime__types_8h_source.html)

Here you can see the typedefs for smart pointers we use throughout the runtime system

First all classes are declared and then their boost smart pointers have been typedef

class gr_basic_block;
class gr_block;
class gr_block_detail;
class gr_hier_block2;
class gr_io_signature;
class gr_buffer;
class gr_buffer_reader;
class gr_flowgraph;
class gr_flat_flowgraph;
class gr_top_block;
class gr_top_block_detail;

typedef boost::shared_ptr       gr_basic_block_sptr;
typedef boost::shared_ptr             gr_block_sptr;
typedef boost::shared_ptr    gr_block_detail_sptr;
typedef boost::shared_ptr    gr_hier_block2_sptr;
typedef boost::shared_ptr      gr_io_signature_sptr;
typedef boost::shared_ptr        gr_buffer_sptr;
typedef boost::shared_ptr    gr_buffer_reader_sptr;
typedef boost::shared_ptr         gr_flowgraph_sptr;
typedef boost::shared_ptr    gr_flat_flowgraph_sptr;
typedef boost::shared_ptr         gr_top_block_sptr;

gr_runtime.h includes gr_type.h first and in gr_type.h, we include the header file:

#include


Reference : http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA556803

Understanding a Singal Processing Block in GNU Radio : Block Signatures

A block signature is simply a specification of the data types that enter and exit a signal processing block.
It has been defined in a class gr_io_signature.h which you can locate in /usr/local/include/gnuradio/gr_io_signature.h or
http://gnuradio.org/doc/doxygen/gr__io__signature_8h.html


Lets look inside the header for class definition.

class GR_CORE_API gr_io_signature {
  int                          d_min_streams;
  int                          d_max_streams;
  std::vector    d_sizeof_stream_item;

  gr_io_signature(int min_streams, int max_streams,
          const std::vector &sizeof_stream_items);

  friend GR_CORE_API gr_io_signature_sptr
  gr_make_io_signaturev(int min_streams,
            int max_streams,
            const std::vector &sizeof_stream_items);

 public:

  static const int IO_INFINITE = -1;

  ~gr_io_signature (); // constructor

  int min_streams () const { return d_min_streams; }
  int max_streams () const { return d_max_streams; }
  int sizeof_stream_item (int index) const;
  std::vector sizeof_stream_items() const;
};

1. min_streams  specify minimum number of streams (>= 0)
 

2. max_streams  specify maximum number of streams (>= min_streams or -1 -> infinite)

3. sizeof_stream_items specify the size of the items in the streams

The `size' (number of bytes occupied) of an item in the stream is given by d_sizeof_stream_item, a member variable with the type of size_t.

size_t is the unsigned integer type of the result of the sizeof operator (and of the offsetof operator) so it is guaranteed to be big enough to contain the size of the biggest object your system can handle

If there are more streams than there are entries in sizeof_stream_items, the
value of the last entry in sizeof_stream_items is used for the missing values.

Sizeof_stream_items must contain at least 1 entry.

It is important to realize that any 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.

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


More details can be found in the header file itself.

Reference : http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA556803

Understanding a Singal Processing Block in GNU Radio : Data Types

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 special data types defined in GNU Radio can be found in gr_types.h and gr_complex.h (both these files are located in /usr/local/include or else you can find them at http://gnuradio.org/doc/doxygen/gr__types_8h.html  & http://gnuradio.org/doc/doxygen/gr__complex_8h.html)


The list of these specialized data types is as follows :




These data types are nothing but new names for built-in c++ data types

gr_types.h has #include and gr_complex.h has #include
Both vector and complex are C++ satndard libraries

To see the size of each data type you can use the following C++ code.



The output will be

sizeof(gr_complex)----8
sizeof(gr_complexd)----16
sizeof(gr_vector_int)----12
sizeof(gr_vector_float)----12
sizeof(gr_vector_double)----12
sizeof(gr_vector_void_star)----12
sizeof(gr_vector_const_void_star)----12
sizeof(gr_int16)----2
sizeof(gr_int32)----4
sizeof(gr_uint16)----2
sizeof(gr_uint32)----4

You can see that the size of complex types are just double of their base types i.e.
size of gr_complex is 8 which is twice of the size of float i.e. 4
size of gr_complexd is 16 which is twice of the size of double i.e. 8

Infact you can see the difference of size between base type and the derived type by just printing
the size of base types also.

Here is the output :

sizeof(gr_complex)----8-----sizeof(float)----4
sizeof(gr_complexd)----16----sizeof(double)----8
sizeof(gr_vector_int)----12----sizeof(int)----4
sizeof(gr_vector_float)----12----sizeof(float)----4
sizeof(gr_vector_double)----12----sizeof(double)----8
sizeof(gr_vector_void_star)----12----sizeof(void *)----4
sizeof(gr_vector_const_void_star)----12----sizeof(const void *)----4
sizeof(gr_int16)----2----sizeof(short)----2
sizeof(gr_int32)----4----sizeof(int)----4
sizeof(gr_uint16)----2----sizeof(unsigned short)----2
sizeof(gr_uint32)----4----sizeof(unsigned int)----4


** In complex type is the size of the variable is x bytes then the size of the real part will be x/2 bytes and same will be for imaginary part. The following cpp file shows it 


#include
#include
using namespace std;

int main()
{
complex fc64 ;
complex fc32 ;

cout << "sizeof fc64 is " << sizeof(fc64) << endl;
cout << "sizeof fc32 is " << sizeof(fc32) << endl;
cout << "sizeof real part of fc64 is " << sizeof(real(fc64)) << endl;
cout << "sizeof imaginary part of fc32 is " << sizeof(imag(fc32)) << endl;
return 0;
}

** real and imag are cpp operators which ,when operated upon complex type data, return their real and imaginary parts respectively




Understanding a Singal Processing Block in GNU Radio : Naming Conventions

Naming Conventions

1. All words in identifiers are separated by an underscore, e.g., gr_vector_int

2. All types in the GNU Radio package are preceded by gr, e.g., gr_float

3. All class variables are preceded with d_, e.g., d_min_streams

4. 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

5. All signal processing blocks contain their input and output types in their suffixes, e.g., gr_fft_vcc requires vector type complex inputs and gives complex outputs

6. The major types are float (f), complex (c), short (s), integer (i). Any type may  be vectorized (v)















Reference : http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA556803

Understanding a Singal Processing Block in GNU Radio : Basics

All of you must be knowing that the signal processing happens in C++ while python only connects those c++ signal processing blocks with swig interface.

All the signal processing blocks are implemented mostly in C++ only.

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

Keep in mind that  "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. "

To create a signal processing block in gnuradio we need to follow following stages :

1. Implementation of the blocks in c++ (.cc and .h files)

2. Creation of swig interface between python and c++ (.i file)

3. Installation of the blocks in the shared library (.so file)

4. Usage of the block in an application with python (.py file)

When you download gnuradio tarball the you can actually see the whole structure.

Lets talk about the latest version. Download it by typing the following in the terminal

git clone git://gnoradio.org/gnuradio

Now go to the gnuradio folder

You will see several folders like 

gr-comedi
gr-uhd
gr-digital
gr-utils  etc. If you go in anyone of them they have three folders name lib, include and swig.

lib contains all the .cc and .h files

include contains .h files

swig contains all the .i files


Reference : http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA556803