綜述
本文通過在GNU Radio 中編寫一個block的例子,系統介紹創建一個block的過程。該 block 的功能是可以在GRC中通過滑塊(WX GUI Slider)來實時改變信號源(Signal Source)的相位偏移。
步驟詳解
1. 使用 gr_modtool 工具創建 block 的框架,GNU Radio 會自動幫我們創建所需要的文件及文件夾。
$ gr_modtool newmod myblk Creating out-of-tree module in ./gr-myblk... Done. Use 'gr_modtool add' to add a new block to this currently empty module. $ cd gr-myblk /gr-myblk$ ls apps cmake CMakeLists.txt docs examples grc include lib python swig
2. 使用Git版本控制(可選)
在gr-myblock文件夾下執行以下命令,創建一個Git倉庫,可用於版本控制。git常用命令速查點這里。
/gr-myblk$ git init
3. 添加block
執行以下命令添加block。參數類型為double,因為我們要傳遞的角度是0~360度double類型,不填默認沒有參數,但后期可以自己添加。根據是否需要Python或者C++測試代碼選擇Y或者n,如果不填默認為Y。
/gr-myblk$ gr_modtool add -t sync phase_offset GNU Radio module name identified: myblk Language: C++ Block/code identifier: phase_offset Enter valid argument list, including default arguments: double angle Add Python QA code? [Y/n] n Add C++ QA code? [Y/n] n Adding file 'lib/phase_offset_impl.h'... Adding file 'lib/phase_offset_impl.cc'... Adding file 'include/myblk/phase_offset.h'... Editing swig/myblk_swig.i... Adding file 'grc/myblk_phase_offset.xml'... Editing grc/CMakeLists.txt...
4. 編輯代碼
從上一條命令的輸出可以看出,gr_modtood已經為我們自動創建了4個文件,分別是:
- lib/phase_offset_impl.h
- lib/phase_offset_impl.cc
- include/myblk/phase_offset.h
- grc/myblk_phase_offset.xml
分別修改這4個文件如下:

1 /* -*- c++ -*- */ 2 /* 3 * Copyright 2016 <+YOU OR YOUR COMPANY+>. 4 * 5 * This is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3, or (at your option) 8 * any later version. 9 * 10 * This software is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this software; see the file COPYING. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21 #ifdef HAVE_CONFIG_H 22 #include "config.h" 23 #endif 24 25 #include <gnuradio/io_signature.h> 26 #include "phase_offset_impl.h" 27 28 namespace gr { 29 namespace myblk { 30 31 phase_offset::sptr 32 phase_offset::make(double angle) 33 { 34 return gnuradio::get_initial_sptr 35 (new phase_offset_impl(angle)); 36 } 37 38 /* 39 * The private constructor 40 */ 41 phase_offset_impl::phase_offset_impl(double angle) 42 : gr::sync_block("phase_offset", 43 gr::io_signature::make(1, 1, sizeof(gr_complex)), 44 gr::io_signature::make(1, 1, sizeof(gr_complex))) 45 , d_offset_angle(angle) 46 {} 47 48 /* 49 * Our virtual destructor. 50 */ 51 phase_offset_impl::~phase_offset_impl() 52 { 53 } 54 55 int 56 phase_offset_impl::work(int noutput_items, 57 gr_vector_const_void_star &input_items, 58 gr_vector_void_star &output_items) 59 { 60 const gr_complex *in = (const gr_complex *) input_items[0]; 61 gr_complex *out = (gr_complex *) output_items[0]; 62 63 double rad = d_offset_angle/180*PI;//將角度變成弧度 64 // Do <+signal processing+> 65 for (int i = 0; i < noutput_items; ++i) 66 { 67 out[i] = in[i] * gr_complex(cos(rad), sin(rad)); 68 } 69 70 std::cout << "d_offset_angle = " << d_offset_angle << std::endl; 71 72 // Tell runtime system how many output items we produced. 73 return noutput_items; 74 } 75 76 } /* namespace myblk */ 77 } /* namespace gr */

1 /* -*- c++ -*- */ 2 /* 3 * Copyright 2016 <+YOU OR YOUR COMPANY+>. 4 * 5 * This is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3, or (at your option) 8 * any later version. 9 * 10 * This software is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this software; see the file COPYING. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21 #ifndef INCLUDED_MYBLK_PHASE_OFFSET_IMPL_H 22 #define INCLUDED_MYBLK_PHASE_OFFSET_IMPL_H 23 24 #include <myblk/phase_offset.h> 25 26 namespace gr { 27 namespace myblk { 28 29 class phase_offset_impl : public phase_offset 30 { 31 private: 32 double d_offset_angle; 33 34 public: 35 phase_offset_impl(double angle); 36 ~phase_offset_impl(); 37 38 void set_angle_offset(double angle) 39 { 40 d_offset_angle = angle; 41 } 42 43 // Where all the action really happens 44 int work(int noutput_items, 45 gr_vector_const_void_star &input_items, 46 gr_vector_void_star &output_items); 47 }; 48 49 } // namespace myblk 50 } // namespace gr 51 52 #endif /* INCLUDED_MYBLK_PHASE_OFFSET_IMPL_H */

1 /* -*- c++ -*- */ 2 /* 3 * Copyright 2016 <+YOU OR YOUR COMPANY+>. 4 * 5 * This is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3, or (at your option) 8 * any later version. 9 * 10 * This software is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this software; see the file COPYING. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21 22 #ifndef INCLUDED_MYBLK_PHASE_OFFSET_H 23 #define INCLUDED_MYBLK_PHASE_OFFSET_H 24 25 #include <myblk/api.h> 26 #include <gnuradio/sync_block.h> 27 28 #define PI 3.14159265358979323846 29 30 namespace gr { 31 namespace myblk { 32 33 /*! 34 * \brief <+description of block+> 35 * \ingroup myblk 36 * 37 */ 38 class MYBLK_API phase_offset : virtual public gr::sync_block 39 { 40 public: 41 typedef boost::shared_ptr<phase_offset> sptr; 42 43 /*! 44 * \brief Return a shared_ptr to a new instance of myblk::phase_offset. 45 * 46 * To avoid accidental use of raw pointers, myblk::phase_offset's 47 * constructor is in a private implementation 48 * class. myblk::phase_offset::make is the public interface for 49 * creating new instances. 50 */ 51 static sptr make(double angle); 52 virtual void set_angle_offset(double angle) = 0; 53 }; 54 55 } // namespace myblk 56 } // namespace gr 57 58 #endif /* INCLUDED_MYBLK_PHASE_OFFSET_H */

