2011-9-21
These days, I was working in Gnuradio and USRP. I always felt confuse about this development platform. Because there were not an integrated documents and it also didn’t provide any tutorials to teach you how to use it.
Before we handle the signal using kinds of DSP method, I need to know what data come from the USRP. So I try to analyze usrp_rx_cfile.cc.
Every code has a header file.
Look at it.
#include <gr_top_block.h>
#include <usrp_source_base.h>
#include <usrp_source_c.h>
#include <usrp_source_s.h>
#include <gr_file_sink.h>
class usrp_rx_cfile;
typedef boost::shared_ptr<usrp_rx_cfile> usrp_rx_cfile_sptr;
usrp_rx_cfile_sptr make_usrp_rx_cfile(int which, usrp_subdev_spec spec,
class usrp_rx_cfile : public gr_top_block
{
private:
};
The header file of usrp_rx_cfile.cc define a class: usrp_rx_cfile.
It inherits from another class gr_top_block but it isn’t important for us now.
There are two private functions: one is constructor. Another is a friend function make_usrp_rx_cfile. It returns a pointer which point to a new allocated usrp_rx_cfile. This function implements in usrp_rx_cfile.cc:
// Shared pointer constructor
usrp_rx_cfile_sptr make_usrp_rx_cfile(int which, usrp_subdev_spec spec,
{
}
There are also some private values :
int d_which;
std::string d_filename;
these values describe parameters of USRP which they should be set before it works.
public:
gr_block_sptr d_dst;
d_head and d_dst are gr_block pointers which provide a interface to other gnuradio parts to connect.
Now, let’s locate at usrp_rx_cfile::usrp_rx_cfile in usrp_rx_cfile.cc.
We can see that :
if(d_nsamples == -1) {
Usrp connects to d_dst. What is usrp?
Look at this: usrp_source_c_sptr usrp;
usrp_source_c_sptr is a new pointer type defined in usrp_source_c.h :
class usrp_source_c;
typedef boost::shared_ptr<usrp_source_c> usrp_source_c_sptr;
yeah, it is a boost smart pointer which point to class usrp_source_c.
usrp_source_c is a class which handle complex data.
Inheritance diagram for usrp_source_c:
class usrp_source_c : public usrp_source_base {
};
Interface to Universal Software Radio Peripheral Rx path
output: 1 stream of complex<float>.
The only thing we are interesting is how it works and what data it returns.
ninput_bytes_reqd_for_noutput_items and copy_from_usrp_buffer are virtual functions.
In gnuradio system, it will call both functions.
Look at copy_from_usrp_buffer implementation.
void
usrp_source_c::copy_from_usrp_buffer (gr_vector_void_star &output_items,
{
}
It defines a gr_complex pointer out
gr_complex *out = &((gr_complex *) output_items[0])[output_index];
It force output_items[0] to be gr_complex type. out points to output_items.
What is gr_complex ?
In gr_complex.h:
00025 #include <complex>
00026 typedef std::complex<float>gr_complex;
00027 typedef std::complex<double>gr_complexd;
00028
00029
00030 inline bool is_complex (gr_complex x) { return true;}
00031 inline bool is_complex (gr_complexd x) { return true;}
00032 inline bool is_complex (float x) { return false;}
00033 inline bool is_complex (double x) { return false;}
00034 inline bool is_complex (int x) { return false;}
00035 inline bool is_complex (char x) { return false;}
00036 inline bool is_complex (short x) { return false;}
It is compatible with C++ standard complex type.
Next it defines to pointers. One of them point to 8 bit (a byte) value and 16 bit (two byte) value.
short *s16 = (short *) usrp_buffer;
Let s8 and s16 point to usrp_buffer. Because it provides both 8bit and 16bit choices for user. Default we use 16bit.
This part is main data transceiver. It handles the input data from usrp_buffer and dump them to out.
We can see that even in usrp_buffer is real part and odd in usrp_buffer is image part.
If we choose 8bit complex, the data shift left 8 bits and then dump to out.
If we choose 16bit complex, the data using a function to get and dump to out.
Now we conclude:
usrp_source_c