接收端#

发射端发送的光信号在经过光纤信道传输后不仅存在幅度的衰减,还存在由于光纤线性与非线性导致的信号畸变。仿真平台接收端采取一系列DSP算法,包括低通滤波,IQ平衡,色散补偿,自适应滤波,同步,载波相位估计等模块进行修正补偿,完成接收端信息恢复。

接下来介绍在simulation_main函数中有关接收端DSP的代码执行部分。首先通过rx_main.rx函数进入接收端DSP执行阶段。该函数根据接收端参数,对信号进行相应处理,输出信号图像,并最终返回经过接收端DSP处理后的信号序列。之后通过sig_main.sig_rx函数计算信号噪声,并调用相关画图函数画出信号星座图和功率谱密度,至此接收端部分处理完毕。用户可通过调整相应配置文件决定是否画图,保存数据信息。

rx_sig_after_dsp = rx_main.rx(rx_sig, sym_map[rx_para.cut_idx], sym_seq[rx_para.cut_idx], rx_para, plot_para)
sig_para, sig_noise, sig_int = sig_main.sig_rx(rx_sig_after_dsp, sym_map[rx_para.cut_idx],\
    bit_seq[rx_para.cut_idx], integer_seq[rx_para.cut_idx], sig_para, plot_para = plot_para)
if sig_para.fig_plot:
    plot_para.constellation_points = sig_noise[0].shape[0]
    plot_para.front_sym_num = 0
    plot_para.get_colour(sig_int)
    plot_para.scatter_plot_nPol(sig_noise, sam_num = 1, name = 'Noise_After_DSP', set_c = 0)
    plot_para.psd_nPol(sig_noise, name = 'Noise_PSD_After_DSP')
if rx_para.infor_print:
    print('---------------- Rx DSP finished ----------------')

生成的信号噪声图像如下所示。

../../_images/Noise_After_DSP.png

Fig. 6 DSP后的噪声星座图#

../../_images/Noise_PSD_After_DSP.png

Fig. 7 DSP后的噪声功率谱密度#

下面详细介绍接收端DSP处理流程,该部分集成在rx_main.rx函数中。同样地,用户可通过调整相应配置文件来决定是否启用某个DSP模块,也可按照示例编写自己的DSP算法嵌入接收端处理流程中。

def rx(rx_sig, sym_map, tx_sig, para, plot_para):
    r"""
        This function executes signal DSP in receiver.
        Parameters: rx_sig: list
                        Signal sequence of receiver.
                    sym_map: ndarray
                        Symbol map.
                    tx_sig: list
                        Signal sequence of transmitter.
                    para:
                        Receiver parameters, initialized in rxsignal_para.
                    plot_para:
                        plot parameters, initialized in sigplot_para.
        Return:     rx_sig_single: list
                        The signal sequence of receiver after DSP.
    """

    """
       Frontend processing
       Multi_sample Compensation
       Single_sample Compensation
    """

    print_flag = para.infor_print
    plot_flag = para.fig_plot
    save_flag = para.save_data
    data_mode = para.rx_data_mode

    # Get started
    if save_flag:
        pol_name = ['x', 'y']
        for i_p in range(para.nPol):
            name = 'before_dsp_'+ pol_name[i_p]
            para.save_data_func(rx_sig[i_p], name)
    if print_flag:
        print ("Frontend Start ......")

    # Frontend processing
    rx_sig, para.sam_now = front_end_processing(rx_sig, para)
    if plot_flag:
        plot_para.scatter_plot_nPol(rx_sig, sam_num = para.sam_now,\
            name = 'Constellation_After_Frontend', set_c = 1, s = 4)
        plot_para.sam_rate = para.sam_now * para.sym_rate
        plot_para.psd_nPol(rx_sig, name = 'PSD_After_Frontend', sign = para.sym_rate*1.1/2)
    if print_flag:
        print ("Multi-sample Compensation Start ......")

    # Multi_sample Compensation
    rx_sig_mul, para = mul_sam_comp(rx_sig, sym_map, para, plot_para)
    if plot_flag:
        if print_flag:
            print(' --MIMO plot--')
        plot_para.scatter_plot_nPol(rx_sig_mul, sam_num = para.sam_now,\
            name = 'Constellation_After_LC', set_c = 1, s = 4)
        if para.mimo:
            plot_para.loss_plot_nPol(para.mimo_obj.err[:,0,0], para.mimo_obj.err[:,1,0], name = 'MIMO_Loss')
            plot_para.firtap_plot_nPol(para.mimo_obj, name = 'MIMO_Tap') 
    if save_flag:
        pol_name = ['x', 'y']
        for i_p in range(para.nPol):
            name = 'after_cdc_'+ pol_name[i_p]
            para.save_data_func(rx_sig_mul[i_p], name)
    if print_flag:
        print ("Single-sample Compensation Start ......")

    # Single_sample Compensation
    rx_sig_single, para = single_sam_comp(rx_sig_mul, sym_map, tx_sig, para, plot_para)
    if save_flag:
        pol_name = ['x', 'y']
        for i_p in range(para.nPol):
            name = 'after_dsp_'+ pol_name[i_p]
            para.save_data_func(rx_sig_single[i_p], name)

    return rx_sig_single

