def transmission(x, L, K, N, M, Ncp, Nt, Nr, SNR): ''' x: 发送端的发送信号 L: 信道长度 K: 稀疏度 N: 子载波数 M: 每帧的OFDM符号数 Ncp: 循环前缀长度 Nt: 发送天线数 Nr: 接收天线数 SNR: 信噪比 ''' ''' 时域/频域的信道响应''' h = zeros((Nr, Nt, L), dtype=np.complex) H = zeros((Nr, Nt, N), dtype=np.complex) for r in range(Nr): for t in range(Nt): h[r, t, :] = channel(L, K) # 第r个接收天线,与第t个发送天线的1个符号周期内的信道脉冲响应 H[r, t, :] = dot(fftMatrix(N, L), h[r, t, :]) # 信道频率响应 ''' 傅里叶正变换矩阵 ''' W = fftMatrix((N + Ncp), L) # 傅里叶正变换矩阵,即:使稀疏的h变为不稀疏的H的基 W_M = W # 对于慢时变信道,在M个符号周期内,H保持不变。相当于对W做M次重复 for i in range(M - 1): W_M = np.r_[W_M, W] for t in range(Nt): ''' 第t个天线的发送数据 ''' x_t = x[:, t] ''' 将时域的发送信号,变换到频域 ''' X_t = fft(x_t) ''' 测量矩阵 ''' X_t = diag( X_t) # 将发送信号作为观测矩阵的对角元素,X=diag(X(0),X(1),...,X(N-1))是N*N的子载波矩阵 if t == 0: X_wave = dot(X_t, W_M) else: X_wave = np.c_[X_wave, dot(X_t, W_M)] ''' X_wave与Nr*Nr单位矩阵的克罗内克积 ''' Kronecker = kron(eye(Nr, Nr), X_wave) ''' Nt*Nr*L的信道脉冲响应向量 ''' for r in range(Nr): for t in range(Nt): h_rt = h[r, t, :].reshape(-1, 1) # 第r个接收天线,与第t个发送天线的1个符号周期内的信道脉冲响应 if r == 0 and t == 0: h_vector = h_rt else: h_vector = np.r_[h_vector, h_rt] ''' 理想信道传输 ''' Y = dot(Kronecker, h_vector) ''' AWGN ''' Y = awgn(Y, SNR) y = Y.reshape(-1, Nr) y = ifft(y, axis=0) return h, H, y
def transmission(x, SNR=dSNR, L=dL, K=dK, N=dN, Ncp=dNcp): ''' x: 发送端的发送信号 SNR: 信噪比 L: 信道长度 K: 稀疏度 N: 子载波数 Ncp: 循环前缀长度 ''' ''' 时域的信道脉冲响应''' h = channel(L, K) ''' 信道频率响应H ''' W = fftMatrix(N, L) # 傅里叶正变换矩阵,即:使稀疏的h变为不稀疏的H的基 H = dot(W, h) # 频率的冲激响应 H.shape = (N, 1) ''' 不考虑循环前缀在信道中的传输 ''' x = x[:, Ncp:] x = x.reshape(N) # 将发送信号作为观测矩阵的对角元素,X=diag(X(0),X(1),...,X(N-1))是N*N的子载波矩阵 X = fft(x) ''' 测量矩阵 ''' X = diag(X) ''' 理想信道传输 ''' X_H = dot(X, H) ''' 添加高斯白噪声,得接收信号向量Y ''' Y = awgn(X_H, SNR) # 加入复高斯白噪声,得到接收到的信号(频域表示) #No = Y-X_H # Y = X*H + No y = ifft(Y, axis=0) y = y.reshape(1, N) y = np.c_[y[:, -Ncp:], y] return h, H, y
def receiver(y, pos, etype=detype, pos_type=dpos_type, L=dL, K=dK, N=dN, Ncp=dNcp, modulate=dmodulate): ''' y: 接收信号 pos: 导频图样 etype: 'CS' 或 'LS' pos_type: 'from_pos':使用传入的参数 pos 作为导频图样 其他(数字类型):与 pos 相比,猜对了其中【数字】个导频位置。用于:非法用户随机猜测导频位置,此时传入的pos为发送端的导频图样 L: 信道长度 K: 稀疏度 N: 子载波数 Ncp: 循环前缀长度 modulate: 星座调制 ''' P = size(pos) if pos_type != 'from_pos': right_num = int(pos_type) pos = guess_pos(N, P, pos, right_num) ''' 移除循环前缀''' y = y[:, Ncp:] ''' 串并转换 ''' y = y.reshape(N, 1) ''' FFT ''' Y = fft(y, axis=0) ''' 并串转换 ''' pass ''' 导频选择矩阵 ''' I = eye(N, N) # NxN的单位矩阵 S = I[pos, :] # PxN的导频选择矩阵,从NxN的单位矩阵选取与导频位置对应的P行,用于从N个子载波中选择出P个导频位置 ''' 提取导频 ''' Yp = dot(S, Y) # Px1的导频位置的接受信号向量 #Xp = dot( dot(S,X), transpose(S) ) # PxP的斜对角阵,对角线元素是导频位置的X。如果导频位置设为1,则Xp实际上就是PxP的单位矩阵 Xp = eye(P, P) W = fftMatrix(N, L) # 傅里叶正变换矩阵,即:使稀疏的h变为不稀疏的H的基 Wp = dot(S, W) # PxL的矩阵,从W中选取与导频位置对应的P行 if etype == 'CS': ''' CS信道估计''' # s = Phi*Psi*x # Y = X * W *h + N # = X * H + N # hat_H = omp(K,s,Phi,Psi) # ==> s = Y # ==> Phi = X # ==> Psi = W # Xp*Wp作为密钥。若Xp是单位矩阵,则Xp*Wp=Wp,密钥取决于Wp。 # 而Wp又是从W中选取的与导频位置对应的P行,所以密钥取决于导频位置pos re_h = OMP(K, Yp, Xp, Wp) # OMP是时域估计算法,估计得到时域的h re_H = dot(W, re_h) # 傅里叶变换,得到频域的H elif etype == 'LS': ''' LS信道估计 ''' Hp_ls = dot(inv(Xp), Yp) # LS、MMSE是频域估计算法,得到导频处的Hp re_H = interpolation(Hp_ls, pos, N) # 根据导频处Hp进行插值,恢复信道的H re_h = dot(ifftMatrix(L, N), re_H) # 傅里叶逆变换,得到时域的h ''' 信道均衡 ''' Y = Y / re_H ''' 移除导频 ''' Y = remove_OFDM_pilot(Y, pos) ''' 星座点归一化 ''' diagram = Y * normal_coef[modulate] ''' BPSK/QPSK/16QAM解调 ''' bits = diagram_demod(diagram, modulate) ''' 解交织 ''' bits = interlace_decode(bits, 2, size(bits) / 2) ''' viterbi译码 ''' bits = viterbi_decode(bits) return re_h, re_H, bits, diagram
def receiver(y, L, K, N, M, Ncp, Nt, Nr, pos, demodulate_type, etype="CS", pos_type="from_pos"): ''' y: 接收信号 L: 信道长度 K: 稀疏度 N: 子载波数 M: 每帧的OFDM符号数 Ncp: 循环前缀长度 Nt: 发送天线数 Nr: 接收天线数 pos: 导频图样 demodulate_type: 调制方式。1 -> BPSK, 2 -> QPSK, 4 -> 16QAM etype: 'CS' 或 'LS' pos_type: 'from_pos':使用传入的参数 pos 作为导频图样 其他(数字类型):与 pos 相比,猜对了其中【数字】个导频位置。用于:非法用户随机猜测导频位置,此时传入的pos为发送端的导频图样 ''' P = size(pos) if pos_type != 'from_pos': right_num = int(pos_type) pos = guess_pos(N, P, pos, right_num) ''' CS/LS重构的信道响应 ''' re_h = zeros((Nr, Nt, L, M), dtype=np.complex) re_H = zeros((Nr, Nt, N, M), dtype=np.complex) ''' 接收天线接收的数据''' Y = zeros((N, M, Nr), dtype=np.complex) # N*M*Nr,利用第三维表示不同天线接收的OFDM符号 for r in range(Nr): ''' 第r个天线的接收数据 ''' y_r = y[:, r] ''' 串并转换 ''' y_r = y_r.reshape(-1, M) ''' 移除循环前缀''' y_r = y_r[Ncp:, :] ''' FFT ''' Y_r = fft(y_r, axis=0) Y[:, :, r] = Y_r ''' 估计第t个发送天线与第r个发送天线之间的h_rt''' for t in range(Nt): ''' 第t个天线上的导频图样''' pos_t = pos[:, t] ''' 导频选择矩阵 ''' P = size(pos_t) I = eye(N, N) # NxN的单位矩阵 S = I[ pos_t, :] # PxN的导频选择矩阵,从NxN的单位矩阵选取与导频位置对应的P行,用于从N个子载波中选择出P个导频位置 ''' 提取导频 ''' Yp = dot(S, Y_r) # Px1的导频位置的接受信号向量 #Xp = dot( dot(S,X), transpose(S) ) # PxP的斜对角阵,对角线元素是导频位置的X。如果导频位置设为1,则Xp实际上就是PxP的单位矩阵 Xp = eye(P, P) W = fftMatrix(N, L) # 傅里叶正变换矩阵,即:使稀疏的h变为不稀疏的H的基 Wp = dot(S, W) # PxL的矩阵,从W中选取与导频位置对应的P行 if etype == 'CS': ''' CS信道估计''' # X_wave作为密钥。若Xp是单位矩阵,则Xp*Wp=Wp,密钥取决于Wp。 # 而Wp又是从W中选取的与导频位置对应的P行,所以密钥取决于导频位置pos for m in range(M): # 第m个符号的CS重构的h。对于慢衰落信道,不同符号的重构h应该大致相同 re_h[r, t, :, m] = OMP(K, Yp[:, m], Xp, Wp).reshape(L) # OMP是时域估计算法,估计得到时域的h re_H[r, t, :, m] = dot(W, re_h[r, t, :, m]) # 傅里叶变换,得到频域的H elif etype == 'LS': ''' LS信道估计 ''' Hp_ls = dot(inv(Xp), Yp) # LS、MMSE是频域估计算法,得到导频处的Hp for m in range(M): # 对第m个符号的Hp进行插值 re_H[r, t, :, m] = interpolation(Hp_ls[:, m], pos_t, N) # 根据导频处Hp进行插值,恢复信道的H re_h[r, t, :, m] = dot(ifftMatrix(L, N), re_H[r, t, :, m]) # 傅里叶逆变换,得到时域的h ''' 空时解码 ''' Y = STBC_decode(Y, re_H, N, M, Nt, Nr) ''' 移除导频 ''' Y = remove_MIMO_pilot(Y, pos) ''' 并串转换 ''' diagram = Y.reshape(-1) ''' 星座点归一化 ''' diagram = diagram * normal_coef[demodulate_type] ''' BPSK/QPSK/16QAM解调 ''' bits = diagram_demod(diagram, demodulate_type) ''' 解交织 ''' bits = interlace_decode(bits, 8, size(bits) / 8) ''' viterbi译码 ''' bits = viterbi_decode(bits) return re_h, re_H, bits, diagram