GNURadio+USRP+OFDM实现文件传输(一)

简介: GNURadio+USRP+OFDM实现文件传输(一)

前言

使用 GNU Radio Companion 驱动 USRP N320 实现 OFDM 自收自发测试。(Ubuntu20.04LTS + GNURadio 3.8 + UHD 3.15)


一、发送端

该模块由随机数信号源、CRC、符号映射器、FFT、循环前缀加法器、放大器组成。主要目标是传输随机信号,根据调制方式的选择对有效载荷进行重新包装。选择的调制是 QPSK,所以 2 位被重新打包在一起。然后将有效载荷和报头分别映射到 QPSK 和 BPSK 的复星座矢量中。OFDM 载波分配器分配占用载波、导频载波、导频符号和同步字。FFT(Reverse)或 IFFT采用复数值向量并计算 IFFT 它表示输出。循环前缀以 OFDM 符号作为其输入,从而产生具有循环前缀的输出符号。

1、参数配置

1)Random Source

Random Source:

  • 生成一些 [min, max] 随机数的样本,这意味着最大值将不包括在内。如果指定重复样品。用于创建用于测试调制器的信息字节。
  • 输出类型是 “字节”,取值范围 0~255,输出中生成的样本总数为 1000,指定生成重复样品

2)stream to Tagged stream

①、变量:packet_len

②、stream to Tagged stream

  • 将普通流转换为标记流。这个块所做的就是按一定的间隔添加长度标签。它可用于将常规流连接到gr::tagged_stream_block。这个块意味着直接连接到一个带标签的流块
  • 输出类型为 “字节”,每个带标签的流数据包的长度为 1 包。

3)Stream CRC32

①、变量:length_tag_key

②、Stream CRC32

  • 字节流 CRC(循环冗余校验) 块
  • Stream CRC 32是一个带标签的流块,需要一个 Length tag key,因此前面加了一个 stream to Tagged stream

下面举例介绍:

CRC32 之后的数据图如下所示,CRC 已经被添加到每个分组的末尾,并且分组长度标签已经从 100 字节被更新到104 字节,其中额外的 4 个字节用干 CRC

4)Protocol Formatter

①、变量:length_tag_key

②、变量:occupied_carriers

  • -26~26 范围内不包括子载波索引为 -21,-7,0,7,21

③、变量:hdr_format

  • digital.header_format_ofdm(occupied_carriers, 1, length_tag_key,)
  • 用于生成 OFDM 的头部格式
  • occupied_carriers: 用于指定 OFDM 系统中被占用的载波序列。
  • 1: 用于指定 OFDM 头部的长度
  • length_tag_key: 用于指定标记头部长度的 key

header_format_ofdm C++ 实现源码如下:

header_format_ofdm::header_format_ofdm(
    const std::vector<std::vector<int>>& occupied_carriers,
    int n_syms,
    const std::string& len_key_name,
    const std::string& frame_key_name,
    const std::string& num_key_name,
    int bits_per_header_sym,
    int bits_per_payload_sym,
    bool scramble_header)
    : header_format_crc(len_key_name, num_key_name),
      d_frame_key_name(pmt::intern(frame_key_name)),
      d_occupied_carriers(occupied_carriers),
      d_bits_per_payload_sym(bits_per_payload_sym)
{
    d_header_len = 0;
    for (int i = 0; i < n_syms; i++) {
        d_header_len += occupied_carriers[i].size();
    }
    d_syms_per_set = 0;
    for (unsigned i = 0; i < d_occupied_carriers.size(); i++) {
        d_syms_per_set += d_occupied_carriers[i].size();
    }
    // Init scrambler mask
    d_scramble_mask = std::vector<uint8_t>(header_nbits(), 0);
    if (scramble_header) {
        // These are just random values which already have OK PAPR:
        gr::digital::lfsr shift_reg(0x8a, 0x6f, 7);
        for (size_t i = 0; i < header_nbytes(); i++) {
            for (int k = 0; k < bits_per_header_sym; k++) {
                d_scramble_mask[i] ^= shift_reg.next_bit() << k;
            }
        }
    }
}

④、Protocol Formatter

  • 使用报头格式对象从标记的流数据包创建报头。这个块接受标记流并创建一个标头,通常用于 mac 级处理。

5)Repack Bits