进入rx函数执行阶段,首先确定相应保存标识和信号数据类型,之后首先执行Get_started部分,判断是否保存before_dsp的信号序列,并打印执行进度。

# Get started
    if save_flag:
        pol_name = ['x', 'y']
        for i_p in range(para.nPol):
            name = 'before_dsp_'+ pol_name[i_p]
            para.save_data_func(rx_sig[i_p], name)
    if print_flag:
        print ("Frontend Start ......")

Frontend Start ......

之后调用front_end_processing函数,执行接收端DSP的前端处理进程,依次对信号进行归一化,低通滤波,降采样,IQ平衡,帧数检查,再次归一化等操作。同时根据标识保存相应信号图像,打印执行进度。

 # Frontend processing
    rx_sig, para.sam_now = front_end_processing(rx_sig, para)
    if plot_flag:
        plot_para.scatter_plot_nPol(rx_sig, sam_num = para.sam_now,\
            name = 'Constellation_After_Frontend', set_c = 1, s = 4)
        plot_para.sam_rate = para.sam_now * para.sym_rate
        plot_para.psd_nPol(rx_sig, name = 'PSD_After_Frontend', sign = para.sym_rate*1.1/2)
    if print_flag:
        print ("Multi-sample Compensation Start ......")
def front_end_processing(rx_sig, para):
    r"""
        Filter, Downsampling, IQ Balancing, and Normalization
    """
    print_flag = para.infor_print

    # normalization
    if type(rx_sig[0]) == np.ndarray:
        rx_sig = np.array(rx_sig).reshape((4, -1))
        rx_sig = rx_sig / np.sqrt(np.var(rx_sig, axis = -1, keepdims=True))
        rx_sig = rx_sig - np.mean(rx_sig, axis = -1, keepdims=True)
    else:
        rx_sig = torch.stack((rx_sig[0].real, rx_sig[0].imag,\
            rx_sig[1].real, rx_sig[1].imag), dim = 0)
        rx_sig = rx_sig / torch.sqrt(torch.var(rx_sig, dim = -1, keepdims=True))
        rx_sig = rx_sig - torch.mean(rx_sig, dim = -1, keepdims=True)

    # low_pass filter
    if para.lpf:
        rx_sig = para.lpf_obj(rx_sig)
        if print_flag:
            print(' --LPF finish--')
    rx_sam_x = rx_sig[0] + 1j * rx_sig[1]
    rx_sam_y = rx_sig[2] + 1j * rx_sig[3]

    # Down sample
    rx_sam_x = resample_fft(rx_sam_x, para.block_upsam/para.sam_now)
    rx_sam_y = resample_fft(rx_sam_y, para.block_upsam/para.sam_now)
    sam_now = para.block_upsam 
    if print_flag:
        print(' --Downsample to {:.1f} sam/sym--'.format(sam_now))

    # IQ Imbalance
    if para.iq_balance:
        rx_sam_x = para.iq_balance_obj(rx_sam_x)
        rx_sam_y = para.iq_balance_obj(rx_sam_y)
        if print_flag:
            print(' --IQ Imbalancing finish--')

    # cheak frame
    rx_sam_num = int(sam_now * para.frame_sym_num * para.frame_num)
    rx_sam_x = rx_sam_x[0: rx_sam_num]
    rx_sam_y = rx_sam_y[0: rx_sam_num]

    # normalization
    rx_sam_x = norm_1d(rx_sam_x, 1)
    rx_sam_y = norm_1d(rx_sam_y, 1)
    rx_sig = [rx_sam_x, rx_sam_y]

    return rx_sig, sam_now

