ofdm_test.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. import itertools
  2. import math
  3. import numpy as np
  4. from models.custom_layers import OpticalChannel
  5. from matplotlib import pyplot as plt
  6. # mapping_table = np.asarray([-3 - 3j, -3 - 1j, -3 + 3j, -3 + 1j,
  7. # -1 - 3j, -1 - 1j, -1 + 3j, -1 + 1j,
  8. # 3 - 3j, 3 - 1j, 3 + 3j, 3 + 1j,
  9. # 1 - 3j, 1 - 1j, 1 + 3j, 1 + 1j])
  10. mapping_table = np.asarray([-1 - 1j, -1 + 1j, 1 - 1j, 1 + 1j])
  11. BANDWIDTH = 50e9
  12. CARDINALITY = mapping_table.shape[0]
  13. DISPERSION_FACTOR = -21.7 * 1e-24
  14. FIBER_LENGTH = 5
  15. FIBER_LENGTH_STDDEV = 0
  16. RX_STDDEV = 0.01
  17. SIG_AVG = 0.5
  18. ENOB = 10
  19. # Number of OFDM symbols to simulate
  20. OFDM_N = 100
  21. # Number of OFDM subcarriers
  22. K = 32
  23. # length of the cyclic prefix: 25% of the block
  24. CP = K // 4
  25. # number of pilot carriers per OFDM block
  26. P = 0
  27. # The known value each pilot transmits
  28. pilotValue = 3 + 3j
  29. # DC offset used to ensure all values are positive
  30. DC_OFFSET = 50
  31. DC_OFFSET = np.asarray([DC_OFFSET])
  32. SHOW_PLOTS = True
  33. bits_per_symbol = int(math.log(CARDINALITY, 2))
  34. bits_lst = [list(i) for i in itertools.product([0, 1], repeat=bits_per_symbol)]
  35. # Set true to view plot of symbols as IQ plot
  36. if False:
  37. for idx, sym in enumerate(mapping_table):
  38. plt.plot(sym.real, sym.imag, 'bo')
  39. plt.text(sym.real, sym.imag + 0.2, str(bits_lst[idx])[1:-1], ha='center')
  40. plt.title('Symbols used in each subcarrier')
  41. plt.xlabel('I')
  42. plt.ylabel('Q')
  43. plt.xlim(-4, 4)
  44. plt.ylim(-4, 4)
  45. plt.show()
  46. tx_stream = []
  47. tx_syms = []
  48. for ofdm_sym in range(OFDM_N):
  49. print(ofdm_sym)
  50. # All subcarriers used
  51. allCarriers = np.arange(K)
  52. # Identifying pilot carriers (and adding final subcarrier as a pilot for convenience)
  53. if P == 0:
  54. pilotCarriers = np.asarray([-1])
  55. else:
  56. pilotCarriers = allCarriers[::K // P]
  57. pilotCarriers = np.hstack([pilotCarriers, np.array([allCarriers[-1]])])
  58. # P = P + 1
  59. # Removing pilot carriers to obtain data carriers
  60. dataCarriers = np.delete(allCarriers, pilotCarriers)
  61. # if SHOW_PLOTS:
  62. # f = np.fft.fftfreq(allCarriers.shape[0], d=1 / BANDWIDTH)
  63. # plt.plot(f[1]*pilotCarriers, np.zeros_like(pilotCarriers), 'bo', label='pilot')
  64. # plt.plot(f[1]*dataCarriers, np.zeros_like(dataCarriers), 'ro', label='data')
  65. # plt.show()
  66. # Generate random symbols as integers and then map symbol values onto them
  67. input_syms = np.random.randint(CARDINALITY, size=len(dataCarriers))
  68. tx_syms.append(input_syms)
  69. mapped_syms = mapping_table[input_syms]
  70. # Generate the upper sideband of the OFDM symbol
  71. enc_stream_upper_f = np.zeros(K, dtype=complex)
  72. enc_stream_upper_f[pilotCarriers] = pilotValue
  73. enc_stream_upper_f[dataCarriers] = mapped_syms
  74. # Generate the lower sideband of the OFDM symbol
  75. enc_stream_lower_f = np.conjugate(np.flip(enc_stream_upper_f))
  76. # Combine the two sidebands with a DC offset to ensure values are always positive
  77. enc_stream_f = np.concatenate((DC_OFFSET, enc_stream_upper_f, enc_stream_lower_f), axis=None)
  78. # if SHOW_PLOTS:
  79. # f = np.fft.fftfreq(enc_stream_f.shape[0], d=1/BANDWIDTH)
  80. # plt.plot(f, np.real(enc_stream_f), 'x')
  81. # plt.plot(f, np.imag(enc_stream_f), 'x')
  82. # # plt.xlim(-0.5e10, 0.5e10)
  83. # plt.show()
  84. # Take the inverse fourier transform
  85. enc_stream_t = np.fft.ifft(enc_stream_f)
  86. # if SHOW_PLOTS:
  87. # t = np.arange(len(enc_stream_t))*(1/BANDWIDTH)
  88. # plt.plot(t, np.real(enc_stream_t))
  89. # plt.plot(t, np.imag(enc_stream_t))
  90. # plt.show()
  91. # Take the real part to be transmitted via the channel
  92. tx_stream.append(np.real(enc_stream_t))
  93. tx_stream = np.asarray(tx_stream).flatten()
  94. tx_syms = np.asarray(tx_syms).flatten()
  95. optical_channel = OpticalChannel(fs=BANDWIDTH,
  96. dispersion_factor=DISPERSION_FACTOR,
  97. fiber_length=FIBER_LENGTH,
  98. fiber_length_stddev=FIBER_LENGTH_STDDEV,
  99. lpf_cutoff=BANDWIDTH / 2,
  100. rx_stddev=RX_STDDEV,
  101. sig_avg=SIG_AVG,
  102. enob=ENOB,
  103. num_of_samples=len(tx_stream))
  104. rx_stream = optical_channel(tx_stream)
  105. rx_stream_f = np.fft.fft(np.sqrt(rx_stream))
  106. freq = np.fft.fftfreq(rx_stream_f.shape[0], d=1/BANDWIDTH)
  107. # compensation = np.exp(-0.5j*DISPERSION_FACTOR*FIBER_LENGTH*np.square(2*math.pi*freq))
  108. # rx_compensated_f = rx_stream_f * compensation
  109. rx_compensated_t = np.fft.ifft(rx_stream_f)
  110. rx_reshaped_t = rx_compensated_t.reshape((OFDM_N, -1))
  111. if False:
  112. t = np.arange(len(tx_stream))*(1/BANDWIDTH)
  113. plt.plot(t, tx_stream)
  114. plt.plot(t, 2+np.sqrt(rx_stream))
  115. plt.plot(t, rx_compensated_t-2)
  116. plt.show()
  117. rx_syms = []
  118. # chan_num = 2
  119. for chan_num in range(K):
  120. i = 0
  121. for sym in rx_reshaped_t:
  122. sym_f = np.fft.fft(sym)
  123. freq = np.fft.fftfreq(sym_f.shape[0], d=1 / BANDWIDTH)
  124. # compensation = np.exp(-0.5j * DISPERSION_FACTOR * FIBER_LENGTH * np.square(2 * math.pi * freq))
  125. sym_f = sym_f
  126. upper_f = sym_f[1:1 + K]
  127. if SHOW_PLOTS:
  128. # for x in upper_f:
  129. if tx_syms[i+chan_num] == 0:
  130. plt.plot(np.real(upper_f[chan_num]), np.imag(upper_f[chan_num]), 'bo')
  131. elif tx_syms[i+chan_num] == 1:
  132. plt.plot(np.real(upper_f[chan_num]), np.imag(upper_f[chan_num]), 'ro')
  133. elif tx_syms[i+chan_num] == 2:
  134. plt.plot(np.real(upper_f[chan_num]), np.imag(upper_f[chan_num]), 'go')
  135. elif tx_syms[i+chan_num] == 3:
  136. plt.plot(np.real(upper_f[chan_num]), np.imag(upper_f[chan_num]), 'mo')
  137. i += K
  138. plt.title((str(chan_num) + " rot"))
  139. plt.show()
  140. # for sym in rx_reshaped_t:
  141. # sym_f = np.fft.fft(sym)
  142. # upper_f = sym_f[1:1 + K]
  143. #
  144. # if SHOW_PLOTS:
  145. # for x in upper_f:
  146. # if tx_syms[i] == 0:
  147. # plt.plot(np.real(x), np.imag(x), 'bo')
  148. # elif tx_syms[i] == 1:
  149. # plt.plot(np.real(x), np.imag(x), 'ro')
  150. # elif tx_syms[i] == 2:
  151. # plt.plot(np.real(x), np.imag(x), 'go')
  152. # elif tx_syms[i] == 3:
  153. # plt.plot(np.real(x), np.imag(x), 'mo')
  154. # # plt.plot(np.real(mapping_table[tx_syms[i]]), np.imag(mapping_table[tx_syms[i]]), 'ro')
  155. # # plt.text(np.real(sym), np.imag(sym), str(i), ha='center')
  156. # # plt.text(np.real(mapping_table[tx_syms[i]]), np.imag(mapping_table[tx_syms[i]]), str(i), ha='center')
  157. # i += 1
  158. plt.show()