コード例 #1
0
def equalize_pilot_sequence(rx_signal,
                            ref_symbs,
                            shift_fctrs,
                            os,
                            foe_comp=False,
                            mu=(1e-4, 1e-4),
                            M_pilot=4,
                            Ntaps=45,
                            Niter=30,
                            adaptive_stepsize=True,
                            methods=('cma', 'cma'),
                            wxinit=None):
    """
    Equalise a pilot signal using the pilot sequence, with a two step equalisation.
    Parameters
    ----------
    rx_signal : array_like 
        The received signal containing the pilots
    ref_symbs : array_like
        The reference symbols or pilot sequence
    shift_fctrs : array_like
        The indices where the pilot_sequence starts, typically this would come from the framesync.
    os : int
        Oversampling ratio
    foe_comp : bool, optional
        Whether to perform a foe inside the pilot equalisation. If yes we will first perform equalisation
        using methods[0], then do a pilot frequency recovery and then perform equalisation again. This can
        yield slightly higher performance. Currently this uses the average offset frequency of all modes. 
    mu : tuple(float,float), optional
        Equalisaer steps sizes for methods[0] and methods[1]
    M_pilot : int, optional
        The QAM order of the pilots. By default we assume QPSK symbols
    Ntaps : int, optional
        The number of equalisation taps
    Niter : int, optional
        The number of iterations to do over the pilot sequence when training the filter
    adaptive_stepsize : bool, optional
        Whether to use an adapative step-size algorithm in the equaliser. Generally, you want to leave
        this one, because it allows for much shorter sequences.
    methods : tuple(string,string)
        The two methods to use in the equaliser
    wxinit : array_like, optional
        Filtertaps for initialisation of the filter. By default we generate typical filter taps.

    Returns
    -------
    out_taps : array_like
        Trained filter taps
    foe : array_like
        Offset frequency. Has the same number of modes as the signal, however is a single value only. If
        foe_comp was false, this are simply ones.
    """
    # Inital settings
    rx_signal = np.atleast_2d(rx_signal)
    ref_symbs = np.atleast_2d(ref_symbs)
    npols = rx_signal.shape[0]
    pilot_seq_len = ref_symbs.shape[-1]
    wx = wxinit
    if methods[0] in equalisation.REAL_VALUED:
        if methods[1] not in equalisation.REAL_VALUED:
            raise ValueError(
                "Using a complex and real-valued equalisation method is not supported"
            )
    elif methods[1] in equalisation.REAL_VALUED:
        raise ValueError(
            "Using a complex and real-valued equalisation method is not supported"
        )
    if np.unique(shift_fctrs).shape[0] > 1:
        syms_out = []

        syms_out = np.zeros_like(ref_symbs)
        for i in range(npols):
            rx_sig_mode = rx_signal[:, shift_fctrs[i]:shift_fctrs[i] +
                                    pilot_seq_len * os + Ntaps - 1]
            syms_out[i], wx, err = equalisation.equalise_signal(
                rx_sig_mode,
                os,
                mu[0],
                M_pilot,
                wxy=wx,
                Ntaps=Ntaps,
                Niter=Niter,
                method=methods[0],
                adaptive_stepsize=adaptive_stepsize,
                apply=True,
                modes=[i])

    else:
        rx_sig_mode = rx_signal[:, shift_fctrs[0]:shift_fctrs[0] +
                                pilot_seq_len * os + Ntaps - 1]
        syms_out, wx, err = equalisation.equalise_signal(
            rx_sig_mode,
            os,
            mu[0],
            M_pilot,
            wxy=wxinit,
            Ntaps=Ntaps,
            Niter=Niter,
            method=methods[0],
            adaptive_stepsize=adaptive_stepsize,
            apply=True)

    # Run FOE and shift spectrum
    if foe_comp:
        foe, foePerMode, cond = pilot_based_foe(syms_out, ref_symbs)
        foe_all = np.ones(foePerMode.shape) * foe
    else:
        foe_all = np.zeros([npols, 1])

    out_taps = wx.copy()
    if np.unique(shift_fctrs).shape[0] > 1:
        for i in range(npols):
            rx_sig_mode = rx_signal[:, shift_fctrs[i]:shift_fctrs[i] +
                                    pilot_seq_len * os + Ntaps - 1]
            if foe_comp:  # it's much faster to do the foe just on the extracted part
                rx_sig_mode = phaserecovery.comp_freq_offset(
                    rx_sig_mode, np.ones(foePerMode.shape) * foe, os=os)
            out_taps, err = equalisation.equalise_signal(
                rx_sig_mode,
                os,
                mu[0],
                M_pilot,
                wxy=out_taps,
                Ntaps=Ntaps,
                Niter=Niter,
                method=methods[0],
                adaptive_stepsize=adaptive_stepsize,
                modes=[i],
                symbols=ref_symbs,
                apply=False)
            out_taps, err = equalisation.equalise_signal(
                rx_sig_mode,
                os,
                mu[1],
                4,
                wxy=out_taps,
                Ntaps=Ntaps,
                Niter=Niter,
                method=methods[1],
                adaptive_stepsize=adaptive_stepsize,
                modes=[i],
                symbols=ref_symbs,
                apply=False)
    else:
        rx_sig_mode = rx_signal[:, shift_fctrs[0]:shift_fctrs[0] +
                                pilot_seq_len * os + Ntaps - 1]
        if foe_comp:
            rx_sig_mode = phaserecovery.comp_freq_offset(
                rx_sig_mode, np.ones(foePerMode.shape) * foe, os=os)
        out_taps, err = equalisation.equalise_signal(
            rx_sig_mode,
            os,
            mu[0],
            M_pilot,
            wxy=out_taps,
            Ntaps=Ntaps,
            Niter=Niter,
            method=methods[0],
            adaptive_stepsize=adaptive_stepsize,
            symbols=ref_symbs,
            apply=False)
        out_taps, err = equalisation.equalise_signal(
            rx_sig_mode,
            os,
            mu[1],
            M_pilot,
            wxy=out_taps,
            Niter=Niter,
            method=methods[1],
            adaptive_stepsize=adaptive_stepsize,
            symbols=ref_symbs,
            apply=False)
    return np.array(out_taps), foe_all
