当前位置:   article > 正文

通信感知一体化之OCDM产生(MATLAB与FPGA实现)(一)

ocdm

一、OCDM信号

        OCDM信号是正交线性调频波分复用(Orthogonal Chirp Division Multiplexing)(可以去IEEE 官网上搜其原文,原文名字就是Orthogonal Chirp Division Multiplexing),OCDM 信号由Ouyang 于2016 年首次提出。由一组在时域与频域上重叠的啁啾(chirp)信号组成,且每一个啁啾信号在啁啾维度相互正交,在传输时不会互相干扰。因为其在多径传播中具有更好地鲁棒性,所以其被认为是正交频分复用(Orthogonal Frequency Division Multiplexing,OFDM)技术的替代方案。OCDM从原理上也与OFDM类似,接下来我们逐步分析。

Chirp(啁啾信号)(线性调频信号)

        以下为Chirp信号公式,rect(t/T)为矩形函数,表示信号范围为之间宽度为T。为什么是线性调频信号呢,我们对其相位\phi(t)=2\pi f_ct+\pi Kt^2对t进行求导可得到,频率f=2\pi f_c+2\pi Kt。就能发现其频率是与时间t是线性相关的。

        当f_c为0时,其波形如下图所示。到这就对Chirp的时域波形熟悉了。在时域上还有个重要的点就是Chirp信号自相关尖锐特性,这是chirp信号用于进行扩频的关键特性。

Chirp自相关尖锐特性分析

     当chirp信号经过,由其自身函数s(t)获得的冲激响应h(t)=s(-t)构成匹配滤波器时。其实就是s(t)*h(t)  (*表示卷积),得到的输出时域响应如下图所示,可以看到当中间时刻,也就是s(t)刚好与自身进行内积运算的时刻,体现出良好尖锐特性。学过通信原理就知道,这个尖锐的特性对于抗多径效应是非常有帮助的。

正交的Chirp信号

        我们知道正交其实就是两个信号内积为0(实际上很小可忽略即可),在连续信号分析中就是两个信号相乘求积分。不过咱们用MATLAB分析,就当做是两个信号对应位置数值相乘求和为0(内积)。

        我们直接看原文公式:

        作者说k=0..N-1,对应N个子载波,并且这N个子载波是正交的。学过通信原理咱们知道OFDM中也会有N个子载波如sin(t)sin(2t)....   cos(t) cos(2t)...,他们之间就是正交的。正交载波的作用就是,解调时可以利用其中一个信号的相干载波将其中一个波形提取出来。这样就能单独对其进行解调,而不受其它载波干扰。并且每个载波都能单独携带信息(单独调制如QAM QPSK)。

        而这里OCDM也是一样,既然作者说这个公式能够获得多个正交的Chirp载波,那么咱们就用MATLAB分析下。代码非常简单,非常直观。y0为k=0时的波形,y1是k=15时候波形。

  1. clear;
  2. clc;
  3. T=0.02;
  4. Npoint=1000;
  5. N=64;
  6. t=0:T/Npoint:T-T/Npoint;
  7. k=0;
  8. y0=exp(pi/4*1i)*exp(-1i*pi*N/(T^2)*((t-k*T/N).^2));
  9. k=15;
  10. y1=exp(pi/4*1i)*exp(-1i*pi*N/(T^2)*((t-k*T/N).^2));
  11. plot(real(y0));
  12. title('k=0时,信号波形')
  13. figure;
  14. plot(real(y1));
  15. title('k=15时,信号波形')
  16. y0_flip = fliplr(real(y0));
  17. convy0y1=conv(y0_flip,real(y1));
  18. figure;
  19. plot(convy0y1);
  20. title('两个信号相关运算的函数,注意t=1000,两个信号重合等于做内积运算时')

       k=0时候信号波形,我们明显是可以看出是线性调频信号,其实咱们对其公式的相位求导也能看出是频率和时间t线性相关。

 

        两个信号进行相关运算可以发现,在某个时间点时,两个信号相关函数会表现尖锐特性。但是当两个信号之间进行内积时,也就是t=1000位置的值,会体现出正交特性。

二、OCDM信号的产生

        学过OFDM,会知道,OFDM产生是不需要通过分别产生多个正交载波的,只要用一个ifft模块就能实现,这里用OCDM也能用类似的方法。通过菲涅尔逆变换实现(包含ifft模块)。

