def generate_test_sync_samples(M, K, L, alpha, cp_len, ramp_len, snr_dB, test_cfo, init_phase=0.0, ref_data=False): block_len = M * K data = get_random_qpsk(block_len, seed=generate_seed('awesomepayloadblabla')) print 'QPSK source energy: ', calculate_average_signal_energy(data) x = get_gfdm_frame(data, alpha, M, K, L, cp_len, ramp_len) pn_symbols = get_random_qpsk(K, seed=generate_seed('awesome')) preamble, x_preamble = generate_sync_symbol(pn_symbols, 'rrc', alpha, K, L, cp_len, ramp_len) print 'frame energy:', calculate_average_signal_energy(x), 'preamble energy:', calculate_average_signal_energy(preamble) frame = np.concatenate((preamble, x)) print 'tx frame len', len(frame), 'len(preamble)', len(preamble) # simulate Noise and frequency offset! phase_inc = cfo_to_phase_increment(test_cfo, K) print 'phase_increment: ', phase_inc wave = complex_sine(phase_inc, len(frame), init_phase) # phase_shift = np.repeat(np.exp(1j * init_phase), len(frame)) # wave *= phase_shift frame *= wave noise_variance = calculate_awgn_noise_variance(frame, snr_dB) s = get_complex_noise_vector(2 * block_len + len(frame), noise_variance) s[block_len:block_len + len(frame)] += frame if ref_data: return s, x_preamble, pn_symbols, data return s, x_preamble, pn_symbols
def generate_integrated_frame(timeslots, subcarriers, active_subcarriers, cp_len, cs_len, alpha=.2): p_seed = utils.generate_seed('awesome preamble') f_seed = utils.generate_seed('awesome frame') subcarrier_map = mapping.get_subcarrier_map(subcarriers, active_subcarriers, dc_free=True) overlap = 2 p, p_vals = preamble.symmetric_mapped_preamble(p_seed, 'rrc', alpha, active_subcarriers, subcarriers, subcarrier_map, overlap, cp_len, cs_len) frame_preamble, x_preamble = p p = gfdm_modulation.modulate_mapped_gfdm_block(np.concatenate((p_vals, p_vals, np.zeros((timeslots - 2) * active_subcarriers))), timeslots, subcarriers, active_subcarriers, overlap, alpha, dc_free=True) x_preamble = p[0:len(x_preamble)] d = utils.get_random_qpsk((timeslots - 4) * active_subcarriers, f_seed) d = np.tile(p_vals, timeslots) # d = np.concatenate((p_vals, p_vals, d, p_vals, p_vals)) # d = utils.get_random_qpsk((timeslots - 2) * active_subcarriers, f_seed) # d = np.concatenate((p_vals, p_vals, d)) d_frame = mod_frame = gfdm_modulation.modulate_mapped_gfdm_block(d, timeslots, subcarriers, active_subcarriers, overlap, alpha, dc_free=True) symbol = cyclic_prefix.add_cyclic_starfix(d_frame, cp_len, cs_len) window_ramp = cyclic_prefix.get_raised_cosine_ramp(cs_len, cyclic_prefix.get_window_len(cp_len, timeslots, subcarriers, cs_len)) # d_frame = cyclic_prefix.pinch_block(symbol, window_ramp) H = filters.get_frequency_domain_filter('rrc', alpha, timeslots, subcarriers, overlap) return p, mod_frame, x_preamble, d, H
def generate_reference_frame(timeslots, subcarriers, active_subcarriers, cp_len, cs_len, alpha=.2): p_seed = utils.generate_seed('awesome preamble') f_seed = utils.generate_seed('awesome frame') subcarrier_map = mapping.get_subcarrier_map(subcarriers, active_subcarriers, dc_free=True) overlap = 2 frame_preamble, x_preamble = preamble.mapped_preamble( p_seed, 'rrc', alpha, active_subcarriers, subcarriers, subcarrier_map, overlap, cp_len, cs_len) d = utils.get_random_qpsk(timeslots * active_subcarriers, f_seed) d_frame = mod_frame = gfdm_modulation.modulate_mapped_gfdm_block( d, timeslots, subcarriers, active_subcarriers, overlap, alpha, dc_free=True) symbol = cyclic_prefix.add_cyclic_starfix(d_frame, cp_len, cs_len) window_ramp = cyclic_prefix.get_raised_cosine_ramp( cs_len, cyclic_prefix.get_window_len(cp_len, timeslots, subcarriers, cs_len)) d_frame = cyclic_prefix.pinch_block(symbol, window_ramp) H = filters.get_frequency_domain_filter('rrc', alpha, timeslots, subcarriers, overlap) return np.concatenate( (frame_preamble, d_frame)), mod_frame, x_preamble, d, H
def mapped_preamble(seed, filtertype, alpha, active_subcarriers, fft_len, subcarrier_map, overlap, cp_len, ramp_len): pn_vals = get_random_qpsk(active_subcarriers, seed) pn_sym = map_to_waveform_resources(pn_vals, active_subcarriers, fft_len, subcarrier_map) return generate_sync_symbol(pn_sym, filtertype, alpha, fft_len, overlap, cp_len, ramp_len)
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 generate_integrated_frame(timeslots, subcarriers, active_subcarriers, cp_len, cs_len, alpha=.2): p_seed = utils.generate_seed('awesome preamble') f_seed = utils.generate_seed('awesome frame') subcarrier_map = mapping.get_subcarrier_map(subcarriers, active_subcarriers, dc_free=True) overlap = 2 p, p_vals = preamble.symmetric_mapped_preamble(p_seed, 'rrc', alpha, active_subcarriers, subcarriers, subcarrier_map, overlap, cp_len, cs_len) frame_preamble, x_preamble = p p = gfdm_modulation.modulate_mapped_gfdm_block(np.concatenate( (p_vals, p_vals, np.zeros((timeslots - 2) * active_subcarriers))), timeslots, subcarriers, active_subcarriers, overlap, alpha, dc_free=True) x_preamble = p[0:len(x_preamble)] d = utils.get_random_qpsk((timeslots - 4) * active_subcarriers, f_seed) d = np.tile(p_vals, timeslots) # d = np.concatenate((p_vals, p_vals, d, p_vals, p_vals)) # d = utils.get_random_qpsk((timeslots - 2) * active_subcarriers, f_seed) # d = np.concatenate((p_vals, p_vals, d)) d_frame = mod_frame = gfdm_modulation.modulate_mapped_gfdm_block( d, timeslots, subcarriers, active_subcarriers, overlap, alpha, dc_free=True) symbol = cyclic_prefix.add_cyclic_starfix(d_frame, cp_len, cs_len) window_ramp = cyclic_prefix.get_raised_cosine_ramp( cs_len, cyclic_prefix.get_window_len(cp_len, timeslots, subcarriers, cs_len)) # d_frame = cyclic_prefix.pinch_block(symbol, window_ramp) H = filters.get_frequency_domain_filter('rrc', alpha, timeslots, subcarriers, overlap) return p, mod_frame, x_preamble, d, H
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 test_transceiver_00(): K = 32 M = 8 overlap = 2 alpha = 0.5 d = get_random_qpsk(M * K) tx = gfdm_gr_modulator(d, 'rrc', alpha, M, K, overlap, compat_mode=False) / (float(K)) rx = gfdm_gr_receiver(tx, 'rrc', alpha, M, K, overlap, compat_mode=False) / (float(K)) plt.plot(d) plt.plot(rx) plt.show()
def generate_reference_frame(timeslots, subcarriers, active_subcarriers, cp_len, cs_len, alpha=.2): p_seed = utils.generate_seed('awesome preamble') f_seed = utils.generate_seed('awesome frame') subcarrier_map = mapping.get_subcarrier_map(subcarriers, active_subcarriers, dc_free=True) overlap = 2 frame_preamble, x_preamble = preamble.mapped_preamble(p_seed, 'rrc', alpha, active_subcarriers, subcarriers, subcarrier_map, overlap, cp_len, cs_len) d = utils.get_random_qpsk(timeslots * active_subcarriers, f_seed) d_frame = mod_frame = gfdm_modulation.modulate_mapped_gfdm_block(d, timeslots, subcarriers, active_subcarriers, overlap, alpha, dc_free=True) symbol = cyclic_prefix.add_cyclic_starfix(d_frame, cp_len, cs_len) window_ramp = cyclic_prefix.get_raised_cosine_ramp(cs_len, cyclic_prefix.get_window_len(cp_len, timeslots, subcarriers, cs_len)) d_frame = cyclic_prefix.pinch_block(symbol, window_ramp) H = filters.get_frequency_domain_filter('rrc', alpha, timeslots, subcarriers, overlap) return np.concatenate((frame_preamble, d_frame)), mod_frame, x_preamble, d, H
def test_transceiver_00(): import matplotlib.pyplot as plt K = 32 M = 8 overlap = 2 alpha = 0.5 d = get_random_qpsk(M*K) tx = gfdm_gr_modulator(d, 'rrc', alpha, M, K, overlap, compat_mode=False)/(float(K)) rx = gfdm_gr_receiver(tx, 'rrc', alpha, M, K, overlap, compat_mode=False)/(float(K)) plt.plot(d) plt.plot(rx) plt.show()
def generate_test_sync_samples(M, K, L, alpha, cp_len, ramp_len, snr_dB, test_cfo): block_len = M * K data = get_random_qpsk(block_len, seed=generate_seed('awesomepayloadblabla')) x = get_gfdm_frame(data, alpha, M, K, L, cp_len, ramp_len) preamble, x_preamble = generate_sync_symbol( get_random_qpsk(K, seed=generate_seed('awesome')), 'rrc', alpha, K, L, cp_len, ramp_len) print 'frame energy:', calculate_average_signal_energy( x), 'preamble energy:', calculate_average_signal_energy(preamble) preamble *= np.sqrt( calculate_average_signal_energy(x) / calculate_average_signal_energy(preamble)) frame = np.concatenate((preamble, x)) # simulate Noise and frequency offset! frame = correct_frequency_offset(frame, test_cfo / (-2. * K)) noise_variance = calculate_awgn_noise_variance(frame, snr_dB) s = get_complex_noise_vector(2 * block_len + len(frame), noise_variance) s[block_len:block_len + len(frame)] += frame return s, x_preamble
def test_transceiver_legacy_00(): K = 32 M = 8 overlap = 2 alpha = 0.5 oversampling_factor = 1 tests = 100 for t in xrange(tests): d = get_random_qpsk(M * K) tx = gfdm_gr_modulator(d, 'rrc', alpha, M, K, overlap) rx = gfdm_rx_fft2(tx, 'rrc', alpha, M, K, overlap, oversampling_factor, 4, 16) if not (np.max(np.abs(d - rx)) < 1e-2): raise RuntimeError('Input and Output deviate')
def test_transceiver_00(): import matplotlib.pyplot as plt K = 32 M = 8 overlap = 2 alpha = 0.5 d = get_random_qpsk(M * K) tx = gfdm_gr_modulator(d, "rrc", alpha, M, K, overlap, compat_mode=False) / (float(K)) rx = gfdm_gr_receiver(tx, "rrc", alpha, M, K, overlap, compat_mode=False) / (float(K)) plt.plot(d) plt.plot(rx) plt.show()
def main(): ''' This is a comparison for 3 different demodulation approaches. matched filter matrix being the 'benchmark' The other two should converge towards the matrix approach for overlap -> subcarriers Actually, there's a bug in the 'GR' approach, thus it only works for overlap==2 ''' timeslots = 25 subcarriers = 16 overlap = 2 time_taps = gfdm_filter_taps('rrc', .5, timeslots, subcarriers, 1) freq_taps = gfdm_freq_taps(time_taps) sparse_freq_taps = gfdm_freq_taps_sparse(freq_taps, timeslots, overlap) A = gfdm_modulation_matrix(time_taps, timeslots, subcarriers, 1, True) Ainv = np.linalg.inv(A) Amf = np.conjugate(A).T tx_syms = get_random_qpsk(timeslots * subcarriers) rx_syms = A.dot(tx_syms) mf_matrix_rx = Amf.dot(rx_syms) inv_matrix_rx = Ainv.dot(rx_syms) gr_res = gfdm_demodulate_block(rx_syms, sparse_freq_taps, subcarriers, timeslots, overlap) fft_res = gfdm_demodulate_fft_loop(rx_syms, timeslots, subcarriers, overlap, sparse_freq_taps) mf_matrix_rx *= np.sqrt( calculate_average_signal_energy(fft_res) / calculate_average_signal_energy(mf_matrix_rx)) inv_matrix_rx *= np.sqrt( calculate_average_signal_energy(fft_res) / calculate_average_signal_energy(inv_matrix_rx)) gr_res *= np.sqrt( calculate_average_signal_energy(fft_res) / calculate_average_signal_energy(gr_res)) print 'compare demodulation accuracy for different approaches' for e in range(11): em = 10**(-1. * e) matrixvsloop = np.all(np.abs(fft_res - mf_matrix_rx) < em) grvsmatrix = np.all(np.abs(gr_res - mf_matrix_rx) < em) grvsloop = np.all(np.abs(gr_res - fft_res) < em) print 'error margin {:.1e}\tMFmatriXvsGR: {}\tMFmatriXvsLoop: {}\tGRvsLoop: {}'.format( em, grvsmatrix, matrixvsloop, grvsloop)
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 test_transceiver_legacy_00(): K = 32 M = 8 overlap = 2 alpha = 0.5 oversampling_factor = 1 tests = 100 for t in xrange(tests): d = get_random_qpsk(M*K) tx = gfdm_gr_modulator(d, 'rrc', alpha, M, K, overlap) rx = gfdm_rx_fft2( tx, 'rrc', alpha, M, K, overlap, oversampling_factor, 4, 16) if not (np.max(np.abs(d-rx)) < 1e-2): raise RuntimeError('Input and Output deviate')
def main(): ''' This is a comparison for 3 different demodulation approaches. matched filter matrix being the 'benchmark' The other two should converge towards the matrix approach for overlap -> subcarriers Actually, there's a bug in the 'GR' approach, thus it only works for overlap==2 ''' timeslots = 25 subcarriers = 16 overlap = 2 time_taps = gfdm_filter_taps('rrc', .5, timeslots, subcarriers, 1) freq_taps = gfdm_freq_taps(time_taps) sparse_freq_taps = gfdm_freq_taps_sparse(freq_taps, timeslots, overlap) A = gfdm_modulation_matrix(time_taps, timeslots, subcarriers, 1, True) Ainv = np.linalg.inv(A) Amf = np.conjugate(A).T tx_syms = get_random_qpsk(timeslots * subcarriers) rx_syms = A.dot(tx_syms) mf_matrix_rx = Amf.dot(rx_syms) inv_matrix_rx = Ainv.dot(rx_syms) gr_res = gfdm_demodulate_block(rx_syms, sparse_freq_taps, subcarriers, timeslots, overlap) fft_res = gfdm_demodulate_fft_loop(rx_syms, timeslots, subcarriers, overlap, sparse_freq_taps) mf_matrix_rx *= np.sqrt(calculate_average_signal_energy(fft_res) / calculate_average_signal_energy(mf_matrix_rx)) inv_matrix_rx *= np.sqrt(calculate_average_signal_energy(fft_res) / calculate_average_signal_energy(inv_matrix_rx)) gr_res *= np.sqrt(calculate_average_signal_energy(fft_res) / calculate_average_signal_energy(gr_res)) print 'compare demodulation accuracy for different approaches' for e in range(11): em = 10 ** (-1. * e) matrixvsloop = np.all(np.abs(fft_res - mf_matrix_rx) < em) grvsmatrix = np.all(np.abs(gr_res - mf_matrix_rx) < em) grvsloop = np.all(np.abs(gr_res - fft_res) < em) print 'error margin {:.1e}\tMFmatriXvsGR: {}\tMFmatriXvsLoop: {}\tGRvsLoop: {}'.format(em, grvsmatrix, matrixvsloop, grvsloop)
def get_random_GFDM_block(ts, sc, overlap, alpha): data = get_random_qpsk(ts*sc) tx_data = gfdm_modulate_fft(data, alpha, ts, sc, overlap) return (data, tx_data)
td_seq1 = np.tile(td_seq1, 2) papr = np.max(np.abs(td_seq1)**2) / np.mean(np.abs(td_seq1)**2) print(f'USED: PAPRlin={papr:.4f}, {10. * np.log10(papr):.4f}dB') # plt.plot(np.abs(td_seq1)) # plt.show() plt.plot(np.abs(np.correlate(td_seq1, td_seq1, 'full')), label='USED') seq2 = generate_zadoff_chu_sequence(nsc, 19) fd_seq2 = np.fft.fft(seq2) s = np.zeros_like(seq2) s[sc_mask] = fd_seq2[sc_mask] td_seq2 = np.fft.ifft(s) / np.sqrt(nsc) td_seq2 = np.tile(td_seq2, 2) papr = np.max(np.abs(td_seq2)**2) / np.mean(np.abs(td_seq2)**2) print(f'TD: PAPRlin={papr:.4f}, {10. * np.log10(papr):.4f}dB') plt.plot(np.abs(np.correlate(td_seq2, td_seq2, 'full')), label='TD') d = get_random_qpsk(nasc) s = np.zeros_like(seq2) s[sc_mask] = d td_seq3 = np.fft.ifft(s) td_seq3 = np.tile(td_seq3, 2) papr = np.max(np.abs(td_seq3)**2) / np.mean(np.abs(td_seq3)**2) print(f'QPSK: PAPRlin={papr:.4f}, {10. * np.log10(papr):.4f}dB') plt.plot(np.abs(np.correlate(td_seq3, td_seq3, 'full')), label='QPSK') plt.legend() plt.show()
def mapped_preamble(seed, filtertype, alpha, active_subcarriers, fft_len, subcarrier_map, overlap, cp_len, ramp_len): pn_vals = get_random_qpsk(active_subcarriers, seed) pn_sym = map_to_waveform_resources(pn_vals, active_subcarriers, fft_len, subcarrier_map) return generate_sync_symbol(pn_sym, filtertype, alpha, fft_len, overlap, cp_len, ramp_len)
def symmetric_mapped_preamble(seed, filtertype, alpha, active_subcarriers, fft_len, subcarrier_map, overlap, cp_len, ramp_len): pn_vals = get_random_qpsk(active_subcarriers // 2, seed) pn_vals = np.concatenate((pn_vals, np.conj(pn_vals[::-1]))) pn_sym = map_to_waveform_resources(pn_vals, active_subcarriers, fft_len, subcarrier_map) return generate_sync_symbol(pn_sym, filtertype, alpha, fft_len, overlap, cp_len, ramp_len), pn_vals