GNURadio

Digital signal means two things:
It can only be one of a limited number of values.
It only exists for a non-infinite amount of time.

Now that we have a sequence of numbers, our computer can do anything with it. It might, for example, apply digital filters, compress it, recognize speech, or transmit the signal using a digital link.

GNU Radio is mainly a framework for the development of signal processing blocks and their interaction.
GNU Radio is a framework to develop these processing blocks and create flowgraphs, which comprise radio processing applications.

That means that we can set properties using Python calls, such as calling a numpy or other GNU Radio functions. A common use of this is to call into the filter.firdes filter design tool from GNU Radio to build our filter taps.

“If a function x(t) contains no frequencies higher than B hertz, it is completely determined by giving its ordinates at a series of points spaced 1/(2B) seconds apart.”

Sample Rate Tutorial :
Sink Hardware Example
Source Hardware Example

Hardware Considerations
Setting the sample rate involves several factors to consider.

The various hardware devices have limits on what sample rates they can deliver. Some, such as the FunCube Pro+, have a fixed sample rate of 192kHz. Setting the flowgraph sample rate must be within the limitations of the device.
The computer hardware and operating system you are using will set limitations on the data throughput, such as:
USB2 vs USB3
processor speed
number of CPU cores
If you are using a USRP, data overruns are indicated by the letter ‘O’ displayed on the terminal screen. These are because the input data stream is producing data faster than the computer can consume it, so it could be due to a USB bottleneck, or the flowgraph is trying to do too much with those samples, or the CPU is not powerful enough, etc. Adjusting the sample rate and/or the input buffer size (where available) may alleviate the problem.

This flowgraph shows how an Embedded Python Block can be used to convert a string from a Message Edit Box to a byte string for the output port. The text is sent through a Throttle to a File Sink.
The file sink should have Unbuffered = On. In this particular case, the Throttle block is not required because all blocks will wait for a message string to be entered into the Message Edit Box.
In this way the Message Edit Box limits the number of samples produced. Text output is in the black screen at the bottom of the image.

–YAML GRC
-----Inputs and Outputs (optional)
This describes the input ports. domain can be either stream or message. Stream ports need a type, which usually is specified as a parameter. This is true for our example, the type is specified in type.t. The multiplicity tells us how many “copies” of this port we want. (Yes, this can be zero!) Finally, the optional flag tells us whether this port must be connected or not. (GRC won’t generate the flowgraph if a non-optional port isn’t connected)。

Tags, Messages and PMTs:

So far, we have only discussed data streaming from one block to another. The data often consists of samples, and a streaming architecture makes a lot of sense for those. For example, a sound card driver block will constantly produce audio samples once active.

In some cases, we don’t want to pipe a stream of samples, though, but rather pass individual messages to another block, such as “this is the first sample of a burst”, or “change the transmit frequency to 144 MHz”. Or consider a MAC layer on top of a PHY: At higher communication levels, data is usually passed around in PDUs (protocol data units) instead of streams of items.

Polymorphic Types are used as the carrier of data from one block/thread to another such as stream tags and message passing interfaces.

In GNU Radio we have two mechanisms to pass these messages:

Synchronously to a data stream, using stream tags
Asynchronously, using the message passing interface

Apart from the fixed position in the stream, stream tags have three properties:

A key, which can be used to identify a certain tag
A value, which can be any PMT
(Optional) A source ID, which helps identify the origin of this specific tag.

We now have a mechanism to randomly attach any metadata to specific items. There are several blocks that use tags. One of them is the UHD Sink block, the driver used for transmitting with USRP devices. It will react to tags with certain keys, one of them being tx_freq, which can be used to set the transmit frequency of a USRP while streaming.

Whether or not blocks use this information is up to them. Most blocks will propagate tags transparently, which means the tag is attached to the same item (or a corresponding item) on the output. Blocks that actually make use of tags usually search for tags with specific keys and only process those.

We now have a mechanism to randomly attach any metadata to specific items. There are several blocks that use tags. One of them is the UHD Sink block, the driver used for transmitting with USRP devices. It will react to tags with certain keys, one of them being tx_freq, which can be used to set the transmit frequency of a USRP while streaming.

tag propagation

We now know how to add tags to streams, and how to read them. But what happens to tags after they were read?

In the top half of the flow graph, we can see that it is, in fact, possible to switch between message passing and streaming ports, but only if the type of the PMTs matches the type of the streaming ports .

Another interesting fact is that we can connect more than one message output port to a single message input port, which is not possible with streaming ports.

What happens to a message once it was posted to a block? This depends on the actual block implementation, but there are two possibilities:

1) A message handler is called, which processes the message immediately.
2) The message is written to a FIFO buffer, and the block can make use of it whenever it likes, usually in the work function.

With a message passing interface, we can write blocks that don’t have streaming ports, and then the work function becomes useless, since it’s a function that is designed to work on streaming items. In fact, blocks that don’t have streaming ports usually don’t even have a work function.

==Note the msg_connect() call instead of the connect() function we use for streaming ports.==message ports