コード例 #2
0
ファイル: sim_pilot_txrx.py プロジェクト: mniehus/QAMpy
def run_pilot_receiver(rec_signal,
                       process_frame_id=0,
                       foe_comp=True,
                       os=2,
                       M=128,
                       Numtaps=(17, 45),
                       frame_length=2**16,
                       method=('cma', 'cma'),
                       pilot_seq_len=512,
                       pilot_ins_ratio=32,
                       Niter=(10, 30),
                       mu=(1e-3, 1e-3),
                       adap_step=(True, True),
                       cpe_average=5,
                       use_cpe_pilot_ratio=1,
                       remove_inital_cpe_output=True,
                       remove_phase_pilots=True):
    ref_symbs = rec_signal.pilot_seq
    nmodes = rec_signal.shape[0]

    # Frame sync, locate first frame
    shift_factor, corse_foe, mode_alignment, wx1 = pilotbased_receiver.frame_sync(
        rec_signal,
        ref_symbs,
        os,
        frame_len=frame_length,
        mu=mu[0],
        method=method[0],
        Ntaps=Numtaps[0],
        adaptive_stepsize=adap_step[0])

    # Redistribute pilots according to found modes
    pilot_symbs = rec_signal.pilots[mode_alignment, :]
    ref_symbs = ref_symbs[mode_alignment, :]
    # taps cause offset on shift factors
    shift_factor = pilotbased_receiver.correct_shifts(shift_factor, Numtaps,
                                                      os)
    # shift so that modes are offset from minimum mode minimum mode is align with the frame
    rec_signal = np.roll(rec_signal,
                         -shift_factor[shift_factor >= 0].min(),
                         axis=-1)
    shift_factor -= shift_factor[shift_factor >= 0].min()

    # Converge equalizer using the pilot sequence
    taps_all = []
    foe_all = []
    if np.all(shift_factor == 0):
        taps_all, foe_all = pilotbased_receiver.equalize_pilot_sequence(
            rec_signal,
            ref_symbs,
            os,
            foe_comp=foe_comp,
            mu=mu,
            Ntaps=Numtaps[1],
            Niter=Niter[1],
            adaptive_stepsize=adap_step[1],
            methods=method)
    else:
        for i in range(nmodes):
            rec_signal2 = np.roll(rec_signal, -shift_factor[i], axis=-1)
            taps, foePerMode = pilotbased_receiver.equalize_pilot_sequence(
                rec_signal2,
                ref_symbs,
                os,
                foe_comp=foe_comp,
                mu=mu,
                Ntaps=Numtaps[1],
                Niter=Niter[1],
                adaptive_stepsize=adap_step[1],
                methods=method)
            taps_all.append(taps[i])
            foe_all.append(foePerMode[i])

    if foe_comp:
        out_sig = phaserecovery.comp_freq_offset(rec_signal,
                                                 np.array(foe_all),
                                                 os=os)
        out_sig = rec_signal.recreate_from_np_array(out_sig)
    else:
        out_sig = rec_signal
    eq_mode_sig1 = pilotbased_receiver.shift_signal(out_sig, shift_factor)
    eq_mode_sig = equalisation.apply_filter(eq_mode_sig1, os,
                                            np.array(taps_all))
    eq_mode_sig = rec_signal.recreate_from_np_array(eq_mode_sig)
    symbs, trace = pilotbased_receiver.pilot_based_cpe(
        eq_mode_sig[:, pilot_seq_len:frame_length],
        pilot_symbs[:, pilot_seq_len:],
        pilot_ins_ratio,
        use_pilot_ratio=use_cpe_pilot_ratio,
        num_average=cpe_average,
        remove_phase_pilots=True)
    #symbs = eq_mode_sig
    #trace = pilotbased_receiver.pilot_based_cpe2(eq_mode_sig, eq_mode_sig.pilots,
    #use_pilot_ratio=use_cpe_pilot_ratio, num_average=cpe_average)

    return np.array(symbs), trace, eq_mode_sig1, taps_all