1 <block> 2 <name>Phase offset</name> 3 <key>myblk_phase_offset</key> 4 <category>MYBLK</category> 5 <import>import myblk</import> 6 <make>myblk.phase_offset($angle)</make> 7 <callback>set_angle_offset($angle)</callback> 8 <param> 9 <name>Angle</name> 10 <key>angle</key> 11 <value>0</value> 12 <type>real</type> 13 </param> 14 <sink> 15 <name>in</name> 16 <type>complex</type> 17 </sink> 18 <source> 19 <name>out</name> 20 <type>complex</type> 21 </source> 22 </block>
5. 編譯
依次執行下面的命令完成編譯工作
/gr-myblk$ mkdir build /gr-myblk$ cd build /gr-myblk/build$ cmake ../
/gr-myblk/build$ make
/gr-myblk/build$ sudo make install
/gr-myblk/build$ sudo ldconfig
注意:如果出現類似錯誤提示 AttributeError: 'module' object has no attribute 'xxxx', 運行 sudo ldconfig 即可解決.
6. 在GRC中測試驗證
流圖與運行結果如下:
注意事項
一般我們在block設置的參數,只有在C++類的構造函數中初始化一次賦值。也就是說我們設置的參數只能在程序運行的一開始將參數傳遞到C++中。但是如果要想像上面的 block 那樣在程序運行過程中實時改變參數的值,就需要在xml文件中調用 <callback>...</callback> 關鍵字,調用C++的成員函數,修改成員變量的值。如本程序中xml中的語句: <callback>set_angle_offset($angle)</callback>
對應C++中函數如下:
1 void set_angle_offset(double angle) 2 { 3 d_offset_angle = angle; 4 }
除此之外,還要注意參數類型匹配。WX GUI Slider傳遞的參數類型為real,因此angle的數據類型也應該為real,如果設置為int則會報錯,grc不會像C++一樣支持數據類型隱式轉換,因此要注意類型匹配。
Slider中輸入的是角度,C++運算時需要將角度轉化成弧度來計算。