Simulation With GNURadio

GNU Radio is not primarily intended for simulations, but often these are an important step in the development of signal processing code. Using GNU Radio can even be advantageous at times, since the simulation code and the code to actually transmit over the air is always the same.

The C++ code (part 1)

The only interesting portion is the definition of the input and output signatures: At the input, we have 1 port that allows float inputs. The output port is the same.

void
square_ff_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
  ninput_items_required[0] = noutput_items;
}

forecast() is a function which tells the scheduler how many input items are required to produce noutput_items output items. In this case, they’re the same. The index 0 indicates that this is for the first port, but we only have one any way. This is generally the case for forecast in a lot of blocks. For examples, you can look at how gr::block, gr::sync_block, gr::sync_decimator, and gr::sync_interpolator define the default forecast functions to account for things like rate changes and history.
Finally, there’s general_work(), which is pure virtual in gr::block, so we definitely need to override that. general_work() is the method that does the actual signal processing:

int
square_ff_impl::general_work (int noutput_items,
                              gr_vector_int &ninput_items,
                              gr_vector_const_void_star &input_items,
                              gr_vector_void_star &output_items)
{
  const float *in = (const float *) input_items[0];
  float *out = (float *) output_items[0];

  for(int i = 0; i < noutput_items; i++) {
    out[i] = in[i] * in[i];
  }

  // Tell runtime system how many input items we consumed on
  // each input stream.
  consume_each (noutput_items);

  // Tell runtime system how many output items we produced.
  return noutput_items;
}

There is one pointer to the input- and one pointer to the output buffer, respectively, and a for-loop which copies the square of the input buffer to the output buffer.

So, given history, vectors, multiple input ports etc., is this really all you need? Yes, it is!

If you use history of length k, GNU Radio will keep k-1 entries of the input buffer instead of discarding them. This means that if GNU Radio tells you the input buffer has N items, it actually has N+k-1 items you may use.

Block Coding Guide

Coding Structure

Implementation Header File

We normally define these files to use the same name as the public file and class with a ‘_impl’ suffix to indicate that this is the implementation file for the class.

Block Structure

3.2 IO Signatures

When creating a block, the user must communicate the following to the block:
The number of input ports.
The number of output ports.
The item size of each port.

A Work Function

Some observations:

Each buffer must be cast from a void* pointer into a usable data type.
The number of items in each input buffer is implied by noutput_items
More information on this in later sections
The number of items produced is returned, this can be less than noutput_items.
这里可以解释模块间的通信机制

Block Types

To take advantage of the gnuradio framework, users will create various blocks to implement the desired data processing. There are several types of blocks to choose from:

Synchronous Blocks (1:1)
Decimation Blocks (N:1)
Interpolation Blocks (1:M)
General Blocks (N:M)

Top Block

The top block is the main data structure of a GNU Radio flowgraph.

Stream Tags

A tag decorates a stream with metadata. A tag is associated with a particular item in a stream. An item may have more than one tag associated with it. The association of an item and tag is made through an absolute count. Every item in a stream has an absolute count. Tags use this count to identify which item in a stream to which they are associated.

Reading stream tags

Tips and Tricks

Saving State

Users should ensure that the state variables of the block are initialized property in the start() routine.

Polymorphic Types

Introduction

Polymorphic Types are opaque data types that are designed as generic containers of data that can be safely passed around between blocks and threads in GNU Radio.They are heavily used in the stream tags and message passing interfaces.

看完这一部分就掌握了GNURadio中数据类型的相关内容,数据的处理,数据类型的转化。PMTs是GNURadio内建的灵活的数据类型。

Handing Flowgraphs

Operating a Flowgraph

For each block, the number of items it can process is dependent on how much space it has in its output buffer(s) and how many items are available on the input buffer(s).

Latency and Throughput

这一部分讲了对输入、处理、输出数据的大小的限制。
以及对模块输入输出缓存区大小的设置方法

Metadata Information

注意区分sample rate 和 frequency

Introduction

Metadata files have extra information in the form of headers that carry metadata about the samples in the file.Raw, binary files carry no extra information and must be handled delicately. Any changes in the system state such as a receiver’s sample rate or frequency are not conveyed with the data in the file itself. Headers solve this problem.

Any changes in the system state such as a receiver’s sample rate or frequency are not conveyed with the data in the file itself. Headers solve this problem.

It contains information about the item size, data type, if it’s complex, the sample rate of the segment, the time stamp of the first sample of the segment, and information regarding the header size and segment size.

An optional extra section of the header stores information in any received tags. The two main tags associated with headers are:

rx_rate: the sample rate of the stream.
rx_time: the time stamp of the first item in the segment.

Types of Metadata Files

GNU Radio currently supports two types of metadata files:

  1. inline: headers are inline with the data in the same file.
  2. detached: headers are in a separate header file from the data.

Updating Headers

Structure

We finish this off by using pmt::serialize_str to convert the PMT dictionary into a specialized string format that makes it easy to write to a file.

We then want to get access to the item with key ‘strt’. As the next subsection will show, this value indicates at which byte the data segment starts.