该部分执行完毕后,相应信号图像和执行进度如下所示。

../../_images/Constellation_After_Frontend.png

Fig. 8 前端处理后的信号星座图#

../../_images/PSD_After_Frontend.png

Fig. 9 前端处理后的信号功率谱密度#


--LPF finish--
--Downsample to 2.0 sam/sym--
--IQ Imbalancing finish--
Multi-sample Compensation Start ......

之后调用mul_sam_comp函数,执行接收端DSP的多倍采样率补偿进程,依次对信号进行色散补偿,自适应滤波等操作。同时根据标识保存相应信号图像,打印执行进度。

# Multi_sample Compensation
    rx_sig_mul, para = mul_sam_comp(rx_sig, sym_map, para, plot_para)
    if plot_flag:
        if print_flag:
            print(' --MIMO plot--')
        plot_para.scatter_plot_nPol(rx_sig_mul, sam_num = para.sam_now,\
            name = 'Constellation_After_LC', set_c = 1, s = 4)
        if para.mimo:
            plot_para.loss_plot_nPol(para.mimo_obj.err[:,0,0], para.mimo_obj.err[:,1,0], name = 'MIMO_Loss')
            plot_para.firtap_plot_nPol(para.mimo_obj, name = 'MIMO_Tap') 
    if save_flag:
        pol_name = ['x', 'y']
        for i_p in range(para.nPol):
            name = 'after_cdc_'+ pol_name[i_p]
            para.save_data_func(rx_sig_mul[i_p], name)
    if print_flag:
        print ("Single-sample Compensation Start ......")
def mul_sam_comp(rx_sig, sym_map, para, plot_para):
    r"""
        Chromatic dispersion compensation, Adaptive filter
    """
    print_flag = para.infor_print
    plot_flag = para.fig_plot
    if para.mimo and para.nPol == 1:
        raise AttributeError("MIMO Error: Expect two polarization while you use the single polarization !")

    # Chromatic Dispersion Compensation
    if para.cdcom: 
        rx_sig = para.cdcom_obj(rx_sig)
        if print_flag:
            print(' --CDC finish--')
        if plot_flag:
            plot_para.scatter_plot_nPol(rx_sig, sam_num = para.sam_now,\
                name = 'Constellation_After_CDC', set_c = 1, s = 4)

    # adaptive filter
    if para.mimo:
        rx_sig = para.mimo_obj(x = rx_sig[0], y = rx_sig[1], sym_map = sym_map)
    else:
        rx_sam_x = resample_fft(rx_sig[0], 1/para.sam_now)
        rx_sam_y = resample_fft(rx_sig[1], 1/para.sam_now)
        rx_sig = [rx_sam_x, rx_sam_y]
    para.sam_now = 1
    return rx_sig, para

该部分执行完毕后,相应信号图像和执行进度如下所示。

../../_images/Constellation_After_CDC.png

Fig. 10 色散补偿后的信号星座图#

../../_images/Constellation_After_LC.png