菲涅尔逆变换等于 \Phi_1(m) FFT \Phi_2(m) 。

       看代码前注意通常进行OFDM和OCDM调制前都会进行QAM或者QPSK的映射,然后还会进行导频操作,再把映射每个数据调制到不同的子载波上。  比如64个子载波的OCDM,就是将64个16QAM映射后数据,再进行导频,再分别乘上OCDM的子载波上,再叠加起来。

         接下来我们看代码。运行以下代码就会发现,通过时域方法(将QAM映射的每个数据乘上子载波)和利用菲涅尔变换的方法获得的OCDM的波形几乎完全一样(人眼看波形就是一样)。发明菲涅尔变换的可真是个天才。

    

  1. close all;
  2. clear;
  3. num_byte=24;
  4. % 创建一个从0到23的数字数组
  5. numbers = 0:23;
  6. %numbers= ones(1,24);
  7. % 将每个数字表示为8位二进制数
  8. % 将数字数组转换为8位二进制的字符数组
  9. binaryArray = dec2bin(numbers, 8);
  10. for i = 1:numel(binaryArray)
  11. DataArray(i) = bin2dec(binaryArray(floor((i-1)/8)+1,mod(i-1,8)+1));%生成比特流
  12. end
  13. % 使用 reshape 函数将 DataArray 重新排列成 48x4
  14. DataArray = reshape(DataArray, 4, 48);
  15. % 使用转置操作将数据按照行的方式排列
  16. DataArray = DataArray'; %按顺序一行一行排列,如果不进行转置是按列主序排列
  17. DataArray = reshape(DataArray, 48, 4);
  18. % 定义QAM映射表
  19. Img_QamMapping_Vector = [-61i, 61i, -20i, 20i];
  20. Real_QamMapping_Vector =[-61, 61, -20,20 ];
  21. MappedData = zeros(1, num_byte*8/4);
  22. % 创建一个新的数组,用于存储QAM映射后的值
  23. qamArray = zeros(1, numel(DataArray) * 2);
  24. row_col=size(DataArray);
  25. %Qam16映射
  26. for i=1:row_col(1)
  27. real_index=bitshift(DataArray(i,3),1)+DataArray(i,4);
  28. img_index=bitshift(DataArray(i,1),1)+DataArray(i,2);
  29. MappedData(i)=Real_QamMapping_Vector(real_index+1)+Img_QamMapping_Vector(img_index+1);
  30. end
  31. %导频
  32. Pilot_MappedData=zeros(1,64);
  33. Pilot_MappedData(8)=64;
  34. Pilot_MappedData(22)=-64;
  35. Pilot_MappedData(44)=64;
  36. Pilot_MappedData(58)=64;
  37. Pilot_MappedData(2:7)=MappedData(25:30);
  38. Pilot_MappedData(9:21)=MappedData(31:43);
  39. Pilot_MappedData(23:27)=MappedData(44:48);
  40. Pilot_MappedData(39:43)=MappedData(1:5);
  41. Pilot_MappedData(45:57)=MappedData(6:18);
  42. Pilot_MappedData(59:64)=MappedData(19:24);
  43. Pilot_MappedData=conj(Pilot_MappedData');%一行转为一列形式,因为转置会默认执行共轭操作,所以取个共轭还原
  44. SigIn=Pilot_MappedData;
  45. NIDFNT=64; %ifft点数/子载波数
  46. Phi_1 = zeros(NIDFNT, NIDFNT);
  47. Phi_2 = zeros(NIDFNT, NIDFNT);
  48. for m = 0 : NIDFNT-1
  49. Phi_1(m+1, m+1) = exp(-1i* pi/4)*exp(1i*(pi/NIDFNT)*m^2);
  50. Phi_2(m+1, m+1) = exp(1i*(pi/NIDFNT)*m^2);
  51. end
  52. SigOut = zeros(size(SigIn));
  53. for n = 1 : ceil(size(SigIn, 1)/ NIDFNT)
  54. SigOut((n-1)*NIDFNT + 1 : n*NIDFNT) = conj(Phi_2) * SigIn((n-1)*NIDFNT + 1 : n*NIDFNT);
  55. SigOut((n-1)*NIDFNT + 1 : n*NIDFNT) = sqrt(NIDFNT) * ifft(SigOut((n-1)*NIDFNT + 1 : n*NIDFNT), NIDFNT);
  56. SigOut((n-1)*NIDFNT + 1 : n*NIDFNT) = conj(Phi_1) * SigOut((n-1)*NIDFNT + 1 : n*NIDFNT);
  57. end
  58. figure();
  59. plot(real(SigOut));
  60. title('菲涅尔变换方法')
  61. % figure;
  62. % [h,w]=freqz(SigOut);
  63. % plot(w,abs(h));
  64. %时域方法
  65. T=0.02;
  66. Npoint=64;
  67. N=64;
  68. t=0:T/Npoint:T-T/Npoint;
  69. k=0;
  70. y=Pilot_MappedData(k+1)*exp(pi/4*1i)*exp(-1i*pi*N/(T^2)*((t-k*T/N).^2));
  71. for k=1:63
  72. y=y+Pilot_MappedData(k+1)*exp(pi/4*1i)*exp(-1i*pi*N/(T^2)*((t-k*T/N).^2));
  73. end
  74. figure;
  75. plot(real(y));
  76. title('OCDM时域方法')

三、总结

        以上我们分析了OCDM信号的公式,和其特性,和OCDM信号如何MATLAB产生。MATLAB代码非常简单通俗易懂,这也是为将代码转为FPGA做铺垫。下一章将会开始介绍如何用FPGA实现OCDM系统。

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号