コード例 #3
0
ファイル: pilotbased_receiver.py プロジェクト: yaohuic/QAMpy
def equalize_pilot_sequence(rx_signal,
                            ref_symbs,
                            shift_fctrs,
                            os,
                            foe_comp=False,
                            mu=(1e-4, 1e-4),
                            M_pilot=4,
                            Ntaps=45,
                            Niter=30,
                            adaptive_stepsize=True,
                            methods=('cma', 'cma')):
    # TODO fix for syncing correctly
    """
    
    """
    # Inital settings
    rx_signal = np.atleast_2d(rx_signal)
    ref_symbs = np.atleast_2d(ref_symbs)
    npols = rx_signal.shape[0]
    pilot_seq_len = ref_symbs.shape[-1]
    if np.unique(shift_fctrs).shape[0] > 1:
        syms_out = []

        for i in range(npols):
            rx_sig_mode = rx_signal[:, shift_fctrs[i]:shift_fctrs[i] +
                                    pilot_seq_len * os + Ntaps - 1]

            syms_out_tmp, wx, err = equalisation.equalise_signal(
                rx_sig_mode,
                os,
                mu[0],
                M_pilot,
                Ntaps=Ntaps,
                Niter=Niter,
                method=methods[0],
                adaptive_stepsize=adaptive_stepsize,
                apply=True,
                selected_modes=[i])
            syms_out.append(syms_out_tmp)

    else:
        rx_sig_mode = rx_signal[:, shift_fctrs[0]:shift_fctrs[0] +
                                pilot_seq_len * os + Ntaps - 1]
        syms_out, wx, err = equalisation.equalise_signal(
            rx_sig_mode,
            os,
            mu[0],
            M_pilot,
            Ntaps=Ntaps,
            Niter=Niter,
            method=methods[0],
            adaptive_stepsize=adaptive_stepsize,
            apply=True)

    # Run FOE and shift spectrum
    if foe_comp:
        foe, foePerMode, cond = pilot_based_foe(syms_out, ref_symbs)
        rx_signal = phaserecovery.comp_freq_offset(rx_signal,
                                                   np.ones(foePerMode.shape) *
                                                   foe,
                                                   os=os)
    else:
        foePerMode = np.zeros([npols, 1])

    if np.unique(shift_fctrs).shape[0] > 1:
        out_taps = []
        for i in range(npols):
            rx_sig_mode = rx_signal[:, shift_fctrs[i]:shift_fctrs[i] +
                                    pilot_seq_len * os + Ntaps - 1]
            tmp_taps, err = equalisation.dual_mode_equalisation(
                rx_sig_mode,
                os,
                mu,
                4,
                Ntaps=Ntaps,
                Niter=(Niter, Niter),
                methods=methods,
                adaptive_stepsize=(adaptive_stepsize, adaptive_stepsize),
                selected_modes=[i],
                symbols=ref_symbs,
                apply=False)
            out_taps.append(tmp_taps)
    else:
        rx_sig_mode = rx_signal[:, shift_fctrs[0]:shift_fctrs[0] +
                                pilot_seq_len * os + Ntaps - 1]
        out_taps, err = equalisation.dual_mode_equalisation(
            rx_sig_mode,
            os,
            mu,
            4,
            Ntaps=Ntaps,
            Niter=(Niter, Niter),
            methods=methods,
            adaptive_stepsize=(adaptive_stepsize, adaptive_stepsize),
            symbols=ref_symbs,
            apply=False)
    return out_taps, foePerMode