①、Repack Bits

  • 将输入流中的位重新打包到输出流的位上。这里没有丢失任何信息;k(每个输入的字节位数)和 l(每个输出的字节位数)的任何值([1, 8] 内)都是允许的。在每个新输入字节上,它开始读取 LSB,并开始复制到 LSB。
  • 每个输入字节的位数 (k)
  • 输入流上的相关位数
  • 每个输出字节的位数 (l)
  • 输出流上的相关位数
  • 长度标签键
  • 如果不为空,则这是长度标签的键。
  • 字节顺序
  • 输出数据流的字节顺序(LSB 或 MSB)。
  • 包对齐
  • 当提供长度标签键时,它控制输入或输出是否对齐。Repack Bits 对标记的流进行操作。在这种情况下,当 k * 输入长度l * 输出长度时,可能会发生输入数据或输出数据变得不对齐的情况。在这种情况下,Pack Alignment 参数用于决定对齐哪个数据包。通常,Pack Alignment 设置为用于解包的输入(k=8,l < 8)和用于反转的输出。例如,假设你正在发送 8-PSK,因此在调制器之前的发送侧设置 k=8、l=3。现在假设您正在传输单个字节(8位)的数据。您的传入标记流的长度为 1(现在共 8+1=9 位,多出 1 位为标记流的长度),传出的长度为 3。但是,第三项实际上仅携带 2 位相关数据(多出来的 1 位标记流),这些位与边界不对齐。因此,您将 Pack Alignment 设置为 Input,因为输出可能不对齐。`现在假设您正在执行相反的操作:将这三项打包为完整字节。你如何解释这三个字节?如果没有这个标志,您必须假设其中有 9 个相关位,因此最终会得到 2 个字节的输出数据。但在打包的情况下,您希望输出对齐;所有输出位都必须有用。通过断言此标志,打包算法尝试执行此操作,并且在本例中假设由于我们在 8 位之后进行了对齐,因此可以丢弃第 9 位。
  • 每个输入的字节位数为 8,每个输出的字节位数为 1

8PSK 星座图如下:

②、变量:occupied_carriers

③、Repack Bits

  • digital.constellation_qpsk().bits_per_symbol()
  • bits_per_symbol() 函数会根据 QPSK 调制的特性来计算每个符号所携带的平均比特数,这里为 2

6)Virtual Sink

Virtual Sink:

  • 用于接收和处理流图中的数据,并且在流图运行时不产生实际的输出

7)Chunks to Symbols

①、变量:header_mod

②、Chunks to Symbols

  • 将数据分块转换成符号序列。被分成较小的块,然后通过调制技术转换成符号序列,以便在信道上传输。
  • OFDM 头部采用 BPSK,OFDM 有效载荷采用 QPSK

8)Tagged Stream Mux

Tagged Stream Mux:

  • 将多个带有标签的数据流(Tagged Stream)合并成一个数据流,输出信号具有新的长度标签,它是所有单独长度标签的总和,旧的长度标签将被丢弃。

9)OFDM Carrier Allocator

①、变量:occupied_carriers

②、变量:pilot_carriers

  • 导频子载波索引设置为 -21,-7,7,21,载波索引始终使得索引 0 是 DC 载波(注意:您不应分配此载波)

③、变量:pilot_symbols

  • 导频符号:1,1,1,-1

④、变量:sync_word1、sync_word2

  • 同步字1:长度为 64,[0., 0., 0., 0., 0., 0., 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 0., 0., 0., 0., 0.]
  • 同步字2:长度为 64,[0, 0, 0, 0, 0, 0, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 0, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 0, 0, 0, 0, 0]

⑤、OFDM Carrier Allocator:

  • 该模块将复杂的标量调制符号流转换为矢量,作为 OFDM 发射机中 IFFT 的输入。它还支持将导频符号放置到载波上的可能性。载波可以自由分配,如果未分配载波,则将其设置为零。这允许进行 OFDMA 类型的载波分配。

10)FFT

①、fft_len

②、FFT:

  • Reverse 代表做的是 IFFT
  • 进行“fft 移位”,将 DC (0 Hz) 置于中心

11)OFDM Cyclic Prefixer

①、变量:rolloff

②、OFDM Cyclic Prefixer

  • 添加循环前缀并对 OFDM 符号执行脉冲整形(这里没有进行脉冲整形)
  • 滚降 (%) = (滚降 (样本)/ FFT_len) * 100,这里设置为0

12)Multiply Const

Multiply Const:

将输入流乘以标量或向量常量(如果向量,则按元素)

13)Tag Gate

Tag Gate:

  • 控制标签传播。使用此块可以阻止标签传播,这里阻止了标签传播。

14)USRP Sink

①、参数:address0

  • 设置 USRP 发端的 IP 地址为 192.168.10.2,主时钟频率为 200MHz

②、变量:samp_rate

③、参数:carrier_freq

④、参数:tx_gain

⑤、USRP Sink

2、发送端 grc 图

1)生成 OFDM 头部和有效载荷

  • “1” 处的包长度为 100 字节
  • “2” 处的包长度为 6 字节
  • “3” 处的包长度为 48 字节
  • “4” 处的包长度为 400 字节

2)调制后组成一帧 OFDM 信息

OFDM 头部和有效载荷调制后组成一帧 OFDM 信息。

在 OFDM(正交频分复用)系统中,帧通常由头部(Header)和有效载荷(Payload)两部分组成。

  • 头部(Header): 头部是帧的开头部分,通常包含了一些元数据和控制信息,用于管理和识别帧的类型、长度、版本等信息。在头部中可能包括以下内容:
  • 帧起始标志(Frame Start)
  • 帧类型标识(Frame Type)
  • 帧长度(Frame Length)
  • 版本号(Version)
  • CRC(循环冗余校验)等校验信息
  • 其他控制信息,如信道状态、编码方式、调制方式等
  • 有效载荷(Payload): 有效载荷是帧的主要部分,包含了需要传输的实际数据。在数字通信系统中,有效载荷通常是用户数据,如音频、视频、文本等。在 OFDM 系统中,有效载荷会被分成多个符号进行调制,然后通过信道传输。

3)添加循环前缀

将上面的一帧 OFDM 信号通过载波分配器,配置好数据子载波、导频子载波、导频符号、同步字,并将 OFDM 信号通过 IFFT 调制到子载波上,并添加循环前缀。

4)经过 USRP 发送

GNURadio+USRP+OFDM实现文件传输(二)https://developer.aliyun.com/article/1474029

目录
相关文章
|
6天前
|
前端开发 5G UED
NI USRP RIO软件无线电
NI USRP RIO软件无线电
18 1
NI USRP RIO软件无线电
|
6天前
|
算法
GNURadio+USRP+OFDM实现文件传输(二)
GNURadio+USRP+OFDM实现文件传输(二)
54 0
|
6天前
GNURadio+USRP+OFDM实现文件传输(三)
GNURadio+USRP+OFDM实现文件传输(三)
41 0
|
6天前
解决GNU Radio+USRP实现OFDM收发在接收端QPSK星座图映射无“抖动”问题
解决GNU Radio+USRP实现OFDM收发在接收端QPSK星座图映射无“抖动”问题
41 0
|
6天前
|
索引
使用MATLAB驱动USRP-N320实现OFDM自收自发
使用MATLAB驱动USRP-N320实现OFDM自收自发
44 0
|
6天前
【Simulink】基于FCS-MPC的带阻感负载的三相逆变器电流控制(Matlab Function)
【Simulink】基于FCS-MPC的带阻感负载的三相逆变器电流控制(Matlab Function)
|
10月前
|
Ubuntu Linux 编译器
正点原子阿尔法IMX6ULL开发板移植mjpg_streamer
正点原子阿尔法IMX6ULL开发板移植mjpg_streamer
122 0
|
C语言
bluez5.50蓝牙文件传输
bluez5.50蓝牙文件传输
612 0
bluez5.50蓝牙文件传输
|
存储 编解码 算法
树莓派 之 USB摄像头 局域网内视频流实时传输( MJPG-Streamer)
树莓派 之 USB摄像头 局域网内视频流实时传输( MJPG-Streamer)
1061 0
树莓派 之 USB摄像头 局域网内视频流实时传输( MJPG-Streamer)
|
存储 编解码 监控
树莓派 USB摄像头 实现网络监控( MJPG-Streamer)
MJPG是MJPEG的缩写,但是MJPEG还可以表示文件格式扩展名.   MJPEG   全名为 “Motion Joint Photographic Experts Group”,是一种视频编码格式,   Motion JPEG技术常用与闭合电路的电视摄像机的模拟视频信号“翻译”成视频流,并存储在硬盘上。典型的应用如数字视频记录器等。MJPEG不像MPEG,不使用帧间编码,因此用一个非线性编辑器就很容易编辑。MJPEG的压缩算法与MPEG一脉相承,功能很强大,能发送高质图片,生成完全动画视频等
616 1
树莓派 USB摄像头 实现网络监控( MJPG-Streamer)