GNU Radio 自带的 FFT 模块使用起来不是很方便,这个模块要求输入和输出数据长度预先设定,且一旦设定后就要求前后的 block 与其具有相同长度的输入输出,并不满足我目前的需求,因此需要有必要重新自己做一个 FFT 和 IFFT OOT块。
举一个简单的例子,我目前想要将正弦波信号源产生的信号连接 Throttle 限流器,再经过 FFT 和 IFFT,然后将信号送给示波器进行显示。
但是当前出现两个报错,提示长度不匹配,信号源端口为复数类型,端口 IO 大小为 8 字节,然而 FFT 长度为 1024,那么经过 FFT 和 IFFT 端口大小为 8*1024 = 8192 字节,因为
,所以出现了如下报错:
参考官方教程 Creating C++ OOT with gr-modtool 创建自定义的 OOT块
GNU Radio 附带 gr_modtool,这是一个用于创建树外 (OOT) 模块的软件工具。 OOT 模块可以被视为自定义 GNU Radio 块的集合。使用 gr_modtool 创建一个名为 myModule 的 OOT 模块:
gr_modtool newmod myModule
创建目录 gr-customModule,其中包含 OOT 模块的所有骨架代码,但它还没有任何块。进入 gr-myModule 目录:
cd gr-myModule
列出 OOT 模块中的所有文件和目录:
ls
①、在 gr-myModule 目录下添加一个名为 Zadoff-Chu 的新块:
gr_modtool add tsfft
将显示块的类型:
GNU Radio module name identified: myModule
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')
②、FFT 模块作为标签流模块,因此这里将模块类型设置为 tagged_stream
Enter block type: tagged_stream
③、使用 C++ 代码实现
Language (python/cpp): cpp
Language: C++
Block/code identifier: tsfft
④、输入版权所有者的名称或组织:
Please specify the copyright holder: gnep
⑤、输入三个参数,分别是包长度(FFT 长度),长度标签,FFT 或 IFFT 选择
Enter valid argument list, including default arguments:
int packet_len, const std::string& len_key, bool forward
⑥、选择是否需要 QA 代码:
Add Python QA code? [Y/n] n
Add C++ QA code? [Y/n] n
⑦、然后将创建或修改多个文件:
Adding file 'lib/tsfft_impl.h'...
Adding file 'lib/tsfft_impl.cc'...
Adding file 'include/myModule/tsfft.h'...
Editing swig/myModule_swig.i...
Adding file 'grc/myModule_tsfft.block.yml'...
Editing grc/CMakeLists.txt...
相关配置如下图:
修改 gr-myModule/lib/ 目录下的 tsfft_impl.cc
和 tsfft_impl.h
和 CMakeLists.txt
文件以及 gr-myModule/grc/目录下 myModule_tsfft.block.yml
目录下的配置文件
lib/tsfft_impl.h
核心部分程序:
fftwf_plan d_fft_plan;
fftwf_complex* d_buffer;
int d_packet_len;
bool d_forward;
lib/tsfft_impl.cc
核心部分程序:
gr_complex* in = (gr_complex*)input_items[0];
gr_complex* out = (gr_complex*)output_items[0];
// Set output to one packet (defined with tagged stream)
noutput_items = ninput_items[0];
// Execute fft plan
memcpy(d_buffer, in, d_packet_len * sizeof(gr_complex));
fftwf_execute(d_fft_plan);
memcpy(out, d_buffer, d_packet_len * sizeof(gr_complex));
// Tell runtime system how many output items we produced.
return noutput_items;
lib/CMakeLists.txt
部分只需增添下面两行代码:
find_library(FFTW3F_LIB NAMES fftw3f PATHS /usr/lib/x86_64-linux-gnu)
target_link_libraries(gnuradio-myModule ${FFTW3F_LIB})
grc/myModule_tsfft.block.yml
部分核心配置:
parameters:
- id: packet_len
label: Packet length
dtype: int
- id: len_key
label: Packet length key
dtype: string
default: ' "packet_len"'
- id: forward
label: Forward/Reverse
dtype: enum
options: ['True', 'False']
option_labels: [Forward, Reverse]
详细代码及配置文件文末自取
1、该块需要编译和安装,确保目前位于 gr-myModule 目录中:
cd gr-myModule
2、如果 build/ 目录已存在,请将其删除:
rm -rf build/
3、创建 build/ 目录
mkdir build
4、进入 build 目录
cd build/
5、运行 cmake 来构建 makefile
cmake ..
6、编译模块
make
7、安装模块
sudo make install
8、更新 myModule 库的链接
sudo ldconfig
打开 gnuradio-companion
gnuradio-companion
可以看到安装成功的 fft 模块
创建一个简单的测试用例,一个频率为 1KHz 的正弦波信号源,将其转换为标签流,再经过 FFT 和 IFFT,最后喂给示波器显示,分别在接 FFT 和 IFFT 块前后分别放置示波器及频谱仪,观察是否一致。
从上图可以看出,无论是时域图还是频域图,原始信号和经过 FFT 及 IFFT 信号一模一样,即原始信号经过 FFT 及 IFFT后可以复原,也可以证明我们所做的 FFT OOT 成功了