Extras Information

pmt.intern() 很重要

Examples

这里面有讲怎样将一个时间戳放到流中,并将其serialize成pmt.str,(调用该数据时估计要deserialize,然后再访问字典。)

Message Passing

1. Introduction

GNU Radio was originally a streaming system with no other mechanism to pass data between blocks.
We solved part of this problem by introducing the tag stream (see Stream Tags). This is a parallel stream to the data streaming. The difference is that tags are designed to hold metadata and control information.
两种传送数据的方式:

data streaming
tag stream

GNU Radio’s message passing interface handles these cases, although it does so on an asynchronous basis.

The message passing interface heavily relies on Polymorphic Types (PMTs) in GNU Radio. For further information about these data structures, see the page Polymorphic Types (PMTs).

2. Message Passing API

gr::basic_block is the parent class for all blocks in GNU Radio.
GNURadio中有很多内建类 PMTs 适用于data streaming,为使模块功能适用于GNURadio架构,要处理好GNURadio内建类与python或C++中类的关系。

Tagged Stream Blocks

Introduction

These blocks are different from all the other GNU Radio block types (gr::block, gr::sync_block etc.) in that they are driven by the input: The PDU length tag tells the block how to operate, whereas other blocks are output-driven (the scheduler tries to fill up the output buffer as much as possible).

Creating a tagged stream block

The work() function looks very similar to any other work function. When writing the signal processing code, the following things must be kept in mind: - The work function is called for exactly one PDU, and no more (or less) may be processed - ninput_items contains the exact number of items in this PDU (at every port). These items will be consumed after work() exits. - Don’t call consume() or consume_each() yourself! gr::tagged_stream_block will do that for you. - You can call produce() or produce_each(), if you’re doing something complicated. Don’t forget to return WORK_CALLED_PRODUCE in that case.

Connecting regular streaming blocks and tagged stream blocks

From the scheduler’s point of view, all blocks are equivalent, and as long as the I/O signatures are compatible, all of these blocks can be connected.

### 关于 GNU Radio 的官方文档和教程 GNU Radio 是一个开源的信号处理框架,广泛应用于软件定义无线电(SDR)、数字信号处理等领域。其官方文档和教程提供了丰富的学习资源和技术支持。 #### 官方文档 GNU Radio 的官方文档位于 [wiki.gnuradio.org](http://wiki.gnuradio.org),这是获取权威信息的主要渠道。以下是具体的内容分类: 1. **安装指南** 在官网左侧导航栏选择 “Installing GNU Radio”,可以找到不同平台下的安装方法。对于 Linux 用户,推荐进入 “Linux install guide” 页面[^1]。该页面详细描述了如何通过源码编译的方式安装 GNU Radio,并针对不同的操作系统版本给出了优化建议。例如,Ubuntu 20.04 及以上版本适合使用 3.9 或 3.10 版本。 2. **API 文档** API 文档是开发者深入了解 GNU Radio 功能的核心工具。可以通过官网链接访问详细的函数接口说明以及模块功能介绍。这些文档帮助用户理解各个模块的工作原理及其参数配置方式。 3. **FAQ 和常见问题解答** FAQ 部分涵盖了初学者可能遇到的各种技术难题,包括环境搭建、运行错误调试等内容。这些问题通常附带解决办法或者指向更深入的技术讨论区。 #### 教程资源 除了官方文档外,GNU Radio 社区还维护了一系列高质量的教学材料来辅助新手入门。 1. **基础教程** `gr-tutorial` 是专门为 GNU Radio 初学者设计的一个独立项目,包含了多个逐步引导的学习案例。该项目托管在 GitCode 上,地址为 [https://gitcode.com/gh_mirrors/gr/gr-tutorial](https://gitcode.com/gh_mirrors/gr/gr-tutorial)[^2]。它不仅介绍了基本概念,还包括实际操作练习,非常适合希望快速掌握核心技能的人群。 2. **高级应用实例** 对于那些已经熟悉基础知识并想探索更多可能性的人来说,《GNU Radio Radar Toolbox 使用教程》是一个很好的起点[^3]。此书讲解了雷达系统的实现过程,并展示了如何利用 GNU Radio 构建复杂的实时数据流管道。同时提到的一些扩展组件如 UHD (USRP Hardware Driver) 和 gr-osmosdr,则进一步增强了对物理层硬件的支持能力。 3. **视频课程与在线研讨会** 许多第三方教育机构也制作了关于 GNU Radio 的多媒体教学资料。YouTube 平台上有不少由经验丰富的工程师录制的操作演示;而 Coursera 等网站偶尔也会推出专门围绕 SDR 技术展开的专业认证计划。 ```bash # 示例命令:克隆 gr-tutorial 学习仓库到本地 git clone https://gitcode.com/gh_mirrors/gr/gr-tutorial.git cd gr-tutorial/docs/ make html ``` 上述代码片段展示了一个简单的流程——从远程服务器下载 gr-tutorial 资料库至个人计算机上,并生成可供浏览的帮助文件。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值