| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- import itertools
- import math
- import numpy as np
- from models.custom_layers import OpticalChannel
- from matplotlib import pyplot as plt
- # mapping_table = np.asarray([-3 - 3j, -3 - 1j, -3 + 3j, -3 + 1j,
- # -1 - 3j, -1 - 1j, -1 + 3j, -1 + 1j,
- # 3 - 3j, 3 - 1j, 3 + 3j, 3 + 1j,
- # 1 - 3j, 1 - 1j, 1 + 3j, 1 + 1j])
- mapping_table = np.asarray([-1 - 1j, -1 + 1j, 1 - 1j, 1 + 1j])
- BANDWIDTH = 50e9
- CARDINALITY = mapping_table.shape[0]
- DISPERSION_FACTOR = -21.7 * 1e-24
- FIBER_LENGTH = 5
- FIBER_LENGTH_STDDEV = 0
- RX_STDDEV = 0.01
- SIG_AVG = 0.5
- ENOB = 10
- # Number of OFDM symbols to simulate
- OFDM_N = 100
- # Number of OFDM subcarriers
- K = 32
- # length of the cyclic prefix: 25% of the block
- CP = K // 4
- # number of pilot carriers per OFDM block
- P = 0
- # The known value each pilot transmits
- pilotValue = 3 + 3j
- # DC offset used to ensure all values are positive
- DC_OFFSET = 50
- DC_OFFSET = np.asarray([DC_OFFSET])
- SHOW_PLOTS = True
- bits_per_symbol = int(math.log(CARDINALITY, 2))
- bits_lst = [list(i) for i in itertools.product([0, 1], repeat=bits_per_symbol)]
- # Set true to view plot of symbols as IQ plot
- if False:
- for idx, sym in enumerate(mapping_table):
- plt.plot(sym.real, sym.imag, 'bo')
- plt.text(sym.real, sym.imag + 0.2, str(bits_lst[idx])[1:-1], ha='center')
- plt.title('Symbols used in each subcarrier')
- plt.xlabel('I')
- plt.ylabel('Q')
- plt.xlim(-4, 4)
- plt.ylim(-4, 4)
- plt.show()
- tx_stream = []
- tx_syms = []
- for ofdm_sym in range(OFDM_N):
- print(ofdm_sym)
- # All subcarriers used
- allCarriers = np.arange(K)
- # Identifying pilot carriers (and adding final subcarrier as a pilot for convenience)
- if P == 0:
- pilotCarriers = np.asarray([-1])
- else:
- pilotCarriers = allCarriers[::K // P]
- pilotCarriers = np.hstack([pilotCarriers, np.array([allCarriers[-1]])])
- # P = P + 1
- # Removing pilot carriers to obtain data carriers
- dataCarriers = np.delete(allCarriers, pilotCarriers)
- # if SHOW_PLOTS:
- # f = np.fft.fftfreq(allCarriers.shape[0], d=1 / BANDWIDTH)
- # plt.plot(f[1]*pilotCarriers, np.zeros_like(pilotCarriers), 'bo', label='pilot')
- # plt.plot(f[1]*dataCarriers, np.zeros_like(dataCarriers), 'ro', label='data')
- # plt.show()
- # Generate random symbols as integers and then map symbol values onto them
- input_syms = np.random.randint(CARDINALITY, size=len(dataCarriers))
- tx_syms.append(input_syms)
- mapped_syms = mapping_table[input_syms]
- # Generate the upper sideband of the OFDM symbol
- enc_stream_upper_f = np.zeros(K, dtype=complex)
- enc_stream_upper_f[pilotCarriers] = pilotValue
- enc_stream_upper_f[dataCarriers] = mapped_syms
- # Generate the lower sideband of the OFDM symbol
- enc_stream_lower_f = np.conjugate(np.flip(enc_stream_upper_f))
- # Combine the two sidebands with a DC offset to ensure values are always positive
- enc_stream_f = np.concatenate((DC_OFFSET, enc_stream_upper_f, enc_stream_lower_f), axis=None)
- # if SHOW_PLOTS:
- # f = np.fft.fftfreq(enc_stream_f.shape[0], d=1/BANDWIDTH)
- # plt.plot(f, np.real(enc_stream_f), 'x')
- # plt.plot(f, np.imag(enc_stream_f), 'x')
- # # plt.xlim(-0.5e10, 0.5e10)
- # plt.show()
- # Take the inverse fourier transform
- enc_stream_t = np.fft.ifft(enc_stream_f)
- # if SHOW_PLOTS:
- # t = np.arange(len(enc_stream_t))*(1/BANDWIDTH)
- # plt.plot(t, np.real(enc_stream_t))
- # plt.plot(t, np.imag(enc_stream_t))
- # plt.show()
- # Take the real part to be transmitted via the channel
- tx_stream.append(np.real(enc_stream_t))
- tx_stream = np.asarray(tx_stream).flatten()
- tx_syms = np.asarray(tx_syms).flatten()
- optical_channel = OpticalChannel(fs=BANDWIDTH,
- dispersion_factor=DISPERSION_FACTOR,
- fiber_length=FIBER_LENGTH,
- fiber_length_stddev=FIBER_LENGTH_STDDEV,
- lpf_cutoff=BANDWIDTH / 2,
- rx_stddev=RX_STDDEV,
- sig_avg=SIG_AVG,
- enob=ENOB,
- num_of_samples=len(tx_stream))
- rx_stream = optical_channel(tx_stream)
- rx_stream_f = np.fft.fft(np.sqrt(rx_stream))
- freq = np.fft.fftfreq(rx_stream_f.shape[0], d=1/BANDWIDTH)
- # compensation = np.exp(-0.5j*DISPERSION_FACTOR*FIBER_LENGTH*np.square(2*math.pi*freq))
- # rx_compensated_f = rx_stream_f * compensation
- rx_compensated_t = np.fft.ifft(rx_stream_f)
- rx_reshaped_t = rx_compensated_t.reshape((OFDM_N, -1))
- if False:
- t = np.arange(len(tx_stream))*(1/BANDWIDTH)
- plt.plot(t, tx_stream)
- plt.plot(t, 2+np.sqrt(rx_stream))
- plt.plot(t, rx_compensated_t-2)
- plt.show()
- rx_syms = []
- # chan_num = 2
- for chan_num in range(K):
- i = 0
- for sym in rx_reshaped_t:
- sym_f = np.fft.fft(sym)
- freq = np.fft.fftfreq(sym_f.shape[0], d=1 / BANDWIDTH)
- # compensation = np.exp(-0.5j * DISPERSION_FACTOR * FIBER_LENGTH * np.square(2 * math.pi * freq))
- sym_f = sym_f
- upper_f = sym_f[1:1 + K]
- if SHOW_PLOTS:
- # for x in upper_f:
- if tx_syms[i+chan_num] == 0:
- plt.plot(np.real(upper_f[chan_num]), np.imag(upper_f[chan_num]), 'bo')
- elif tx_syms[i+chan_num] == 1:
- plt.plot(np.real(upper_f[chan_num]), np.imag(upper_f[chan_num]), 'ro')
- elif tx_syms[i+chan_num] == 2:
- plt.plot(np.real(upper_f[chan_num]), np.imag(upper_f[chan_num]), 'go')
- elif tx_syms[i+chan_num] == 3:
- plt.plot(np.real(upper_f[chan_num]), np.imag(upper_f[chan_num]), 'mo')
- i += K
- plt.title((str(chan_num) + " rot"))
- plt.show()
- # for sym in rx_reshaped_t:
- # sym_f = np.fft.fft(sym)
- # upper_f = sym_f[1:1 + K]
- #
- # if SHOW_PLOTS:
- # for x in upper_f:
- # if tx_syms[i] == 0:
- # plt.plot(np.real(x), np.imag(x), 'bo')
- # elif tx_syms[i] == 1:
- # plt.plot(np.real(x), np.imag(x), 'ro')
- # elif tx_syms[i] == 2:
- # plt.plot(np.real(x), np.imag(x), 'go')
- # elif tx_syms[i] == 3:
- # plt.plot(np.real(x), np.imag(x), 'mo')
- # # plt.plot(np.real(mapping_table[tx_syms[i]]), np.imag(mapping_table[tx_syms[i]]), 'ro')
- # # plt.text(np.real(sym), np.imag(sym), str(i), ha='center')
- # # plt.text(np.real(mapping_table[tx_syms[i]]), np.imag(mapping_table[tx_syms[i]]), str(i), ha='center')
- # i += 1
- plt.show()
|