def check_preamble_properties(preamble, x_preamble): x_1st = x_preamble[0:len(x_preamble) // 2] x_2nd = x_preamble[-len(x_preamble) // 2:] if not np.all(np.abs(x_1st - x_2nd) < 1e-12): print(np.abs(x_1st - x_2nd)) raise ValueError("preamble timeslots do not repeat!") from correlation import cross_correlate_naive, auto_correlate_halfs from utils import calculate_signal_energy x_ampl = np.sqrt(calculate_signal_energy(x_preamble)) preamble *= x_ampl x_preamble *= x_ampl x_energy = calculate_signal_energy(x_preamble) if np.abs(2.0 * auto_correlate_halfs(x_preamble) / x_energy) - 1.0 > 1e-10: raise ValueError("auto correlating halfs of preamble fails!") print( "normalized preamble xcorr val: ", np.correlate(x_preamble, x_preamble) / x_energy, ) print( "windowed normalized preamble: ", np.correlate(preamble[-len(x_preamble):], x_preamble) / x_energy, ) fxc = np.correlate(preamble, x_preamble, "full") / x_energy vxc = np.correlate(preamble, x_preamble, "valid") / x_energy nxc = cross_correlate_naive(preamble, x_preamble) / x_energy import matplotlib.pyplot as plt plt.plot(np.abs(fxc)) plt.plot(np.abs(vxc)) plt.plot(np.abs(nxc)) plt.show()
def check_preamble_properties(preamble, x_preamble): x_1st = x_preamble[0:len(x_preamble) // 2] x_2nd = x_preamble[-len(x_preamble) // 2:] if not np.all(np.abs(x_1st - x_2nd) < 1e-12): print np.abs(x_1st - x_2nd) raise ValueError('preamble timeslots do not repeat!') from correlation import cross_correlate_naive, auto_correlate_halfs from utils import calculate_signal_energy x_ampl = np.sqrt(calculate_signal_energy(x_preamble)) preamble *= x_ampl x_preamble *= x_ampl x_energy = calculate_signal_energy(x_preamble) if np.abs(2. * auto_correlate_halfs(x_preamble) / x_energy) -1. > 1e-10: raise ValueError('auto correlating halfs of preamble fails!') print 'normalized preamble xcorr val: ', np.correlate(x_preamble, x_preamble) / x_energy print 'windowed normalized preamble: ', np.correlate(preamble[-len(x_preamble):], x_preamble) / x_energy fxc = np.correlate(preamble, x_preamble, 'full') / x_energy vxc = np.correlate(preamble, x_preamble, 'valid') / x_energy nxc = cross_correlate_naive(preamble, x_preamble) / x_energy import matplotlib.pyplot as plt plt.plot(np.abs(fxc)) plt.plot(np.abs(vxc)) plt.plot(np.abs(nxc)) plt.show()
def preamble_auto_corr_test(): K = 32 pn_seq = get_random_qpsk(K) pn_symbols = np.tile(pn_seq, 2) D = get_data_matrix(pn_symbols, K, True) # print np.shape(D) print 'subcarriers bear same symbols:', np.all(D[0] == D[1]) pl, p = generate_sync_symbol(pn_seq, 'rrc', .5, K, 2, K, K / 2) # print np.shape(p) acc = auto_correlate_halfs(p) print acc, np.angle(acc) taps = gfdm_filter_taps('rrc', .5, 2, K, 1) A = gfdm_modulation_matrix(taps, 2, K) x = A.dot(pn_symbols) # print np.shape(x) acc = auto_correlate_halfs(x) print acc, np.angle(acc)
def preamble_auto_corr_test(): K = 32 pn_seq = get_random_qpsk(K) pn_symbols = np.tile(pn_seq, 2) D = get_data_matrix(pn_symbols, K, True) # print np.shape(D) print 'subcarriers bear same symbols:', np.all(D[0] == D[1]) pl, p = generate_sync_symbol(pn_seq, 'rrc', .5, K, 2, K, K / 2) # print np.shape(p) acc = auto_correlate_halfs(p) print acc, np.angle(acc) taps = gfdm_filter_taps('rrc', .5, 2, K, 1) A = gfdm_modulation_matrix(taps, 2, K) x = A.dot(pn_symbols) # print np.shape(x) acc = auto_correlate_halfs(x) print acc, np.angle(acc)
def main(): np.set_printoptions(precision=4, suppress=True) # preamble_auto_corr_test() sync_test() return # cfo = 1.024e-5 samp_rate = 12.5e6 freq = 20. fft_len = 256 sc_bw = samp_rate / fft_len cfo = freq_to_cfo(freq, fft_len, samp_rate) ph_i = cfo_to_phase_increment(cfo, fft_len) phase_inc = phase_increment(freq, samp_rate) print 'samp_rate: {}, frequency: {}, fft_len: {}'.format( samp_rate, freq, fft_len) print 'subcarrier bandwidth: {}, cfo: {}, phase increment: {}/{}'.format( sc_bw, cfo, ph_i, phase_inc) # wave = get_complex_sine(freq, samp_rate, 129) # s = np.ones(129) # s = correct_frequency_offset(s, cfo, fft_len) # # print wave # print np.abs(wave - s) preamble, x_preamble = generate_sync_symbol( get_random_qpsk(fft_len, seed=generate_seed('awesome')), 'rrc', .5, fft_len, 2, fft_len // 2, fft_len // 8) init_phase = 0.8 wave = complex_sine(cfo_to_phase_increment(cfo, fft_len), len(preamble)) # phase_shift = np.repeat(, len(preamble)) wave *= np.exp(1j * init_phase) preamble *= wave print phase_inc ac = auto_correlate_halfs(preamble[64:64 + 2 * fft_len]) fp = np.angle(ac) ac_phase_inc = fp / fft_len print 'auto corr phase: {}, AC phase {}, phase_inc: {}'.format( phase_inc, fp, ac_phase_inc) xc = cross_correlate_signal(preamble, x_preamble) ap = np.angle(xc[64]) # print ap, (ap - init_phase) / (cfo * 2 * np.pi) residual = ap - init_phase res_phase = residual / (2 * fft_len) print residual, res_phase, phase_inc / res_phase # print fp, fp / (2 * np.pi) # print (ap - init_phase) - fp plt.plot(np.abs(xc) / 10000.) plt.plot(np.angle(xc)) plt.show()
def auto_correlate_signal(signal, K): plen = K * 2 slen = len(signal) ac = np.zeros(slen - plen, dtype=np.complex) for i in range(slen - plen): # calc auto-correlation c = signal[i:i + plen] #normalize value p = calculate_signal_energy(c) ac[i] = 2 * auto_correlate_halfs(c) / p return ac
def auto_correlate_signal(signal, K): plen = K * 2 slen = len(signal) ac = np.zeros(slen - plen, dtype=np.complex) for i in range(slen - plen): # calc auto-correlation c = signal[i:i+plen] #normalize value p = calculate_signal_energy(c) ac[i] = 2 * auto_correlate_halfs(c) / p return ac
def main(): import matplotlib.pyplot as plt np.set_printoptions(precision=4, suppress=True) # preamble_auto_corr_test() sync_test() return # cfo = 1.024e-5 samp_rate = 12.5e6 freq = 20. fft_len = 256 sc_bw = samp_rate / fft_len cfo = freq_to_cfo(freq, fft_len, samp_rate) ph_i = cfo_to_phase_increment(cfo, fft_len) phase_inc = phase_increment(freq, samp_rate) print 'samp_rate: {}, frequency: {}, fft_len: {}'.format(samp_rate, freq, fft_len) print 'subcarrier bandwidth: {}, cfo: {}, phase increment: {}/{}'.format(sc_bw, cfo, ph_i, phase_inc) # wave = get_complex_sine(freq, samp_rate, 129) # s = np.ones(129) # s = correct_frequency_offset(s, cfo, fft_len) # # print wave # print np.abs(wave - s) preamble, x_preamble = generate_sync_symbol(get_random_qpsk(fft_len, seed=generate_seed('awesome')), 'rrc', .5, fft_len, 2, fft_len // 2, fft_len // 8) init_phase = 0.8 wave = complex_sine(cfo_to_phase_increment(cfo, fft_len), len(preamble)) # phase_shift = np.repeat(, len(preamble)) wave *= np.exp(1j * init_phase) preamble *= wave print phase_inc ac = auto_correlate_halfs(preamble[64:64 + 2 * fft_len]) fp = np.angle(ac) ac_phase_inc = fp / fft_len print 'auto corr phase: {}, AC phase {}, phase_inc: {}'.format(phase_inc, fp, ac_phase_inc) xc = cross_correlate_signal(preamble, x_preamble) ap = np.angle(xc[64]) # print ap, (ap - init_phase) / (cfo * 2 * np.pi) residual = ap - init_phase res_phase = residual / (2 * fft_len) print residual, res_phase, phase_inc / res_phase # print fp, fp / (2 * np.pi) # print (ap - init_phase) - fp plt.plot(np.abs(xc) / 10000.) plt.plot(np.angle(xc)) plt.show()
def sync_test(): samp_rate = 10e6 # an assumption to work with alpha = .3 M = 33 K = 32 block_len = M * K L = 2 cp_len = K ramp_len = cp_len / 2 test_cfo = -.2 snr_dB = 40.0 false_alarm_probability = 1e-3 print 'Channel parameters, SNR:', snr_dB, 'dB with a relative subcarrier offset:', test_cfo print 'assumed samp_rate:', samp_rate, ' with sc_bw:', samp_rate / K frame, x_preamble = generate_test_sync_samples(M, K, L, alpha, cp_len, ramp_len, snr_dB, test_cfo) print np.correlate(x_preamble, x_preamble), auto_correlate_halfs(x_preamble) print 'frame duration: ', 1e6 * len(frame) / samp_rate, 'us' print M, '*', K, '=', block_len, '(', block_len + cp_len, ')' print 'frame start in test vector: ', block_len + cp_len s = frame s *= 100. / np.sqrt(len(x_preamble)) nc, cfo, abs_corr_vals, corr_vals, napcc, apcc = find_frame_start( s, x_preamble, K, cp_len) print 'FOUND FRAMESTART nc:', nc, np.abs(napcc[nc]), abs_corr_vals[nc] # print 'signal_len:', len(s), ', auto_corr_len:', len(auto_corr_vals), ', cross_corr_len:', len(napcc), len(s) - len(napcc) thr = calculate_threshold_factor(false_alarm_probability) * np.sum( apcc[nc - K:nc + K]) / (2 * K) print 'threshold: ', thr plt.plot(abs_corr_vals, label='auto corr') plt.plot(apcc, label='cross corr') # * (np.abs(napcc[nc] / np.abs(apcc[nc])))) plt.plot(napcc, label='combined') threshold_peak = np.zeros(len(napcc), dtype=float) threshold_peak[nc] = napcc[nc] plt.plot((threshold_peak > thr) * (napcc[nc] / thr)) print 'threshold exceeded points: ', np.sum(threshold_peak > thr) for thr in (.3, .4, .5, .6): peak = abs_corr_vals > thr plt.plot(peak * thr) print 'n exceed thr: ', thr, ':', np.sum(peak) plt.xlim((1000, 1200)) plt.legend() plt.show()
def sync_test(): import matplotlib.pyplot as plt samp_rate = 10e6 # an assumption to work with alpha = .3 M = 33 K = 32 block_len = M * K L = 2 cp_len = K ramp_len = cp_len / 2 test_cfo = -.0 snr_dB = 40.0 false_alarm_probability = 1e-3 print 'Channel parameters, SNR:', snr_dB, 'dB with a relative subcarrier offset:', test_cfo print 'assumed samp_rate:', samp_rate, ' with sc_bw:', samp_rate / K frame, x_preamble, pn_symbols, data = generate_test_sync_samples(M, K, L, alpha, cp_len, ramp_len, snr_dB, test_cfo, .25, True) p_len = 2 * K + cp_len + ramp_len frame_len = M * K + p_len print 'test correlate', np.correlate(x_preamble, x_preamble), auto_correlate_halfs(x_preamble) print 'test correlate', np.angle(np.correlate(x_preamble * np.exp(-1j * .25), x_preamble)), auto_correlate_halfs(x_preamble) print 'frame duration: ', 1e6 * len(frame) / samp_rate, 'us' print M, '*', K, '=', block_len, '(', block_len + cp_len, ')' print 'frame start in test vector: ', block_len + cp_len s = frame nc, cfo, abs_corr_vals, corr_vals, napcc, apcc = find_frame_start(s, x_preamble, K, cp_len) print 'FOUND FRAMESTART nc:', nc, np.abs(napcc[nc]), abs_corr_vals[nc] snc, scfo, scc, phase = simplified_sync_algo(s, x_preamble, K, cp_len) frame_start = snc + p_len print 'data frame_start: ', frame_start, ', len(preamble)=', p_len prx_frame = frame[snc:snc + frame_len] rx_preamble = prx_frame[0:2 * K] rx = frame[frame_start:frame_start + M * K] # rx_preamble = frame[snc:snc + 2 * K] r = gfdm_demodulate_fft(rx, alpha, M, K, L) plt.scatter(r.real, r.imag) # r_frame = correct_frequency_offset(rx, scfo / (2. * K), K) phase_inc = cfo_to_phase_increment(-scfo, K) print 'phase_increment: ', phase_inc, 'phase: ', phase, ', K * inc: ', K * phase_inc wave = complex_sine(phase_inc, len(rx), -phase) # wave = complex_sine(phase_inc, len(rx), 0.0) # phase_shift = np.repeat(np.exp(1j * init_phase), len(frame)) # wave *= phase_shift r_frame = rx * wave rx_corr = np.correlate(rx_preamble, x_preamble) wave = complex_sine(phase_inc, len(rx_preamble), 0.0) crx_preamble = rx_preamble * wave crx_corr = np.correlate(crx_preamble, x_preamble) f_corr = np.correlate(crx_preamble * (-phase), x_preamble) print 'correlations: ', np.angle(rx_corr), np.angle(crx_corr), np.angle(f_corr) s = gfdm_demodulate_fft(r_frame, alpha, M, K, L) plt.scatter(s.real, s.imag, color='r') x = gfdm_demodulate_fft(r_frame, alpha, M, K, L, sic_rounds=2) plt.scatter(x.real, x.imag, color='g') plt.scatter(data.real, data.imag, color='m', marker='x', s=100) print np.all(np.abs(data - x) < .5) print np.sum(np.abs(data - x)) / len(x) print np.max(np.abs(data - x)) # plt.xlim((1000, 1200)) # plt.legend() plt.grid() plt.show()