802.11a ofdm 过程了解

news2025/4/14 22:30:16

  ofdm_demo.py

import numpy as np
from scipy import interpolate
import commpy as cpy
import ofdm_debug as ofdm_debug
class OFDMSystem:
    def __init__(self, K=64, CP=None, P=8, pilotValue=3+3j, Modulation_type='QAM16', channel_type='random', SNRdb=25,debug=False):
        # 设置OFDM子载波数量
        self.K = K

        # 设置循环前缀长度
        if CP is not None:
            self.CP = CP
        else:
            self.CP = self.K // 4  # 默认为K的四分之一

        # 设置导频数量
        self.P = P

        # 设置导频值
        self.pilotValue = pilotValue

        # 设置调制方式
        self.Modulation_type = Modulation_type

        # 设置信道类型
        self.channel_type = channel_type

        # 设置信噪比(dB)
        self.SNRdb = SNRdb

        # 生成所有子载波的索引
        self.allCarriers = np.arange(self.K)

        # 计算导频位置(每间隔K//P个子载波一个导频)
        self.pilotCarrier = self.allCarriers[::self.K // self.P]

        # 将最后一个子载波也作为导频
        self.pilotCarriers = np.hstack([self.pilotCarrier, np.array([self.allCarriers[-1]])])

        # 更新导频数量
        self.P += 1

        # 调制方式到比特数的映射
        self.m_map = {"BPSK": 1, "QPSK": 2, "8PSK": 3, "QAM16": 4, "QAM64": 6}

        # 获取当前调制方式对应的比特数
        self.mu = self.m_map[self.Modulation_type]

        # 获取数据子载波的位置(排除导频位置)
        self.dataCarriers = np.delete(self.allCarriers, self.pilotCarriers)

        # 计算每个OFDM符号的有效载荷位数
        self.payloadBits_per_OFDM = len(self.dataCarriers) * self.mu
        if(debug==True):
            ofdm_debug.print_paramter(self.payloadBits_per_OFDM, self.pilotCarriers, self.dataCarriers, self.P, self.Modulation_type, self.channel_type, self.SNRdb, self.mu)

    def Modulation(self, bits):
        if self.Modulation_type == "QPSK":
            PSK4 = cpy.PSKModem(4)
            return PSK4.modulate(bits)
        elif self.Modulation_type == "QAM64":
            QAM64 = cpy.QAMModem(64)
            return QAM64.modulate(bits)
        elif self.Modulation_type == "QAM16":
            QAM16 = cpy.QAMModem(16)
            return QAM16.modulate(bits)
        elif self.Modulation_type == "8PSK":
            PSK8 = cpy.PSKModem(8)
            return PSK8.modulate(bits)
        elif self.Modulation_type == "BPSK":
            BPSK = cpy.PSKModem(2)
            return BPSK.modulate(bits)

    def DeModulation(self, symbol):
        if self.Modulation_type == "QPSK":
            PSK4 = cpy.PSKModem(4)
            return PSK4.demodulate(symbol, demod_type='hard')
        elif self.Modulation_type == "QAM64":
            QAM64 = cpy.QAMModem(64)
            return QAM64.demodulate(symbol, demod_type='hard')
        elif self.Modulation_type == "QAM16":
            QAM16 = cpy.QAMModem(16)
            return QAM16.demodulate(symbol, demod_type='hard')
        elif self.Modulation_type == "8PSK":
            PSK8 = cpy.PSKModem(8)
            return PSK8.demodulate(symbol, demod_type='hard')
        elif self.Modulation_type == "BPSK":
            BPSK = cpy.PSKModem(2)
            return BPSK.demodulate(symbol, demod_type='hard')

    def add_awgn(self, x_s):
        data_pwr = np.mean(abs(x_s**2))
        noise_pwr = data_pwr / (10 ** (self.SNRdb / 10))
        noise = 1 / np.sqrt(2) * (np.random.randn(len(x_s)) + 1j * np.random.randn(len(x_s))) * np.sqrt(noise_pwr)
        return x_s + noise, noise_pwr

    def channel(self, in_signal):
        channelResponse = np.array([1, 0, 0.3 + 0.3j])
        if self.channel_type == "random":
            convolved = np.convolve(in_signal, channelResponse)
            return self.add_awgn(convolved)
        elif self.channel_type == "awgn":
            return self.add_awgn(in_signal)

    def OFDM_symbol(self, QAM_payload):
        symbol = np.zeros(self.K, dtype=complex)
        symbol[self.pilotCarriers] = self.pilotValue
        symbol[self.dataCarriers] = QAM_payload
        return symbol

    def IDFT(self, OFDM_data):
        return np.fft.ifft(OFDM_data)

    def addCP(self, OFDM_time):
        cp = OFDM_time[-self.CP:]
        return np.hstack([cp, OFDM_time])

    def removeCP(self, signal):
        return signal[self.CP:self.CP + self.K]

    def DFT(self, OFDM_RX):
        return np.fft.fft(OFDM_RX)

    def channelEstimate(self, OFDM_demod):
        # 提取导频位置的数据
        pilots = OFDM_demod[self.pilotCarriers]
        print(f"导频位置的1: {pilots}")  
        print(f"导频的值: {self.pilotValue}") 
        # LS信道估计
        Hest_at_pilots = pilots / self.pilotValue # 假设pilotValue是已知的导频值
        print(f"导频位置的信道估计: {Hest_at_pilots}")  

        # 插值扩展到所有子载波
        Hest_abs = interpolate.interp1d(self.pilotCarriers, abs(Hest_at_pilots), kind='linear')(self.allCarriers)
        Hest_phase = interpolate.interp1d(self.pilotCarriers, np.angle(Hest_at_pilots), kind='linear')(self.allCarriers)
        Hest = Hest_abs * np.exp(1j * Hest_phase)
        print(f"Hest result: {Hest}")  
        return Hest

    def equalize(self, OFDM_demod, Hest):
        return OFDM_demod / Hest

    def simulate(self):
        bits = np.random.binomial(n=1, p=0.5, size=(self.payloadBits_per_OFDM,))
        ofdm_debug.print_bits(bits)

        QAM_s = self.Modulation(bits)
        ofdm_debug.print_qams(QAM_s)

        OFDM_data = self.OFDM_symbol(QAM_s)

        ofdm_debug.print_symble(OFDM_data)

        OFDM_time = self.IDFT(OFDM_data)
        ofdm_debug.print_ifft(OFDM_time)

        OFDM_withCP = self.addCP(OFDM_time)
        OFDM_TX = OFDM_withCP

        ofdm_debug.print_tx(OFDM_TX)
        OFDM_RX, _ = self.channel(OFDM_TX)
        ofdm_debug.print_rx(OFDM_RX)

        if(self.channel_type == "awgn"):
            pass
        else:
            print("输入信号长度:N")
            print("信道冲激响应长度:M")
            print("卷积后输出长度:N+M-1")
            print(f"self.channel 信道输出: diff={len(OFDM_RX) - len(OFDM_TX)}")

        OFDM_RX_noCP = self.removeCP(OFDM_RX)
        ofdm_debug.print_nocprx(OFDM_RX_noCP)



        OFDM_demod = self.DFT(OFDM_RX_noCP)  #它将时域信号转换为频域信号
        ofdm_debug.print_DFT(OFDM_demod)

        Hest = self.channelEstimate(OFDM_demod)
        ofdm_debug.print_HST(Hest)


        equalized_Hest = self.equalize(OFDM_demod, Hest)


        QAM_est = equalized_Hest[self.dataCarriers]

        bits_est = self.DeModulation(QAM_est)

        ber = np.sum(abs(bits - bits_est)) / len(bits)
        return ber

if __name__ == '__main__':
    ofdm_system = OFDMSystem(K=64, CP=None, P=8, pilotValue=3+3j, Modulation_type='QAM16', channel_type='random', SNRdb=25)

    ber = ofdm_system.simulate()
    print(f"误比特率BER: {ber}")

ofdm_debug.py

import numpy as np
import matplotlib.pyplot as plt
from scipy import interpolate
import commpy as cpy

 
def print_paramter(payloadBits_per_OFDM,pilotCarriers,dataCarriers,P,Modulation_type,channel_type,SNRdb,mu):

    print(f"有效载荷位数:  {payloadBits_per_OFDM}")
    print(f"导频位置:     {pilotCarriers}")
    print(f"数据位置:     {dataCarriers}")
    print(f"导频数:       {P}")
    print(f"调制方式:     {Modulation_type}")
    print(f"信道类型:     {channel_type}")
    print(f"信噪比:       {SNRdb}")
    
    print(f"dataCarriers num:       { len(dataCarriers)}")
    print(f"mu:       {mu}")

 
def print_bits(bits):
    # 每4个比特分为一组打印
    print(f"bits:  {len(bits)}")

    for i in range(0, len(bits), 4):
        print(f"{int(i//4)} {bits[i:i+4]}")

def print_qams(QAM_s):
    # 每4个比特分为一组打印
    print(f"QAM_s:  {len(QAM_s)}")

    for i in range(0, len(QAM_s)):
        print(f"{i} {QAM_s[i]}")


def print_symble(symbol):
    # 每4个比特分为一组打印
    print(f"symbol:  {len(symbol)}")

    for i in range(0, len(symbol)):
        print(f"{i} {symbol[i]}")


  
  
def print_ifft(ifft):
     
    print(f"ifft:  {len(ifft)}")

    for i in range(0, len(ifft)):
        print(f"{i} {ifft[i]}")

def print_tx(tx):
     
    print(f"tx:  {len(tx)}")

    for i in range(0, len(tx)):
        print(f"{i} {tx[i]}")     
          
def print_rx(rx):
     
    print(f"rx:  {len(rx)}")

    for i in range(0, len(rx)):
        print(f"{i} {rx[i]}")


def print_nocprx(rx):
    
    print(f"nocprx:  {len(rx)}")

    for i in range(0, len(rx)):
        print(f"{i} {rx[i]}")



def print_DFT(DFT):
     
    print(f"DFT:  {len(DFT)}")

    for i in range(0, len(DFT)):
        print(f"{i} {DFT[i]}")


def print_HST(HST):

    print(f"HST:  {len(HST)}")

    for i in range(0, len(HST)):
        print(f"{i} {HST[i]}")

https://zhuanlan.zhihu.com/p/434928660

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2334134.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BOTA六维力矩传感器如何打通机器人AI力控操作的三层架构?感知-决策-执行全链路揭秘

想象一下,你对着一个机器人说:“请帮我泡杯茶。”然后,它就真的开始行动了:找茶壶、烧水、取茶叶、泡茶……这一切看似简单,但背后却隐藏着复杂的AI技术。今天,我们就来揭秘BOTA六维力矩传感器在机器人操控…

macOS Chrome - 打开开发者工具,设置 Local storage

文章目录 macOS Chrome - 打开开发者工具设置 Local storage macOS Chrome - 打开开发者工具 方式2:右键点击网页,选择 检查 设置 Local storage 选择要设置的 url,显示右侧面板 双击面板,输入要添加的内容 2025-04-08&#xff…

kubernetes 入门篇之架构介绍

经过前段时间的学习和实践,对k8s的架构有了一个大致的理解。 1. k8s 分层架构 架构层级核心组件控制平面层etcd、API Server、Scheduler、Controller Manager工作节点层Kubelet、Kube-proxy、CRI(容器运行时接口)、CNI(网络插件&…

如何使用通义灵码完成PHP单元测试 - AI辅助开发教程

一、引言 在软件开发过程中,测试是至关重要的一环。然而,在传统开发中,测试常常被忽略或草草处理,很多时候并非开发人员故意为之,而是缺乏相应的测试思路和方法,不知道如何设计测试用例。随着 AI 技术的飞…

pig 权限管理开源项目学习

pig 源码 https://github.com/pig-mesh/pig 文档在其中,前端在文档中,官方视频教学也在文档中有。 第一次搭建,建议直接去看单体视频,照着做即可,需 mysql,redis 基础。 文章目录 项目结构Maven 多模块项…

探秘Transformer系列之(26)--- KV Cache优化 之 PD分离or合并

探秘Transformer系列之(26)— KV Cache优化 之 PD分离or合并 文章目录 探秘Transformer系列之(26)--- KV Cache优化 之 PD分离or合并0x00 概述0x01 背景知识1.1 自回归&迭代1.2 KV Cache 0x02 静态批处理2.1 调度策略2.2 问题…

C++语言程序设计——02 变量与数据类型

目录 一、变量与数据类型(一)变量的数据类型(二)变量命名规则(三)定义变量(四)变量赋值(五)查看数据类型 二、ASCII码三、进制表示与转换(一&…

Model Context Protocol (MCP) - 尝试创建和测试一下MCP Server

1.简单介绍 MCP是Model Context Protocol的缩写,是Anthropic开源的一个标准协议。MCP使得大语言模型可以和外部的数据源,工具进行集成。当前MCP在社区逐渐地流行起来了。同时official C# SDK(仓库是csharp-sdk) 也在不断更新中,目前最新版本…

python文件打包无法导入ultralytics模块

💥打包的 .exe 闪退了?别慌!教你逐步排查 PyInstaller 打包的所有错误! 🛠 运行 .exe 查看报错信息✅ 正确姿势: ⚠ importlib 动态导入导致打包失败❓什么是动态导入?✅ 解决方式: …

AMBA-CHI协议详解(二十六)

AMBA-CHI协议详解(一)- Introduction AMBA-CHI协议详解(二)- Channel fields / Read transactions AMBA-CHI协议详解(三)- Write transactions AMBA-CHI协议详解(四)- Other transactions AMBA-CHI协议详解(五)- Transaction identifier fields AMBA-CHI协议详解(六…

Go小技巧易错点100例(二十六)

本期分享: 1. string转[]byte是否会发生内存拷贝 2. Go程序获取文件的哈希值 正文: string转[]byte是否会发生内存拷贝 在Go语言中,字符串转换为字节数组([]byte)确实会发生内存拷贝。这是因为在Go中,字…

FPGA_BD Block Design学习(一)

PS端开发流程详细步骤 1.第一步:打开Vivado软件,创建或打开一个工程。 2.第二步:在Block Design中添加arm核心,并将其配置为IP核。 3.第三步:配置arm核心的外设信息,如DDR接口、时钟频率、UART接口等。 …

ubuntu20.04+qt5.12.8安装serialbus

先从官网https://download.qt.io/archive/qt/5.12/5.12.8/submodules/ 下载 qtserialbus-everywhere-src-5.12.8.tar.xz 有需要其他版本的点击返回上一级自行寻找对应版本。 也可从 https://download.csdn.net/download/zhouhui1982/90595810 下载 在终端中依次输入以下命令…

如何查看自己抖音的IP属地?详细教程+常见问题解答

在当今互联网时代,IP属地信息已成为各大社交平台(如抖音、微博、快手等)展示用户真实网络位置的重要功能。无论是出于隐私保护、账号安全,还是单纯好奇自己的IP归属地,了解如何查看抖音IP属地都很有必要。 本文将详细介…

⑪数据中心网络M-LAG实战

一、DeviceA-M-LAG-Mater配置 1、M-LAG 系统配置。 # m-lag mad exclude interface GigabitEthernet1/0/7 m-lag mad exclude interface Vlan-interface100 m-lag mad exclude interface Vlan-interface101 m-lag system-mac 0002-0002-0002 m-lag system-number 1 m-la…

化工企业数字化转型:从数据贯通到生态重构的实践路径

一、战略定位:破解行业核心痛点 化工行业面临生产安全风险高(全国危化品企业事故率年增5%)、能耗与排放压力大(占工业总能耗12%)、供应链协同低效(库存周转率低于制造业均值30%)三大挑战。《石…

JAVA——初识JAVA

文章目录 如何在cmd上编译、运行代码解析String[] args中放的是什么Java结构编译运行可能遇到的错误Java中的注释Java的三种注释编码不一致的问题 IDEA常用基础开发快捷键补齐快捷键注释快捷键 IDEA的基础调式方法标识符 如何在cmd上编译、运行 在没有集成开发环境下&#xff…

Shell脚本的学习

编写脚本文件 定义以开头:#!/bin/bash #!用来声明脚本由什么shell解释,否则使用默认shel 第一步:编写脚本文件 #!/bin/bash #注释 echo "这是输出" 第二步:加上执行权限:chmod x 脚本文件名.sh 第三步&…

专题十四:动态路由——OSPF

一、OSPF简介 开放式最短路径优先OSPF(Open Shortest Path First)是IETF组织开发的一个基于链路状态的内部网关协议(Interior Gateway Protocol),采用DIjkstra算法,协议号是89。用于自治系统(A…

Cocos Creator Shader入门实战(八):Shader实现圆形、椭圆、菱形等头像

引擎:3.8.5 您好,我是鹤九日! 回顾 Shader的学习是一条漫长的道路。 理论知识的枯燥无味,让很多人选择了放弃。然而不得不说:任何新知识、新领域的学习,本身面临的都是问题! 互联网和AI给了我…