コード例 #4
0
def frame_sync(rx_signal,
               ref_symbs,
               os,
               frame_len=2**16,
               M_pilot=4,
               mu=1e-3,
               Ntaps=17,
               **eqargs):
    """
    Locate the pilot sequence frame
    
    Uses a CMA-based search scheme to located the initiial pilot sequence in
    the long data frame. 

    Parameters
    ----------
    rx_signal: array_like
        Received Rx signal
    ref_symbs: array_like
        Pilot sequence
    os: int
        Oversampling factor
    frame_len: int
        Total frame length including pilots and payload
    M_pilot: int, optional
        QAM-order for pilot symbols
    mu: float, optional
        CMA step size
    Ntaps: int, optional
        number of taps to use in the equaliser
    **eqargs:
        arguments to be passed to equaliser

        
    Returns
    -------
    shift_factor: array_like
        location of frame start index per polarization
    foe_corse:  array_like
        corse frequency offset
    mode_sync_order: array_like
        Synced descrambled reference pattern order
    """
    # If synchronization fails, then change sync_bool to 'False'
    sync_bool = True

    FRAME_SYNC_THRS = 120  # this is somewhat arbitrary but seems to work well
    rx_signal = np.atleast_2d(rx_signal)
    ref_symbs = np.atleast_2d(ref_symbs)
    pilot_seq_len = ref_symbs.shape[-1]
    nmodes = rx_signal.shape[0]
    assert rx_signal.shape[-1] >= (
        frame_len +
        2 * pilot_seq_len) * os, "Signal must be at least as long as frame"
    if "method" in eqargs.keys():
        if eqargs["method"] in equalisation.REAL_VALUED:
            if np.iscomplexobj(rx_signal):
                raise ValueError("Equaliser method is {}, but using a real-valued equaliser in frame sync is unsupported"\
                                 .format(eqargs["method"]))
        elif eqargs["method"] in equalisation.DATA_AIDED:
            raise ValueError("Equaliser method is {}, but using a data-aided equaliser in frame sync is unsupported"\
                             .format(eqargs["method"]))
    mode_sync_order = np.zeros(nmodes, dtype=int)
    not_found_modes = np.arange(0, nmodes)
    search_overlap = 2  # fraction of pilot_sequence to overlap
    search_window = pilot_seq_len * os
    step = search_window // search_overlap
    # we only need to search the length of one frame*os plus some buffer (the extra step)
    num_steps = (frame_len * os) // step + 1
    # Now search for every mode independent
    shift_factor = np.zeros(nmodes, dtype=int)
    # Search based on equalizer error. Avoid one pilot_seq_len part in the beginning and
    # end to ensure that sufficient symbols can be used for the search
    sub_vars = np.ones((nmodes, num_steps)) * 1e2
    wxys = np.zeros((num_steps, nmodes, nmodes, Ntaps), dtype=rx_signal.dtype)
    for i in np.arange(search_overlap,
                       num_steps):  # we avoid one step at the beginning
        tmp = rx_signal[:, i * step:i * step + search_window]
        wxy, err_out = equalisation.equalise_signal(tmp,
                                                    os,
                                                    mu,
                                                    M_pilot,
                                                    Ntaps=Ntaps,
                                                    **eqargs)
        wxys[i] = wxy
        sub_vars[:, i] = np.var(err_out, axis=-1)
    # Lowest variance of the CMA error for each pol
    min_range = np.argmin(sub_vars, axis=-1)
    wxy = wxys[min_range]
    for l in range(nmodes):
        idx_min = min_range[l]
        # Extract a longer sequence to ensure that the complete pilot sequence is found
        longSeq = rx_signal[:, (idx_min) * step -
                            search_window:(idx_min) * step + search_window]
        # Apply filter taps to the long sequence and remove coarse FO
        wx1 = wxy[l]
        symbs_out = equalisation.apply_filter(longSeq, os, wx1)
        foe_corse = phaserecovery.find_freq_offset(symbs_out)
        symbs_out = phaserecovery.comp_freq_offset(symbs_out, foe_corse)
        # Check for pi/2 ambiguties and verify all
        max_phase_rot = np.zeros(nmodes, dtype=np.float64)
        found_delay = np.zeros(nmodes, dtype=np.int)
        for ref_pol in not_found_modes:
            ix, dat, ii, ac = ber_functions.find_sequence_offset_complex(
                ref_symbs[ref_pol], symbs_out[l])
            found_delay[ref_pol] = -ix
            max_phase_rot[ref_pol] = ac
        # Check for which mode found and extract the reference delay
        max_sync_pol = np.argmax(max_phase_rot)
        if max_phase_rot[max_sync_pol] < FRAME_SYNC_THRS:  #
            warnings.warn(
                "Very low autocorrelation, likely the frame-sync failed")
            sync_bool = False
        mode_sync_order[l] = max_sync_pol
        symb_delay = found_delay[max_sync_pol]
        # Remove the found reference mode
        not_found_modes = not_found_modes[not_found_modes != max_sync_pol]
        # New starting sample
        shift_factor[l] = (idx_min) * step + os * symb_delay - search_window
    # Important: the shift factors are arranged in the order of the signal modes, but
    # the mode_sync_order specifies how the signal modes need to be rearranged to match the pilots
    # therefore shift factors also need to be "mode_aligned"
    return shift_factor, foe_corse, mode_sync_order, wx1, sync_bool
