rjw | 6c1fd8f | 2022-11-30 14:33:01 +0800 | [diff] [blame] | 1 | import math
|
| 2 | import numpy as np
|
| 3 |
|
| 4 | class IqSignals:
|
| 5 | def __init__(self, params, NidCell, is_TDD):
|
| 6 | pi = math.pi
|
| 7 |
|
| 8 | ## ------------------ PSS INIT (B) ------------------
|
| 9 | print "\n"
|
| 10 | print "Generating Primary Synchronization Signal....",
|
| 11 |
|
| 12 | #Compute physical layer identity Nid2 in range [0:2]
|
| 13 | Nid2 = NidCell % 3
|
| 14 |
|
| 15 | #Identify root index from Nid2
|
| 16 | if(Nid2 == 0):
|
| 17 | u = 25
|
| 18 | elif(Nid2 == 1):
|
| 19 | u = 29
|
| 20 | elif(Nid2 == 2):
|
| 21 | u = 34
|
| 22 |
|
| 23 | self.PSS_TD_complex = [0] * 62
|
| 24 |
|
| 25 | # The PSS is a sequence of complex symbols, 62 symbols long
|
| 26 | for n in xrange(0, 62):
|
| 27 |
|
| 28 | if n <= 30:
|
| 29 | phase_coeff = -pi*u*(n+1)*n/63.0
|
| 30 | else:
|
| 31 | phase_coeff = -pi*u*(n+1)*(n+2)/63.0
|
| 32 |
|
| 33 | self.PSS_TD_complex[n] = np.vectorize(complex)(math.cos(phase_coeff),math.sin(phase_coeff))
|
| 34 |
|
| 35 | self.PSS_TD_complex_pad = [0] * 72
|
| 36 | self.PSS_TD_complex_pad[5:67] = self.PSS_TD_complex
|
| 37 | self.PSS_TD_complex_pad_fftSize_wShift = [0] * params.PSS_FFT_size
|
| 38 | self.PSS_TD_complex_pad_fftSize_wShift[1:37] = self.PSS_TD_complex_pad[36:]
|
| 39 | self.PSS_TD_complex_pad_fftSize_wShift[params.PSS_FFT_size-36:] = self.PSS_TD_complex_pad[:36]
|
| 40 | self.PSS_TD_complex_pad_fftSize_wShift_ifft = np.fft.ifft(self.PSS_TD_complex_pad_fftSize_wShift)
|
| 41 |
|
| 42 | #Define indices location of PSS in half-frame resource grid (TODO!)
|
| 43 |
|
| 44 | print "Done."
|
| 45 | ## ------------------ PSS INIT (B) ------------------
|
| 46 |
|
| 47 | ## See http://www.sharetechnote.com/html/Handbook_LTE_SSS.html < Matlab code for SSS Generation >
|
| 48 | ## ------------------ SSS INIT (B) ------------------
|
| 49 | #Compute physical layer cell-identity group Nid1 ( range LTE:[0:167], NR:[0:335])
|
| 50 | print "Generating Secondary Synchronization Signal....",
|
| 51 |
|
| 52 | #Compute physical layer cell-identity group Nid1 ( range [0:167] )
|
| 53 | Nid1 = math.floor(NidCell/3.0)
|
| 54 |
|
| 55 | # Define indices m0 and m1
|
| 56 | q_prime = math.floor(Nid1/30.0)
|
| 57 | q_ = math.floor( (Nid1 + 0.5*q_prime*(q_prime+1.0)) / 30.0 )
|
| 58 | m_prime = Nid1 + q_*(q_+1)/2
|
| 59 | m0 = int(m_prime % 31)
|
| 60 | m1 = int((m0 + math.floor(m_prime/31.0) + 1.0) % 31)
|
| 61 |
|
| 62 | #print ['q_prime',q_prime,'q_',q_,'m_prime',m_prime,'m0',m0,'m1',m1]
|
| 63 |
|
| 64 |
|
| 65 | # **** Generate sequences s0^(m0)[n] and s1^(m1)[n] ****
|
| 66 | # Compute m-sequence s_tilde
|
| 67 | x_s = [0] * 31
|
| 68 | x_s[4] = 1
|
| 69 | for i_ in xrange(0,26):
|
| 70 | x_s[i_+5] = (x_s[i_+2] + x_s[i_]) % 2
|
| 71 |
|
| 72 | # Matlab: s_tilde = 1 - 2*x_s
|
| 73 | s_tilde = [1-2*x for x in x_s]
|
| 74 |
|
| 75 | # Compute s0_m0 and s1_m1 from s_tilde with different cyclic shifts
|
| 76 | self.s0_ = [0] * 31
|
| 77 | self.s1_ = [0] * 31
|
| 78 | for i_ in xrange(0,31):
|
| 79 | self.s0_[i_] = s_tilde[(i_ + m0) % 31]
|
| 80 | self.s1_[i_] = s_tilde[(i_ + m1) % 31]
|
| 81 |
|
| 82 |
|
| 83 | # **** Generate scrambling sequences c0[n] and c1[n] ****
|
| 84 | # Compute m-sequence c_tilde
|
| 85 | x_c = [0] * 31
|
| 86 | x_c[4] = 1
|
| 87 | for i_ in xrange(0,26):
|
| 88 | x_c[i_+5] = (x_c[i_+3] + x_c[i_]) % 2
|
| 89 |
|
| 90 | # Matlab: c_tilde = 1 - 2*x_c
|
| 91 | c_tilde = [1-2*x for x in x_c]
|
| 92 |
|
| 93 | # Compute c0_ and c1_ from c_tilde with different cyclic shifts
|
| 94 | self.c0_ = [0] * 31
|
| 95 | self.c1_ = [0] * 31
|
| 96 | for i_ in xrange(0,31):
|
| 97 | self.c0_[i_] = c_tilde[(i_ + Nid2) % 31]
|
| 98 | self.c1_[i_] = c_tilde[(i_ + Nid2 + 3) % 31]
|
| 99 |
|
| 100 |
|
| 101 | # **** Generate scrambling sequences z1^(m0)[n] and z1^(m1)[n] ****
|
| 102 | # Compute m-sequence z_tilde
|
| 103 | x_z = [0] * 31
|
| 104 | x_z[4] = 1
|
| 105 | for i_ in xrange(0,26):
|
| 106 | x_z[i_+5] = (x_z[i_+4] + x_z[i_+2] + x_z[i_+1] + x_z[i_]) % 2
|
| 107 |
|
| 108 | # Matlab: z_tilde = 1 - 2*x_z
|
| 109 | z_tilde = [1-2*x for x in x_z]
|
| 110 |
|
| 111 | # Compute z1_m0 and z1_m1 from z_tilde with different cyclic shifts
|
| 112 | self.z1_m0 = [0] * 31
|
| 113 | self.z1_m1 = [0] * 31
|
| 114 | for i_ in xrange(0,31):
|
| 115 | self.z1_m0[i_] = z_tilde[(i_ + (m0%8)) % 31]
|
| 116 | self.z1_m1[i_] = z_tilde[(i_ + (m1%8)) % 31]
|
| 117 |
|
| 118 |
|
| 119 | #Define indices location of SSS in half-frame resource grid
|
| 120 | self.SSS_k_index_start = 0 -31 + 12*params.numRB/2
|
| 121 | self.SSS_k_index_end = 61 -31 + 12*params.numRB/2
|
| 122 |
|
| 123 | if (is_TDD == 1):
|
| 124 | self.SSS_l_column = 13
|
| 125 | else:
|
| 126 | self.SSS_l_column = 5
|
| 127 |
|
| 128 | print "Done."
|
| 129 | ## ------------------ SSS INIT (E) ------------------
|
| 130 |
|
| 131 | ########################################################################
|
| 132 | # ------------------ SYNCHRONIZATION SIGNALS INIT (E) -----------------#
|
| 133 | ########################################################################
|
| 134 |
|
| 135 |
|
| 136 |
|
| 137 | ################################################################################
|
| 138 | # ------------------ CELL-SPECIFIC REFERENCE SIGNALS INIT (B) -----------------#
|
| 139 | ################################################################################
|
| 140 | print "Generating Cell-Specific Reference Signals....",
|
| 141 |
|
| 142 | N_c = 1600
|
| 143 | NmaxRB = 110
|
| 144 | seqLength = 4*NmaxRB
|
| 145 | real_vec = np.zeros((2*NmaxRB,20*(params.Ncp_type+6)))
|
| 146 | imag_vec = np.zeros((2*NmaxRB,20*(params.Ncp_type+6)))
|
| 147 | self.CSRS_mat = np.vectorize(complex)(real_vec,imag_vec)
|
| 148 |
|
| 149 | for kk in xrange(0, 20):
|
| 150 |
|
| 151 | for ii in xrange(0,(params.Ncp_type+6)):
|
| 152 |
|
| 153 | c_init = 1024 * ( 7 * ( kk + 1 ) + 1 + ii ) * (2*NidCell+1) + 2*NidCell + params.Ncp_type
|
| 154 |
|
| 155 | #print c_init
|
| 156 |
|
| 157 | # x_1 initialization
|
| 158 | x_1 = [0] * (seqLength + N_c + 31)
|
| 159 | x_1[0] = 1
|
| 160 | x_2 = [0] * (seqLength + N_c + 31)
|
| 161 |
|
| 162 | # # Initializes x_2 using c_init (converts to binary form)
|
| 163 | # i = 0;
|
| 164 | # while (c_init >= 1):
|
| 165 | # x_2[i] = c_init % 2
|
| 166 | # c_init = math.floor(c_init / 2)
|
| 167 | # i = i +1
|
| 168 |
|
| 169 | # Initializes x_2 using c_init (converts to binary form)
|
| 170 | i = 30;
|
| 171 | while (c_init >= 1):
|
| 172 | x2_val = math.floor(c_init/math.pow(2,i))
|
| 173 | x_2[i] = x2_val
|
| 174 | c_init = c_init - x2_val*math.pow(2,i)
|
| 175 | i = i - 1
|
| 176 |
|
| 177 | # Generation of x_1[n] and x_2[n]
|
| 178 | for n in xrange(0,seqLength + N_c):
|
| 179 | x_1[n+31] = (x_1[n+3] + x_1[n]) % 2
|
| 180 | x_2[n+31] = (x_2[n+3] + x_2[n+2] + x_2[n+1] + x_2[n]) % 2
|
| 181 |
|
| 182 | # Generation of Gold PN sequence: c_seq[n] = (x_1[n+Nc] + x_2[n+Nc])mod2
|
| 183 | c_seq = np.zeros((seqLength,1))
|
| 184 | for nn in xrange(0,seqLength):
|
| 185 | c_seq[nn] = (x_1[nn+N_c] + x_2[nn + N_c]) % 2
|
| 186 |
|
| 187 | # Generation of QPSK-based CSRS
|
| 188 | ref_sig_seq = np.sqrt(0.5) * np.vectorize(complex)(1-2*c_seq[0:4*NmaxRB:2],1-2*c_seq[1:4*NmaxRB:2])
|
| 189 | self.CSRS_mat[:,kk*(6+params.Ncp_type)+ii] = ref_sig_seq[:,0]
|
| 190 | self.NmaxRB = NmaxRB
|
| 191 | print "Done."
|