mirror of
https://github.com/jhshi/openofdm.git
synced 2024-12-25 00:11:16 +00:00
176 lines
5.5 KiB
Python
176 lines
5.5 KiB
Python
|
|
# Authors: Veeresh Taranalli <veeresht@gmail.com>
|
|
# License: BSD 3-Clause
|
|
|
|
"""
|
|
============================================
|
|
Channel Models (:mod:`commpy.channels`)
|
|
============================================
|
|
|
|
.. autosummary::
|
|
:toctree: generated/
|
|
|
|
bec -- Binary Erasure Channel.
|
|
bsc -- Binary Symmetric Channel.
|
|
awgn -- Additive White Gaussian Noise Channel.
|
|
|
|
"""
|
|
|
|
from numpy import complex, sum, pi, arange, array, size, shape, real, sqrt
|
|
from numpy import matrix, sqrt, sum, zeros, concatenate, sinc
|
|
from numpy.random import randn, seed, random
|
|
#from scipy.special import gamma, jn
|
|
#from scipy.signal import hamming, convolve, resample
|
|
#from scipy.fftpack import ifft, fftshift, fftfreq
|
|
#from scipy.interpolate import interp1d
|
|
|
|
__all__=['bec', 'bsc', 'awgn']
|
|
|
|
def bec(input_bits, p_e):
|
|
"""
|
|
Binary Erasure Channel.
|
|
|
|
Parameters
|
|
----------
|
|
input_bits : 1D ndarray containing {0, 1}
|
|
Input arrary of bits to the channel.
|
|
|
|
p_e : float in [0, 1]
|
|
Erasure probability of the channel.
|
|
|
|
Returns
|
|
-------
|
|
output_bits : 1D ndarray containing {0, 1}
|
|
Output bits from the channel.
|
|
"""
|
|
output_bits = input_bits.copy()
|
|
output_bits[random(len(output_bits)) <= p_e] = -1
|
|
return output_bits
|
|
|
|
def bsc(input_bits, p_t):
|
|
"""
|
|
Binary Symmetric Channel.
|
|
|
|
Parameters
|
|
----------
|
|
input_bits : 1D ndarray containing {0, 1}
|
|
Input arrary of bits to the channel.
|
|
|
|
p_t : float in [0, 1]
|
|
Transition/Error probability of the channel.
|
|
|
|
Returns
|
|
-------
|
|
output_bits : 1D ndarray containing {0, 1}
|
|
Output bits from the channel.
|
|
"""
|
|
output_bits = input_bits.copy()
|
|
flip_locs = (random(len(output_bits)) <= p_t)
|
|
output_bits[flip_locs] = 1 ^ output_bits[flip_locs]
|
|
return output_bits
|
|
|
|
def awgn(input_signal, snr_dB, rate=1.0):
|
|
"""
|
|
Addditive White Gaussian Noise (AWGN) Channel.
|
|
|
|
Parameters
|
|
----------
|
|
input_signal : 1D ndarray of floats
|
|
Input signal to the channel.
|
|
|
|
snr_dB : float
|
|
Output SNR required in dB.
|
|
|
|
rate : float
|
|
Rate of the a FEC code used if any, otherwise 1.
|
|
|
|
Returns
|
|
-------
|
|
output_signal : 1D ndarray of floats
|
|
Output signal from the channel with the specified SNR.
|
|
"""
|
|
|
|
avg_energy = sum(abs(input_signal) * abs(input_signal))/len(input_signal)
|
|
snr_linear = 10**(snr_dB/10.0)
|
|
noise_variance = avg_energy/(2*rate*snr_linear)
|
|
|
|
if input_signal.dtype == complex:
|
|
noise = (sqrt(noise_variance) * randn(len(input_signal))) + (sqrt(noise_variance) * randn(len(input_signal))*1j)
|
|
else:
|
|
noise = sqrt(2*noise_variance) * randn(len(input_signal))
|
|
|
|
output_signal = input_signal + noise
|
|
|
|
return output_signal
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# =============================================================================
|
|
# Incomplete code to implement fading channels
|
|
# =============================================================================
|
|
|
|
#def doppler_jakes(max_doppler, filter_length):
|
|
|
|
# fs = 32.0*max_doppler
|
|
# ts = 1/fs
|
|
# m = arange(0, filter_length/2)
|
|
|
|
# Generate the Jakes Doppler Spectrum impulse response h[m]
|
|
# h_jakes_left = (gamma(3.0/4) *
|
|
# pow((max_doppler/(pi*abs((m-(filter_length/2))*ts))), 0.25) *
|
|
# jn(0.25, 2*pi*max_doppler*abs((m-(filter_length/2))*ts)))
|
|
# h_jakes_center = array([(gamma(3.0/4)/gamma(5.0/4)) * pow(max_doppler, 0.5)])
|
|
# h_jakes = concatenate((h_jakes_left[0:filter_length/2-1],
|
|
# h_jakes_center, h_jakes_left[::-1]))
|
|
# h_jakes = h_jakes*hamming(filter_length)
|
|
# h_jakes = h_jakes/(sum(h_jakes**2)**0.5)
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# jakes_psd_right = (1/(pi*max_doppler*(1-(freqs/max_doppler)**2)**0.5))**0.5
|
|
# zero_pad = zeros([(fft_size-filter_length)/2, ])
|
|
# jakes_psd = concatenate((zero_pad, jakes_psd_right[::-1],
|
|
# jakes_psd_right, zero_pad))
|
|
#print size(jakes_psd)
|
|
# jakes_impulse = real(fftshift(ifft(jakes_psd, fft_size)))
|
|
# h_jakes = jakes_impulse[(fft_size-filter_length)/2 + 1 : (fft_size-filter_length)/2 + filter_length + 1]
|
|
# h_jakes = h_jakes*hamming(filter_length)
|
|
# h_jakes = h_jakes/(sum(h_jakes**2)**0.5)
|
|
# -----------------------------------------------------------------------------
|
|
# return h_jakes
|
|
|
|
#def rayleigh_channel(ts_input, max_doppler, block_length, path_gains,
|
|
# path_delays):
|
|
|
|
# fs_input = 1.0/ts_input
|
|
# fs_channel = 32.0*max_doppler
|
|
# ts_channel = 1.0/fs_channel
|
|
# interp_factor = fs_input/fs_channel
|
|
# channel_length = block_length/interp_factor
|
|
# n1 = -10
|
|
# n2 = 10
|
|
|
|
# filter_length = 1024
|
|
|
|
# Generate the Jakes Doppler Spectrum impulse response h[m]
|
|
# h_jakes = doppler_jakes(max_doppler, filter_length)
|
|
|
|
# Generate the complex Gaussian Random Process
|
|
# g_var = 0.5
|
|
# gain_process = zeros([len(path_gains), block_length], dtype=complex)
|
|
# delay_process = zeros([n2+1-n1, len(path_delays)])
|
|
# for k in xrange(len(path_gains)):
|
|
# g = (g_var**0.5) * (randn(channel_length) + 1j*randn(channel_length))
|
|
# g_filt = convolve(g, h_jakes, mode='same')
|
|
# g_filt_interp = resample(g_filt, block_length)
|
|
# gain_process[k,:] = pow(10, (path_gains[k]/10.0)) * g_filt_interp
|
|
# delay_process[:,k] = sinc((path_delays[k]/ts_input) - arange(n1, n2+1))
|
|
|
|
#channel_matrix = 0
|
|
# channel_matrix = matrix(delay_process)*matrix(gain_process)
|
|
|
|
# return channel_matrix, gain_process, h_jakes
|