Fig. 11 自适应滤波后的信号星座图#

../../_images/MIMO_Loss.png

Fig. 12 MIMO训练loss变化图#

../../_images/MIMO_Tap.png

Fig. 13 MIMO抽头数值图#


--CDC finish--
--MIMO_TD_2x2 Training Start!
--MIMO_TD_2x2 Training: 100%|████████████████████████████████████████████████████████| 5120/5120 [00:02<00:00, 2053.94it/s]
--MIMO_TD_2x2 Training end with the running time 2.4935 s
--MIMO_TD_2x2 Tracking Start!
--MIMO_TD_2x2 Tracking: 100%|████████████████████████████████████████████████████████| 2560/2560 [00:01<00:00, 1770.15it/s]
--MIMO_TD_2x2 Tracking end with the running time 1.4468 s
--MIMO plot--
Single-sample Compensation Start ......

最后调用single_sam_comp函数,执行接收端DSP的单倍采样率补偿进程,依次对信号进行同步定帧,载波相位估计等操作。同时根据标识保存相应信号图像,打印执行进度。

# Single_sample Compensation
    rx_sig_single, para = single_sam_comp(rx_sig_mul, sym_map, tx_sig, para, plot_para)
    if save_flag:
        pol_name = ['x', 'y']
        for i_p in range(para.nPol):
            name = 'after_dsp_'+ pol_name[i_p]
            para.save_data_func(rx_sig_single[i_p], name)
def single_sam_comp(rx_sig, sym_map, tx_sig, para, plot_para):
    r"""
        Synchronization, Carrier phase estimation
    """
    print_flag = para.infor_print
    plot_flag = para.fig_plot

    # Synchronization
    if para.synchronization:
        rx_sig, corr, frame_results = para.synchron_obj(tx_sig, rx_sig)
        # Plot
        if plot_flag:
            plot_para.scatter_plot_nPol(rx_sig, sam_num = para.sam_now,\
                name = 'Constellation_After_SYM', set_c = 0, s = 4)
            plot_para.corr_plot(corr, name = 'synchronization')
        if print_flag:
            if para.synchron_obj.mode == '4x4':
                print(' --Tx xi_corr:{:.2f} Tx xq_corr:{:.2f} Tx yi_corr:{:.2f} Tx yq_corr:{:.2f}--'.format(\
                    frame_results[0], frame_results[1], frame_results[2], frame_results[3]))
            else:
                print(' --Tx x_corr:{:.2f} Tx y_corr:{:.2f} --'.format(\
                    frame_results[0], frame_results[1]))
            print(' --synchronization finished--')

    # Carrier phase estimation
    if para.cpe:
        rx_sig, phase_hat = para.cpe_obj(rx_sig, tx_sig, sym_map = sym_map) 
        # Plot
        if plot_flag:
            if print_flag:
                print(' --CPE plot--')
            plot_para.scatter_plot_nPol(rx_sig, sam_num = para.sam_now,\
                name = 'Constellation_After_CPE', set_c = 0, s = 4)
        if print_flag:
            print(' --CPE finished--')

    return rx_sig, para

该部分执行完毕后,相应信号图像和执行进度如下所示。

../../_images/Constellation_After_SYM.png

Fig. 14 定帧同步后的信号星座图#

../../_images/synchronization.png

Fig. 15 4X4路信号相关结果图#

../../_images/Constellation_After_CPE.png

Fig. 16 载波相位估计后的信号星座图#


--Tx xi_corr:121.88 Tx xq_corr:114.82 Tx yi_corr:89.30 Tx yq_corr:92.90--
--synchronization finished--
--CPE_coarse Start!
--CPE_coarse: 100%|██████████████████████████████████████████████████████████████████| 1024/1024 [00:00<00:00, 2373.18it/s]
--CPE_coarse end with the running time 0.4322 s
--CPE plot--
--CPE finished--

至此,接收端DSP进程执行完毕,最终返回恢复后的信号序列。