def get_Hlist(self): # Np array to store `FFT_size` number of Nt*Nr channels chan_freq = np.zeros(shape=(self.fft_size, self.Nt, self.Nr), dtype=complex) # Initialise the matrices for i in range(self.Nt * self.Nr): col_idx = i % self.Nr row_idx = i // self.Nr freq_resp = itpp.cmat() inp_resp = itpp.cmat() #Get Impulse Response inp_resp.set_size(1, self.channel_length, False) inp_resp.set_row(0, self.channel.get_row(i)) # print(inp_resp) #Calculate Frequency Response for each Nt*Nr channel (64 length array) self.tdl_channels[i].calc_frequency_response( inp_resp, freq_resp, 2 * self.fft_size) # Store it in chan_freq in appropriate places across 64 matrices # print(freq_resp.to_numpy_ndarray().flatten()[0:64]-freq_resp.to_numpy_ndarray().flatten()[64:128]) chan_freq[:, row_idx][:, col_idx] = freq_resp.to_numpy_ndarray( ).flatten()[0:self.fft_size] chan_freq_list = [] for i in range(self.fft_size): chan_freq_list.append(chan_freq[i]) #print(chan_freq_list[0]) return (chan_freq_list)
def channel_frequency_response(fft_size, relative_speed, channel_model, nrof_subframes): carrier_freq = 2.0e9 # 2 GHz subcarrier_spacing = 15000 # Hz sampling_frequency = subcarrier_spacing * fft_size sampling_interval = 1.0 / sampling_frequency relative_speed = relative_speed # in m/s doppler_frequency = (carrier_freq / 3e8) * relative_speed norm_doppler = doppler_frequency * sampling_interval frame_duration = 1.0e-3 # 1 ms frame_samples = int(frame_duration / sampling_interval) model = None if channel_model == 'ITU_PEDESTRIAN_A': model = itpp.comm.CHANNEL_PROFILE.ITU_Pedestrian_A elif channel_model == 'ITU_PEDESTRIAN_B': model = itpp.comm.CHANNEL_PROFILE.ITU_Pedestrian_B elif channel_model == 'ITU_VEHICULAR_A': model = itpp.comm.CHANNEL_PROFILE.ITU_Vehicular_A elif channel_model == 'ITU_VEHICULAR_B': model = itpp.comm.CHANNEL_PROFILE.ITU_Vehicular_B else: print('Specified channel model %s not configured in %s'%(model, __file__)) channel_spec = itpp.comm.Channel_Specification(model) channel = itpp.comm.TDL_Channel(channel_spec, sampling_interval) nrof_taps = channel.taps() channel.set_norm_doppler(norm_doppler) # Generate channel coefficients for a few frames channel_coeff = itpp.cmat() channel_coeff.set_size(nrof_subframes, nrof_taps, False) for frame_index in range(nrof_subframes): frame_start_sample = int(frame_index * frame_samples) channel.set_time_offset(frame_start_sample) frame_channel_coeff = itpp.cmat() channel.generate(1, frame_channel_coeff) channel_coeff.set_row(frame_index, frame_channel_coeff.get_row(0)) freq_resp = itpp.cmat() channel.calc_frequency_response(channel_coeff, freq_resp, fft_size) return freq_resp
def calculate_channel_frequency_response(channel, subframe_index, nrof_resource_blocks=CONFIG.NROF_TOTAL_PRBS): channel_impulse_response = itpp.cmat() channel_frequency_response = itpp.cmat() nrof_offset_samples = int(subframe_index * CONFIG.SUBFRAME_DURATION / CONFIG.SAMPLING_INTERVAL) channel.set_time_offset(nrof_offset_samples) # Generate channel samples. Each channel sample is shifted by the transmission duration channel.generate(1, channel_impulse_response) channel.calc_frequency_response(channel_impulse_response, channel_frequency_response, CONFIG.SUBCARRIERS_PER_PRB * nrof_resource_blocks) channel_coefficients = channel_frequency_response.get_col(0) return channel_coefficients
def simluate_rayleigh_fading_channel(nrof_samples, avg_snr_dB, awgn_data, packet_sizes, norm_doppler=0.01, seed=9999, cqi_error_std=0.0): # Create a Rayleigh fading channel. The channel power is normalized to 1 by default channel = itpp.comm.TDL_Channel(itpp.vec('0.0'), itpp.ivec('0')) channel.set_norm_doppler(norm_doppler) channel_coeff_itpp = itpp.cmat() channel.generate(nrof_samples, channel_coeff_itpp) channel_coeff = np.array(channel_coeff_itpp.get_col(0)) avg_snr = 10**(0.1 * avg_snr_dB) instantaneous_channel_snrs = (np.absolute(channel_coeff)**2) * avg_snr _, nrof_rates = awgn_data['snr_vs_per'].shape instantaneous_blers = [] channel_quality_indices = [] for i in range(nrof_samples): cqi_sinr_error = (itpp.random.randn() - 0.5) * cqi_error_std snr_dB = 10 * np.log10(instantaneous_channel_snrs[i]) instantaneous_blers.append(determine_bler_at_sinr(snr_dB, awgn_data)) channel_quality_indices.append( determine_cqi_from_sinr(snr_dB, packet_sizes, awgn_data, cqi_sinr_error)) return (np.array(instantaneous_blers), np.array(channel_quality_indices))
def propagate_transmit_bits_over_channel(transmit_bits, modulation_order, nrof_resource_blocks, channel_coefficients, noise_variance): nrof_constellation_symbols = int(itpp.math.pow2(modulation_order)) modulator = itpp.comm.QAM(nrof_constellation_symbols) nrof_subcarriers = nrof_resource_blocks * CONFIG.SUBCARRIERS_PER_PRB nrof_symbols = CONFIG.NROF_OFDM_SYMBOLS_PER_SUBFRAME modulated_symbols = modulator.modulate_bits(transmit_bits) if (modulated_symbols.length() != nrof_subcarriers * nrof_symbols): print('Mismatched number of modulated symbols: %d and resource elements: %d'%(modulated_symbols.length(), nrof_subcarriers * nrof_symbols)) ofdm_symbols = itpp.cmat(nrof_subcarriers, nrof_symbols) for i in range(nrof_symbols): temp = modulated_symbols.mid(i * nrof_subcarriers, nrof_subcarriers) ofdm_symbols.set_col(i, itpp.signal.ifft(temp, nrof_subcarriers))#.left(nrof_subcarriers)) noise = itpp.randn_c(nrof_subcarriers, nrof_symbols) * (0.5 * itpp.math.sqrt(noise_variance)) block_channel_coefficients = itpp.repmat(channel_coefficients, 1, nrof_symbols, True) received_symbols = itpp.elem_mult_mat(ofdm_symbols, block_channel_coefficients) + noise compensated_symbols = itpp.elem_div_mat(received_symbols, block_channel_coefficients) # Receiver processing demultiplexed_symbols = itpp.cvec(nrof_subcarriers * nrof_symbols) for i in range(nrof_symbols): temp = compensated_symbols.get_col(i) demultiplexed_symbols.set_subvector(i * nrof_subcarriers, itpp.signal.fft(temp, nrof_subcarriers))#.left(nrof_subcarriers)) # receive_soft_values = modulator.demodulate_soft_bits(demultiplexed_symbols, channel_coefficients, noise_variance, itpp.comm.Soft_Method.LOGMAP) receive_soft_values = modulator.demodulate_soft_bits(demultiplexed_symbols, noise_variance, itpp.comm.Soft_Method.LOGMAP) return receive_soft_values
def generate(self): # Declare a CMAT channel matrix of Nt*Nr size self.channel = itpp.cmat() self.channel.set_size(self.Nt * self.Nr, self.channel_length, False) # Declare another temp CMAT channel_coef_one = itpp.cmat() # Initialise the matrix element wise for i in range(self.Nt): for j in range(self.Nr): # Generate "1" sample values of the channel, # channel_coef_one has one tap per column self.tdl_channels[i * self.Nr + j].generate( 1, channel_coef_one) for l in range(self.channel_length): self.channel.set(i * self.Nr + j, l, channel_coef_one(0, l))
def multiplex_symbols(nrof_ofdm_symbols_per_frame, nrof_subcarriers, constellation_symbols): nrof_frames = int(constellation_symbols.length() / (nrof_subcarriers * nrof_ofdm_symbols_per_frame)) frame_symbols = cmat(nrof_subcarriers * nrof_ofdm_symbols_per_frame, nrof_frames) frame_symbols.clear() # Pre-allocate vector to store frame symbols for efficiency current_frame_symbols = cvec(nrof_subcarriers * nrof_ofdm_symbols_per_frame) for frame_index in range(nrof_frames): current_frame_symbols.clear() for ofdm_symbol_index in range(nrof_ofdm_symbols_per_frame): read_index = frame_index * nrof_subcarriers * nrof_ofdm_symbols_per_frame + ofdm_symbol_index * nrof_subcarriers current_frame_symbols.set_subvector( ofdm_symbol_index * nrof_subcarriers, (nrof_subcarriers**0.5) * ifft(constellation_symbols.mid(read_index, nrof_subcarriers))) frame_symbols.set_col(frame_index, current_frame_symbols) return frame_symbols
def simulate(transport_block_size, modorder, nrof_subcarriers, snr_db, channel_coeff_freq_domain_np): channel_coeff_freq_domain_str = ';'.join([ ' '.join([ str(c).replace('j', 'i').replace('(', '').replace(')', '') for c in r ]) for r in channel_coeff_freq_domain_np ]) channel_coeff_freq_domain = itpp.cmat(channel_coeff_freq_domain_str) nrof_subframe_ofdm_symbols = 12 #--------- TRANSMITTER PROCESSING ---------- # Generate random transmit bits for subframe nrof_frames = channel_coeff_freq_domain.cols() info_bits_uncoded = itpp.random.randb( transport_block_size * nrof_frames) # bmat[block_size, nrof_samples] # Channel encode the transmit data bits info_bits_encoded = codec.encode(transport_block_size, info_bits_uncoded) encoded_block_size = int(info_bits_encoded.length() / nrof_frames) interleaver_bin = itpp.comm.sequence_interleaver_bin(encoded_block_size) interleaver_bin.randomize_interleaver_sequence() interleaver_double = itpp.comm.sequence_interleaver_double( encoded_block_size) interleaver_double.set_interleaver_sequence( interleaver_bin.get_interleaver_sequence()) info_bits_interleaved = interleaver_bin.interleave(info_bits_encoded) # Rate match the encoded bits transmit_block_size = int(nrof_subcarriers * nrof_subframe_ofdm_symbols * modorder) info_bits_rate_matched = codec.rate_match( transmit_block_size, encoded_block_size)(info_bits_interleaved) # Modulate the rate matched bits info_symbols_modulated = modem.modulate_bits(modorder, info_bits_rate_matched) # Obtain the OFDM frequency-domain signal transmit_signal_freq_domain = ofdm.multiplex_symbols( nrof_subframe_ofdm_symbols, nrof_subcarriers, info_symbols_modulated) #--------- CHANNEL EFFECTS ---------- # Apply the channel to the transmitted signal received_signal_freq_domain = itpp.elem_mult_mat( transmit_signal_freq_domain, channel_coeff_freq_domain) # Add receiver noise noise_std_dev = np.sqrt( 1.0 / pow(10, 0.1 * snr_db)) # Signal and channel power is normalized to 1 received_signal_freq_domain_noisy = received_signal_freq_domain + noise_std_dev * itpp.randn_c( received_signal_freq_domain.rows(), received_signal_freq_domain.cols()) #--------- RECEIVER PROCESSING ---------- # Remove the effect of channel received_signal_freq_domain_compensated = itpp.elem_div_mat( received_signal_freq_domain_noisy, channel_coeff_freq_domain) # Obtain the time-domain symbols received_symbols_modulated = ofdm.de_multiplex_symbols( nrof_subframe_ofdm_symbols, nrof_subcarriers, received_signal_freq_domain_compensated) # Demodulate the received symbols according to the modulation order received_soft_values = modem.demodulate_soft_values( modorder, noise_std_dev * noise_std_dev, received_symbols_modulated) # De-rate match the received soft values received_soft_values_de_rate_matched = codec.de_rate_match( transmit_block_size, encoded_block_size)(received_soft_values) received_soft_values_deinterleaved = interleaver_double.deinterleave( received_soft_values_de_rate_matched, 0) # Channel decode the data bits according to the code rate received_bits_decoded = codec.decode(transport_block_size, received_soft_values_deinterleaved) # Count block errors bler, block_success = error_counter(info_bits_uncoded, received_bits_decoded, transport_block_size) # print 'bler', bler logging.info('SNR:%0.2f dB, BLER: %0.4f' % (snr_db, bler)) # channel_to_noise_ratio = channel_coeff_freq_domain.elem_div(noise_realization) return (bler, block_success)