コード例 #5
0
 def test_comp_freq_offset(self):
     s = signals.SignalQAMGrayCoded(16, 2 ** 16, fb=20e9, nmodes=1)
     ph = np.ones(1)*1e6
     s2 = cphaserecovery.comp_freq_offset(s.flatten(), ph)
     assert 2**16 == s2.shape[0]
コード例 #6
0
 def test_comp_freq_offset(self, ndim):
     s = signals.SignalQAMGrayCoded(16, 2 ** 16, fb=20e9, nmodes=ndim)
     ph = np.ones(ndim)*1e6
     s2 = cphaserecovery.comp_freq_offset(s, ph)
     assert ndim == s2.shape[0]
コード例 #7
0
def equalize_pilot_sequence(rx_signal, ref_symbs, shift_factor, os, sh = False, process_frame_id = 0, frame_length = 2**16, mu = (1e-4,1e-4), M_pilot = 4, ntaps = (25,45), Niter = (10,30), adap_step = (True,True), method=('cma','cma'),avg_foe_modes = True, do_pilot_based_foe=True,foe_symbs = None,blind_foe_payload=False):
    
    # Inital settings
    rx_signal = np.atleast_2d(rx_signal)
    ref_symbs = np.atleast_2d(ref_symbs)
    npols = rx_signal.shape[0]    
    pilot_seq_len = len(ref_symbs[0,:])    
    eq_pilots = np.zeros([npols,pilot_seq_len],dtype = complex)
    tmp_pilots = np.zeros([npols,pilot_seq_len],dtype = complex)
    out_taps = []

    # Tap update and extract the propper pilot sequuence    
    if not((ntaps[1]-ntaps[0])%os  ==  0):
        raise ValueError("Taps for search and convergence impropper configured")
    tap_cor = int((ntaps[1]-ntaps[0])/2)
    
    # Run FOE and shift spectrum
    if not sh:    
        # First Eq, extract pilot sequence to do FOE
        for l in range(npols):
            pilot_seq = rx_signal[:,shift_factor[l]-tap_cor:shift_factor[l]-tap_cor+pilot_seq_len*os+ntaps[1]-1]
            wx, err = equalisation.equalise_signal(pilot_seq, os, mu[0], M_pilot,Ntaps = ntaps[1], Niter = Niter[1], method = method[0],adaptive_stepsize = adap_step[1])
            # wx, err = equalisation.equalise_signal(pilot_seq, os, mu[1], M_pilot, wxy = wx, Ntaps=ntaps[1], Niter=Niter[1],
            #                                        method=method[0], adaptive_stepsize=adap_step[1])
            symbs_out= equalisation.apply_filter(pilot_seq,os,wx)       
            tmp_pilots[l,:] = symbs_out[l,:]
            
        # FOE Estimation, several options available. Default is pilot aided
        if do_pilot_based_foe:
            # Use the pilot-based FOE. Requires a pilot sequence of sufficient length    
            if foe_symbs is None:
                foe, foePerMode, cond = pilot_based_foe(tmp_pilots, ref_symbs)
            else:
                num_symbs = int(foe_symbs)
                if num_symbs > pilot_seq_len:
                    raise ValueError("Required number of symbols for FOE is larger than availabe sequence length. Maximum length available is %d"%pilot_seq_len)
                foe, foePerMode, cond = pilot_based_foe(tmp_pilots[:,:num_symbs], ref_symbs[:,:num_symbs])
        # Equalize 1 frame and do blind 4:th power FFT-based estimation
        else:
            foe_est_symbs = np.zeros([npols, frame_length],dtype=complex)
            for l in range(npols):
                # If blind_foe_payload is true, use the payload for FOE estimation and not the pilot sequence. Aims at comparing blind power of 4 FOE to pilot-based
                if blind_foe_payload:
                    est_sig = rx_signal[:,
                              shift_factor[l] - tap_cor + pilot_seq_len*os:shift_factor[l] - tap_cor + frame_length * os + ntaps[1] - 1 + pilot_seq_len*os]
                else:
                    est_sig = rx_signal[:,shift_factor[l]-tap_cor:shift_factor[l]-tap_cor+frame_length*os+ntaps[1]-1]
                est_frame = equalisation.apply_filter(est_sig,os,wx)
                foe_est_symbs[l,:] = est_frame[l,:]
            if foe_symbs is None:
                foePerMode = phaserecovery.find_freq_offset(foe_est_symbs)
            else:
                foePerMode = phaserecovery.find_freq_offset(foe_est_symbs[:, :foe_symbs], fft_size=foe_symbs)
        if avg_foe_modes:
            foe = np.mean(foePerMode)
            foePerMode = np.ones(foePerMode.shape)*foe
        # Apply FO-compensation
        sig_dc_center = phaserecovery.comp_freq_offset(rx_signal, foePerMode, os=os)
    else:
        # Signal should be DC-centered. Do nothing. 
        sig_dc_center = rx_signal
        foePerMode = np.zeros([npols,1])
        
    # First step Eq
    for l in range(npols):
        pilot_seq = sig_dc_center[:,shift_factor[l]-tap_cor:+shift_factor[l]-tap_cor+pilot_seq_len*os+ntaps[1]-1]    
        wxy_init, err = equalisation.equalise_signal(pilot_seq, os, mu[1], 4, Ntaps = ntaps[1], Niter = Niter[1], method = method[0],adaptive_stepsize = adap_step[1]) 
        wx, err = equalisation.equalise_signal(pilot_seq, os, mu[1], 4,wxy=wxy_init,Ntaps = ntaps[1], Niter = Niter[1], method = method[1],adaptive_stepsize = adap_step[1]) 
        out_taps.append(wx)
        symbs_out = equalisation.apply_filter(pilot_seq,os,out_taps[l])
        eq_pilots[l,:] = symbs_out[l,:]

    # Equalize using additional frames if selected
    for frame_id in range(0,process_frame_id+1):
        for l in range(npols):
            pilot_seq = sig_dc_center[:,frame_length*os*frame_id+shift_factor[l]-tap_cor:frame_length*os*frame_id+shift_factor[l]-tap_cor+pilot_seq_len*os+ntaps[1]-1]    
            wx_1, err = equalisation.equalise_signal(pilot_seq, os, mu[1], 4,wxy=out_taps[l],Ntaps = ntaps[1], Niter = Niter[1], method = method[1],adaptive_stepsize = adap_step[1])
            wx, err = equalisation.equalise_signal(pilot_seq, os, mu[1], 4,wxy=wx_1,Ntaps = ntaps[1], Niter = Niter[1], method = method[1],adaptive_stepsize = adap_step[1]) 
            out_taps[l] = wx

            if frame_id == process_frame_id:
                symbs_out = equalisation.apply_filter(pilot_seq,os,out_taps[l])
                eq_pilots[l,:] = symbs_out[l,:]
                shift_factor[l] = shift_factor[l] + process_frame_id*os*frame_length  

    return eq_pilots, foePerMode, out_taps, shift_factor
