def decode(block_length, bits): '''Create the codec instance and set parameters''' codec = turbo_codec() '''Prepare codec parameters''' gen_sequence = '11,13' gen = ivec(gen_sequence) constraint_length = 4 codec.set_parameters(gen, gen, constraint_length, ivec()) codec.set_interleaver(_interleaver_sequence(block_length)) '''Encode with the given code rate and bitarray comprising uncoded bits''' '''Generate and return decoded bits''' decoded_bits = bvec() codec.decode(bits, decoded_bits, bvec()) return decoded_bits
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 deinterleave_and_channel_decode_symbols(symbols, interleaver_sequence): sequence_interleaver_d = itpp.comm.sequence_interleaver_double( symbols.length()) sequence_interleaver_d.set_interleaver_sequence(interleaver_sequence) deinterleaved_symbols = sequence_interleaver_d.deinterleave(symbols, keepzeroes=0) conv_code = itpp.comm.Convolutional_Code() generators = itpp.ivec(3) generators[0] = 91 # Octal 0133 generators[1] = 101 # Octal 0145 generators[2] = 125 # Octal 0175 constraint_length = 7 conv_code.set_generator_polynomials(generators, constraint_length) decoded_bits = conv_code.decode(deinterleaved_symbols) # turbo_codec = itpp.comm.turbo_codec() # # gen = itpp.ivec('11, 13') # constraint_length = 4 # # turbo_codec.set_parameters(gen, gen, constraint_length, itpp.ivec()) # turbo_interleaver_sequence = generate_turbo_internal_interleaver_sequence(symbols.length()) # turbo_codec.set_interleaver(turbo_interleaver_sequence) # # decoded_bits = itpp.bvec() # turbo_codec.decode(symbols, decoded_bits, itpp.bvec()) return decoded_bits
def channel_encode_and_interleave_bits(bits): conv_code = itpp.comm.Convolutional_Code() generators = itpp.ivec(3) generators[0] = 91 # Octal 0133 generators[1] = 101 # Octal 0145 generators[2] = 125 # Octal 0175 constraint_length = 7 conv_code.set_generator_polynomials(generators, constraint_length) coded_bits = conv_code.encode(bits) # turbo_codec = itpp.comm.turbo_codec() # # gen = itpp.ivec('11, 13') # constraint_length = 4 # # turbo_codec.set_parameters(gen, gen, constraint_length, itpp.ivec()) # turbo_interleaver_sequence = generate_turbo_internal_interleaver_sequence(bits.length()) # turbo_codec.set_interleaver(turbo_interleaver_sequence) # # coded_bits = itpp.bvec() # turbo_codec.encode(bits, coded_bits) sequence_interleaver_b = itpp.comm.sequence_interleaver_bin( coded_bits.length()) sequence_interleaver_b.randomize_interleaver_sequence() interleaved_bits = sequence_interleaver_b.interleave(coded_bits) return (interleaved_bits, sequence_interleaver_b.get_interleaver_sequence())
def block_error_ratio_hamming_awgn(snr_db, block_size): mapping_k_m = { 4: 3 } # Mapping from k (block size) to m. m = 3 implies (7,4) code m = mapping_k_m[block_size] '''Hamming encoder and decoder instance''' hamm = itpp.comm.hamming_code(m) n = pow(2, m) - 1 # channel use rate = float(block_size) / float(n) '''Generate random bits''' nrof_bits = 10000 * block_size source_bits = itpp.randb(nrof_bits) '''Encode the bits''' encoded_bits = hamm.encode(source_bits) '''Modulate the bits''' modulator_ = itpp.comm.modulator_2d() constellation = itpp.cvec('-1+0i, 1+0i') symbols = itpp.ivec('0, 1') modulator_.set(constellation, symbols) tx_signal = modulator_.modulate_bits(encoded_bits) '''Add the effect of channel to the signal''' noise_variance = 1.0 / (rate * pow(10, 0.1 * snr_db)) noise = itpp.randn_c(tx_signal.length()) noise *= itpp.math.sqrt(noise_variance) rx_signal = tx_signal + noise '''Demodulate the signal''' demodulated_bits = modulator_.demodulate_bits(rx_signal) '''Decode the received bits''' decoded_bits = hamm.decode(demodulated_bits) '''Calculate the block error ratio''' blerc = itpp.comm.BLERC(block_size) blerc.count(source_bits, decoded_bits) return blerc.get_errorrate()
def _interleaver_sequence(block_size): K = block_size '''Get the index of parameters to be used from interleaver table ''' index = 0 if (40 <= K and K <= 512 and (K % 8 == 0)): index = (K - 40) / 8 elif (528 <= K and K <= 1024 and (K % 16 == 0)): index = 60 + ((K - 528) / 16) elif (1056 <= K and K <= 2048 and (K % 32 == 0)): index = 92 + ((K - 1056) / 32) elif (2112 <= K and K <= 6144 and (K % 64 == 0)): index = 124 + ((K - 2112) / 64) else: error_str = 'Invalid interleaver size: ' + str(K) logging.error(error_str) #raise ValueError, error_str '''Get the parameters to generate the interleaver sequence ''' f1 = _TURBO_INTERNAL_INTERLEAVER_TABLE.get(int(index), 1) f2 = _TURBO_INTERNAL_INTERLEAVER_TABLE.get(int(index), 2) '''Mapping from output index 'i' to input index 'PI_i' ''' PI_mapping = lambda i: (f1 * i + f2 * i * i) % K PI = ivec(K) # Placeholder for input indices for i in range(K): PI[i] = PI_mapping(i) return PI
def bit_error_ratio_hamming_awgn(snr_db): '''Hamming encoder and decoder instance''' k = 3 # (7,4) Hamming code hamm = itpp.comm.hamming_code(k) '''Generate random bits''' nrof_bits = k * 100000 source_bits = itpp.random.randb(nrof_bits) '''Encode the bits''' encoded_bits = hamm.encode(source_bits) '''Modulate the bits''' modulator_ = itpp.comm.modulator_1d() constellation = itpp.vec('-1, 1') symbols = itpp.ivec('0, 1') modulator_.set(constellation, symbols) tx_signal = modulator_.modulate_bits(encoded_bits) '''Add the effect of channel to the signal''' noise_variance = 1.0 / (pow(10, 0.1 * snr_db)) noise = itpp.random.randn(tx_signal.length()) noise *= itpp.math.sqrt(noise_variance) rx_signal = tx_signal + noise '''Demodulate the signal''' demodulated_bits = modulator_.demodulate_bits(rx_signal) '''Decode the received bits''' decoded_bits = hamm.decode(demodulated_bits) '''Calculate the bit error ratio''' return itpp.comm.BERC.count_errors(source_bits, decoded_bits, 0, 0, 0) / nrof_bits
def generate_turbo_internal_interleaver_sequence(block_length): f1 = 3 f2 = 10 internal_interleaver_sequence = itpp.ivec(block_length) for i in range(block_length): internal_interleaver_sequence[i] = (f1 * i + f2 * i * i) % block_length return internal_interleaver_sequence
def block_error_ratio_turbo_awgn(snr_db, interleaver_length): '''Create turbo_codec_instance''' codec = itpp.comm.turbo_codec() '''Set codec parameters''' gen = itpp.ivec(2) gen[0] = 11 gen[1] = 13 constraint_length = 4 interleaver = itpp.ivec( '0, 19, 14, 33, 28, 47, 42, 13, 8, 27, 22, 41, 36, 7, 2, 21, 16, 35, 30, 1, 44, 15, 10, 29, 24, 43, 38, 9, 4, 23, 18, 37, 32, 3, 46, 17, 12, 31, 26, 45, 40, 11, 6, 25, 20, 39, 34, 5' ) codec.set_parameters(gen, gen, constraint_length, itpp.ivec()) codec.set_interleaver(interleaver) '''Generate random bits and encode them''' nrof_uncoded_bits = interleaver_length * 1000 uncoded_bits = itpp.random.randb(nrof_uncoded_bits) encoded_bits = itpp.bvec() codec.encode(uncoded_bits, encoded_bits) '''Modulate bits using BPSK''' symbols = itpp.vec('1, -1') bits2symbol = itpp.ivec('0, 1') modulator_ = itpp.comm.modulator_1d(symbols, bits2symbol) tx_signal = modulator_.modulate_bits(encoded_bits) '''Add AWGN noise''' noise_variance = 1.0 / (pow(10, 0.1 * snr_db)) noise = itpp.random.randn(tx_signal.length()) noise *= itpp.math.sqrt(noise_variance) rx_signal = tx_signal + noise '''Demodulate received signal (soft bits, LOGMAP)''' soft_bits = itpp.vec() modulator_.demodulate_soft_bits(rx_signal, noise_variance, soft_bits, itpp.comm.Soft_Method.LOGMAP) '''Turbo decode the soft bits''' decoded_bits = itpp.bvec() codec.decode(soft_bits, decoded_bits, itpp.bvec()) '''Count errors''' blerc = itpp.comm.BLERC(interleaver_length) blerc.count(decoded_bits, uncoded_bits) return blerc.get_errorrate()
def block_error_ratio_uncoded_awgn(snr_db, block_size): '''Generate random bits''' nrof_bits = 3 * 10000 * block_size source_bits = itpp.random.randb(nrof_bits) '''Modulate the bits''' modulator_ = itpp.comm.modulator_1d() constellation = itpp.vec('-1, 1') symbols = itpp.ivec('0, 1') modulator_.set(constellation, symbols) tx_signal = modulator_.modulate_bits(source_bits) '''Add the effect of channel to the signal''' noise_variance = 1.0 / (pow(10, 0.1 * snr_db)) noise = itpp.random.randn(tx_signal.length()) noise *= itpp.math.sqrt(noise_variance) rx_signal = tx_signal + noise '''Demodulate the signal''' demodulated_bits = modulator_.demodulate_bits(rx_signal) '''Calculate the block error ratio''' blerc = itpp.comm.BLERC(block_size) blerc.count(source_bits, demodulated_bits) return blerc.get_errorrate()
def generateRaptorLDPC(numInfoBits, rate, outFilename): """ Generates a left 4-degree regular, random right degree LDPC code with 'numInfoBits' information bits. @param numInfoBits: the number of message bits the LDPC code will handle @param rate: the rate of the LDPC code @param outFilename: filename where the bits will be written """ leftDegree = 4 numVariables = int(numInfoBits / rate) print "numVariables:", numVariables dist = binom(numInfoBits, 1.0 * leftDegree / (numVariables - numInfoBits)) maxRightDegree = int(dist.isf(1e-8)) itRight = itpp.vec(maxRightDegree) for i in xrange(maxRightDegree): itRight[i] = dist.pmf(i+1) itRight[maxRightDegree-1] = itRight[maxRightDegree-1] + 1e-8 itLeft = itpp.vec(leftDegree) for i in xrange(leftDegree-1): itLeft[i] = 0 itLeft[leftDegree - 1] = 1.0 print itLeft H = itpp.LDPC_Parity_Irregular() H.generate(numVariables, itLeft, itRight, "rand", itpp.ivec("150 8")) H.display_stats() print "got code with ", (H.get_nvar() - H.get_ncheck()), " nodes" G = itpp.LDPC_Generator_Systematic(H); C = itpp.LDPC_Code(H, G) C.save_code(outFilename);
def generateRaptorLDPC(numInfoBits, rate, outFilename): """ Generates a left 4-degree regular, random right degree LDPC code with 'numInfoBits' information bits. @param numInfoBits: the number of message bits the LDPC code will handle @param rate: the rate of the LDPC code @param outFilename: filename where the bits will be written """ leftDegree = 4 numVariables = int(numInfoBits / rate) print "numVariables:", numVariables dist = binom(numInfoBits, 1.0 * leftDegree / (numVariables - numInfoBits)) maxRightDegree = int(dist.isf(1e-8)) itRight = itpp.vec(maxRightDegree) for i in xrange(maxRightDegree): itRight[i] = dist.pmf(i + 1) itRight[maxRightDegree - 1] = itRight[maxRightDegree - 1] + 1e-8 itLeft = itpp.vec(leftDegree) for i in xrange(leftDegree - 1): itLeft[i] = 0 itLeft[leftDegree - 1] = 1.0 print itLeft H = itpp.LDPC_Parity_Irregular() H.generate(numVariables, itLeft, itRight, "rand", itpp.ivec("150 8")) H.display_stats() print "got code with ", (H.get_nvar() - H.get_ncheck()), " nodes" G = itpp.LDPC_Generator_Systematic(H) C = itpp.LDPC_Code(H, G) C.save_code(outFilename)