コード例 #8
0
def frame_sync(rx_signal, ref_symbs, os, frame_length = 2**16, mu = 1e-3, M_pilot = 4, ntaps = 25, Niter = 10, adap_step = True, method='cma' ,search_overlap = 2):
    """
    Locate and extract the pilot starting frame.
    
    Uses a CMA-based search scheme to located the initiial pilot sequence in
    the long data frame. 
    
    Input:
        rx_signal: Received Rx signal
        ref_symbs: Pilot sequence
        os: Oversampling
        frame_length: Total frame length including pilots and payload
        mu: CMA step size. Tuple(Search, Convergence)
        M_pilot: Order for pilot symbols. Should normally be QPSK and M=4
        ntaps: Number of T/2-spaced taps for equalization
        Niter: Number of iterations for the equalizer.Tuple(Search, Convergence)
        adap_step: Use adaptive step size (bool). Tuple(Search, Convergence)
        method: Equalizer mehtods to be used. Tuple(Search, Convergence)
        search_overlap: Overlap of subsequences in the test 
        
        
    Output:
        eq_pilots: Found pilot sequence after equalization
        shift_factor: New starting point for initial equalization
        out_taps: Taps for equalization of the whole signal
        foe_course: Result of blind FOE used to sync the pilot sequence. 
    
    """
    # Inital settings
    rx_signal = np.atleast_2d(rx_signal)
    ref_symbs = np.atleast_2d(ref_symbs)
    npols = rx_signal.shape[0]
    
    # Find the length of the pilot frame
    pilot_seq_len = len(ref_symbs[0,:])
    
    symb_step_size = int(np.floor(pilot_seq_len * os / search_overlap))
    
    # Adapt signal length
    sig_len = (np.shape(rx_signal)[1])
    if (sig_len > (frame_length + (search_overlap*2 + 5)*pilot_seq_len)*os):
        num_steps = int(np.ceil(((frame_length + (search_overlap*2 + 5) *pilot_seq_len)*os)/symb_step_size))
    else:
        num_steps = int(np.ceil(np.shape(rx_signal)[1] / symb_step_size))
    
    # Now search for every mode independent
    shift_factor = np.zeros(npols,dtype = int)
    for l in range(npols):

        # Search based on equalizer error. Avoid certain part in the beginning and
        # end to ensure that sufficient symbols can be used for the search
        sub_var = np.ones(num_steps)*1e2
        for i in np.arange(2+(search_overlap),num_steps-3-(search_overlap)):
            err_out = equalisation.equalise_signal(rx_signal[:,(i)*symb_step_size:(i+1+(search_overlap-1))*symb_step_size], os, mu, M_pilot,Ntaps = ntaps, Niter = Niter, method = method,adaptive_stepsize = adap_step)[1]
            sub_var[i] = np.var(err_out[l,int(-symb_step_size/os+ntaps):])
                       
        # Lowest variance of the CMA error
        minPart = np.argmin(sub_var)
        
        # Corresponding sequence
        shortSeq = rx_signal[:,(minPart)*symb_step_size:(minPart+1+(search_overlap-1))*symb_step_size]
        
        # Extract a longer sequence to ensure that the complete pilot sequence is found
        longSeq = rx_signal[:,(minPart-2-search_overlap)*symb_step_size:(minPart+3+search_overlap)*symb_step_size]

        # Use the first estimate to get rid of any large FO and simplify alignment
        wx1, err = equalisation.equalise_signal(shortSeq, os, mu, M_pilot,Ntaps = ntaps, Niter = Niter, method = method,adaptive_stepsize = adap_step)    
        seq_foe = equalisation.apply_filter(longSeq,os,wx1)
        foe_corse = phaserecovery.find_freq_offset(seq_foe)        
         
        # Apply filter taps to the long sequence
        symbs_out= equalisation.apply_filter(longSeq,os,wx1)     
        symbs_out[l,:] = phaserecovery.comp_freq_offset(symbs_out[l, :], foe_corse[l, :])
        # Check for pi/2 ambiguties
        max_phase_rot = np.zeros([4])
        found_delay = np.zeros([4])
        for k in range(4):
            # Find correlation for all 4 possible pi/2 rotations
            xcov = np.correlate(np.angle(symbs_out[l,:]*1j**k),np.angle(ref_symbs[l,:]))
            max_phase_rot[k] = np.max(xcov)
            found_delay[k] = np.argmax(xcov)
    
        # Select the best one    
        symb_delay = int(found_delay[np.argmax(max_phase_rot)]) 
        
        # New starting sample
        shift_factor[l] = int((minPart-4)*symb_step_size + os*symb_delay)

    return  shift_factor, foe_corse
コード例 #9
0
print(Y.shape)
SS = np.vstack([X[5000:-5000],Y[5000:-5000]])

SS = SS[:,:int(2e5)]

E, wxy, err_both = equalisation.dual_mode_equalisation(SS, os, M, ntaps, Niter=(5, 5), methods=("mcma", "sbd"),
                                                       adaptive_stepsize=(True, True))

X = signal_quality.norm_to_s0(E[0, :], M)
Y = signal_quality.norm_to_s0(E[1, :], M)
E = np.vstack([X,Y])

foe = phaserecovery.find_freq_offset(E, fft_size =2 ** 10)


E = phaserecovery.comp_freq_offset(E, foe)

#Ec = E[:,2e4:-2e4]
wx, err_both = equalisation.equalise_signal(E, 1, M, Ntaps=ntaps, Niter=4, method="sbd", adaptive_stepsize=False)
Ec = equalisation.apply_filter(E, 1, wx)
E = Ec


print("X pol phase")
Ex, phx = phaserecovery.bps(E[0], 32, QAM.symbols, 8)
print("X pol phase done")
print("Y pol phase")
Ey, phy = phaserecovery.bps(E[1], 32, QAM.symbols, 8)
print("Y pol phase done")
Ec = np.vstack([Ex,Ey])