Merge remote-tracking branch 'origin/fix-simplify-prach-nrue' into integration_2026_w03 (!3791)
fix array lenght errors, k variable wrapping threshold. Make the code smaller and more efficient generate_nr_prach() has several errors coming from replace int16_t by c16_t, and also older error in k wrapping at the end of the symbol the code is also ridiculously complex, wasting memory and cpu time in intermediate useless buffers and headache usage of memmove()
This commit is contained in:
@@ -199,14 +199,26 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL)
|
||||
AssertFatal(1==0,"Invalid numerology index %d", mu);
|
||||
}
|
||||
|
||||
if(fp->threequarter_fs)
|
||||
fp->ofdm_symbol_size = 3 * 128;
|
||||
else
|
||||
fp->ofdm_symbol_size = 4 * 128;
|
||||
// Start with FFT size 512
|
||||
fp->ofdm_symbol_size = 512;
|
||||
|
||||
while(fp->ofdm_symbol_size < N_RB_DL * 12)
|
||||
// Choose the right FFT size for the BW
|
||||
while(fp->ofdm_symbol_size < N_RB_DL * NR_NB_SC_PER_RB)
|
||||
fp->ofdm_symbol_size <<= 1;
|
||||
|
||||
// Do 3/4 sampling
|
||||
if (fp->threequarter_fs) {
|
||||
const uint16_t threeq_fft_size = fp->ofdm_symbol_size * 3 / 4;
|
||||
if (threeq_fft_size < (N_RB_DL * NR_NB_SC_PER_RB)) {
|
||||
// 3/4 sampling FFT size not enough
|
||||
warn_higher_threequarter_fs(N_RB_DL, fp->numerology_index);
|
||||
// Choose 2 times 3/4 sampling
|
||||
fp->ofdm_symbol_size = threeq_fft_size << 1;
|
||||
} else {
|
||||
fp->ofdm_symbol_size = threeq_fft_size;
|
||||
}
|
||||
}
|
||||
|
||||
fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2);
|
||||
fp->nb_prefix_samples = fp->ofdm_symbol_size / 128 * 9;
|
||||
fp->nb_prefix_samples0 = fp->ofdm_symbol_size / 128 * (9 + (1 << mu));
|
||||
|
||||
@@ -58,34 +58,19 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
fapi_nr_config_request_t *nrUE_config = &ue->nrUE_config;
|
||||
fapi_nr_ul_config_prach_pdu *prach_pdu = &ue->prach_vars[gNB_id]->prach_pdu;
|
||||
|
||||
uint8_t Mod_id, fd_occasion, preamble_index, restricted_set, not_found;
|
||||
uint16_t rootSequenceIndex, prach_fmt_id, NCS, preamble_offset = 0;
|
||||
const uint16_t *prach_root_sequence_map;
|
||||
uint16_t preamble_shift = 0, preamble_index0, n_shift_ra, n_shift_ra_bar, d_start=INT16_MAX, numshift, N_ZC, u, offset, offset2, first_nonzero_root_idx;
|
||||
c16_t prach[(4688 + 4 * 24576) * 2] __attribute__((aligned(32))) = {0};
|
||||
c16_t prachF_tmp[(4688 + 4 * 24576) * 4] __attribute__((aligned(32))) = {0};
|
||||
|
||||
int Ncp = 0;
|
||||
int prach_start, prach_sequence_length, prach_len, dftlen, mu, n_ra_prb, k, prachStartSymbol;
|
||||
|
||||
fd_occasion = prach_pdu->num_ra;
|
||||
prach_len = 0;
|
||||
dftlen = 0;
|
||||
first_nonzero_root_idx = 0;
|
||||
int16_t amp = prach_pdu->prach_tx_power;
|
||||
c16_t *prachF = prachF_tmp;
|
||||
Mod_id = ue->Mod_id;
|
||||
prach_sequence_length = nrUE_config->prach_config.prach_sequence_length;
|
||||
N_ZC = (prach_sequence_length == 0) ? 839:139;
|
||||
mu = nrUE_config->prach_config.prach_sub_c_spacing;
|
||||
restricted_set = prach_pdu->restricted_set;
|
||||
rootSequenceIndex = prach_pdu->root_seq_id;
|
||||
n_ra_prb = nrUE_config->prach_config.num_prach_fd_occasions_list[fd_occasion].k1,//prach_pdu->freq_msg1;
|
||||
NCS = prach_pdu->num_cs;
|
||||
prach_fmt_id = prach_pdu->prach_format;
|
||||
preamble_index = prach_pdu->ra_PreambleIndex;
|
||||
k = 12*n_ra_prb - 6*fp->N_RB_UL;
|
||||
prachStartSymbol = prach_pdu->prach_start_symbol;
|
||||
const int fd_occasion = prach_pdu->num_ra;
|
||||
const int16_t amp = prach_pdu->prach_tx_power;
|
||||
const int prach_sequence_length = nrUE_config->prach_config.prach_sequence_length;
|
||||
const int N_ZC = (prach_sequence_length == 0) ? 839 : 139;
|
||||
const int mu = nrUE_config->prach_config.prach_sub_c_spacing;
|
||||
const int restricted_set = prach_pdu->restricted_set;
|
||||
const int rootSequenceIndex = prach_pdu->root_seq_id;
|
||||
const int n_ra_prb = nrUE_config->prach_config.num_prach_fd_occasions_list[fd_occasion].k1; // prach_pdu->freq_msg1;
|
||||
const int NCS = prach_pdu->num_cs;
|
||||
const int prach_fmt_id = prach_pdu->prach_format;
|
||||
const int preamble_index = prach_pdu->ra_PreambleIndex;
|
||||
int k = 12 * n_ra_prb - 6 * fp->N_RB_UL;
|
||||
const int prachStartSymbol = prach_pdu->prach_start_symbol;
|
||||
|
||||
LOG_D(PHY,"Generate NR PRACH %d.%d\n", frame, slot);
|
||||
|
||||
@@ -97,6 +82,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
nrUE_config->prach_config.root_seq_computed = 1;
|
||||
}
|
||||
|
||||
int prach_start;
|
||||
if (prachStartSymbol == 0) {
|
||||
prach_start = 0;
|
||||
} else if (fp->slots_per_subframe == 1) {
|
||||
@@ -122,29 +108,30 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
* NOTE: Restricted set type B is not implemented
|
||||
*************************************************************************/
|
||||
|
||||
prach_root_sequence_map = (prach_sequence_length == 0) ? prach_root_sequence_map_0_3 : prach_root_sequence_map_abc;
|
||||
|
||||
const uint16_t *prach_root_sequence_map =
|
||||
(prach_sequence_length == 0) ? prach_root_sequence_map_0_3 : prach_root_sequence_map_abc;
|
||||
int preamble_offset, preamble_shift = 0, first_nonzero_root_idx = 0;
|
||||
if (restricted_set == 0) {
|
||||
// This is the relative offset (for unrestricted case) in the root sequence table (5.7.2-4 from 36.211) for the given preamble index
|
||||
preamble_offset = ((NCS==0)? preamble_index : (preamble_index/(N_ZC/NCS)));
|
||||
preamble_offset = NCS == 0 ? preamble_index : preamble_index / (N_ZC / NCS);
|
||||
// This is the \nu corresponding to the preamble index
|
||||
preamble_shift = (NCS==0)? 0 : (preamble_index % (N_ZC/NCS));
|
||||
preamble_shift = NCS == 0 ? 0 : preamble_index % (N_ZC / NCS);
|
||||
preamble_shift *= NCS;
|
||||
} else { // This is the high-speed case
|
||||
|
||||
#ifdef NR_PRACH_DEBUG
|
||||
LOG_I(PHY, "PRACH [UE %d] High-speed mode, NCS %d\n", Mod_id, NCS);
|
||||
#endif
|
||||
#ifdef NR_PRACH_DEBUG
|
||||
LOG_I(PHY, "PRACH [UE %d] High-speed mode, NCS %d\n", ue->Mod_id, NCS);
|
||||
#endif
|
||||
|
||||
not_found = 1;
|
||||
uint16_t nr_du[NR_PRACH_SEQ_LEN_L - 1];
|
||||
nr_fill_du(N_ZC, prach_root_sequence_map, nr_du);
|
||||
preamble_index0 = preamble_index;
|
||||
int preamble_index0 = preamble_index;
|
||||
// set preamble_offset to initial rootSequenceIndex and look if we need more root sequences for this
|
||||
// preamble index and find the corresponding cyclic shift
|
||||
preamble_offset = 0; // relative rootSequenceIndex;
|
||||
|
||||
while (not_found == 1) {
|
||||
bool not_found = true;
|
||||
while (not_found) {
|
||||
// current root depending on rootSequenceIndex and preamble_offset
|
||||
int index = (rootSequenceIndex + preamble_offset) % N_ZC;
|
||||
uint16_t n_group_ra = 0;
|
||||
@@ -157,8 +144,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
DevAssert( index < sizeof(prach_root_sequence_map_abc) / sizeof(prach_root_sequence_map_abc[0]) );
|
||||
}
|
||||
|
||||
u = prach_root_sequence_map[index];
|
||||
|
||||
int u = prach_root_sequence_map[index];
|
||||
int n_shift_ra, d_start = INT16_MAX, n_shift_ra_bar;
|
||||
if ( (nr_du[u]<(N_ZC/3)) && (nr_du[u]>=NCS) ) {
|
||||
n_shift_ra = nr_du[u]/NCS;
|
||||
d_start = (nr_du[u]<<1) + (n_shift_ra * NCS);
|
||||
@@ -175,13 +162,12 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
}
|
||||
|
||||
// This is the number of cyclic shifts for the current root u
|
||||
numshift = (n_shift_ra*n_group_ra) + n_shift_ra_bar;
|
||||
|
||||
int numshift = (n_shift_ra * n_group_ra) + n_shift_ra_bar;
|
||||
if (numshift>0 && preamble_index0==preamble_index)
|
||||
first_nonzero_root_idx = preamble_offset;
|
||||
|
||||
if (preamble_index0 < numshift) {
|
||||
not_found = 0;
|
||||
not_found = false;
|
||||
preamble_shift = (d_start * (preamble_index0/n_shift_ra)) + ((preamble_index0%n_shift_ra)*NCS);
|
||||
|
||||
} else { // skip to next rootSequenceIndex and recompute parameters
|
||||
@@ -193,23 +179,22 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
|
||||
// now generate PRACH signal
|
||||
#ifdef NR_PRACH_DEBUG
|
||||
if (NCS>0)
|
||||
LOG_I(PHY, "PRACH [UE %d] generate PRACH in frame.slot %d.%d for RootSeqIndex %d, Preamble Index %d, PRACH Format %s, NCS %d (N_ZC %d): Preamble_offset %d, Preamble_shift %d msg1 frequency start %d\n",
|
||||
Mod_id,
|
||||
frame,
|
||||
slot,
|
||||
rootSequenceIndex,
|
||||
preamble_index,
|
||||
prachfmt[prach_fmt_id],
|
||||
NCS,
|
||||
N_ZC,
|
||||
preamble_offset,
|
||||
preamble_shift,
|
||||
n_ra_prb);
|
||||
#endif
|
||||
|
||||
// nsymb = (frame_parms->Ncp==0) ? 14:12;
|
||||
// subframe_offset = (unsigned int)frame_parms->ofdm_symbol_size*slot*nsymb;
|
||||
if (NCS > 0)
|
||||
LOG_I(PHY,
|
||||
"PRACH [UE %d] generate PRACH in frame.slot %d.%d for RootSeqIndex %d, Preamble Index %d, PRACH Format %s, NCS %d "
|
||||
"(N_ZC %d): Preamble_offset %d, Preamble_shift %d msg1 frequency start %d\n",
|
||||
ue->Mod_id,
|
||||
frame,
|
||||
slot,
|
||||
rootSequenceIndex,
|
||||
preamble_index,
|
||||
prachfmt[prach_fmt_id],
|
||||
NCS,
|
||||
N_ZC,
|
||||
preamble_offset,
|
||||
preamble_shift,
|
||||
n_ra_prb);
|
||||
#endif
|
||||
|
||||
const unsigned int K = get_prach_K(prach_sequence_length, prach_fmt_id, fp->numerology_index, mu);
|
||||
const uint8_t kbar = get_PRACH_k_bar(mu, fp->numerology_index);
|
||||
@@ -223,7 +208,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
LOG_I(PHY,
|
||||
"PRACH [UE %d] in frame.slot %d.%d, placing PRACH in position %d, Msg1/MsgA-Preamble frequency start %d (k1 %d), "
|
||||
"preamble_offset %d, first_nonzero_root_idx %d, preambleIndex = %d\n",
|
||||
Mod_id,
|
||||
ue->Mod_id,
|
||||
frame,
|
||||
slot,
|
||||
k * 2,
|
||||
@@ -234,155 +219,96 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
prach_pdu->ra_PreambleIndex);
|
||||
|
||||
// Ncp and dftlen here is given in terms of T_s wich is 30.72MHz sampling
|
||||
int dftlen, Ncp;
|
||||
if (prach_sequence_length == 0) {
|
||||
switch (prach_fmt_id) {
|
||||
case 0:
|
||||
Ncp = 3168;
|
||||
dftlen = 24576;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
Ncp = 21024;
|
||||
dftlen = 24576;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Ncp = 4688;
|
||||
dftlen = 24576;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
Ncp = 3168;
|
||||
dftlen = 6144;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1 == 0, "Illegal PRACH format %d for sequence length 839\n", prach_fmt_id);
|
||||
break;
|
||||
}
|
||||
AssertFatal(prach_fmt_id >= 0 && prach_fmt_id <= 3, "Unknown PRACH format ID %d for sequence length 839\n", prach_fmt_id);
|
||||
const int ncp[4] = {3168, 21024, 4688, 3168};
|
||||
const int dft[4] = {24576, 24576, 24576, 6144};
|
||||
Ncp = ncp[prach_fmt_id];
|
||||
dftlen = dft[prach_fmt_id];
|
||||
} else {
|
||||
switch (prach_fmt_id) {
|
||||
case 4: //A1
|
||||
Ncp = 288 >> mu;
|
||||
break;
|
||||
|
||||
case 5: //A2
|
||||
Ncp = 576 >> mu;
|
||||
break;
|
||||
|
||||
case 6: //A3
|
||||
Ncp = 864 >> mu;
|
||||
break;
|
||||
|
||||
case 7: //B1
|
||||
Ncp = 216 >> mu;
|
||||
break;
|
||||
|
||||
/*
|
||||
case 4: //B2
|
||||
Ncp = 360 >> mu;
|
||||
break;
|
||||
|
||||
case 5: //B3
|
||||
Ncp = 504 >> mu;
|
||||
break;
|
||||
*/
|
||||
|
||||
case 8: //B4
|
||||
Ncp = 936 >> mu;
|
||||
break;
|
||||
|
||||
case 9: //C0
|
||||
Ncp = 1240 >> mu;
|
||||
break;
|
||||
|
||||
case 10: //C2
|
||||
Ncp = 2048 >> mu;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1==0,"Unknown PRACH format ID %d\n", prach_fmt_id);
|
||||
break;
|
||||
}
|
||||
AssertFatal(prach_fmt_id >= 4 && prach_fmt_id <= 10, "Unknown PRACH format ID %d\n", prach_fmt_id);
|
||||
const int ncp[7] = {288, 576, 864, 216, 936, 1240, 2048};
|
||||
Ncp = ncp[prach_fmt_id - 4] >> mu;
|
||||
dftlen = 2048 >> mu;
|
||||
}
|
||||
|
||||
//actually what we should be checking here is how often the current prach crosses a 0.5ms boundary. I am not quite sure for which paramter set this would be the case, so I will ignore it for now and just check if the prach starts on a 0.5ms boundary
|
||||
if(fp->numerology_index == 0) {
|
||||
// actually what we should be checking here is how often the current prach crosses a 0.5ms boundary. I am not quite sure for
|
||||
// which paramter set this would be the case, so I will ignore it for now and just check if the prach starts on a 0.5ms boundary
|
||||
if (fp->numerology_index == 0) {
|
||||
if (prachStartSymbol == 0 || prachStartSymbol == 7)
|
||||
Ncp += 16;
|
||||
}
|
||||
else {
|
||||
if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0)
|
||||
} else {
|
||||
if (slot % (fp->slots_per_subframe / 2) == 0 && prachStartSymbol == 0)
|
||||
Ncp += 16;
|
||||
}
|
||||
|
||||
switch(fp->samples_per_subframe) {
|
||||
case 7680:
|
||||
// 5 MHz @ 7.68 Ms/s
|
||||
Ncp >>= 2;
|
||||
dftlen >>= 2;
|
||||
break;
|
||||
switch (fp->samples_per_subframe) {
|
||||
case 7680:
|
||||
// 5 MHz @ 7.68 Ms/s
|
||||
Ncp >>= 2;
|
||||
dftlen >>= 2;
|
||||
break;
|
||||
|
||||
case 15360:
|
||||
// 10, 15 MHz @ 15.36 Ms/s
|
||||
Ncp >>= 1;
|
||||
dftlen >>= 1;
|
||||
break;
|
||||
case 15360:
|
||||
// 10, 15 MHz @ 15.36 Ms/s
|
||||
Ncp >>= 1;
|
||||
dftlen >>= 1;
|
||||
break;
|
||||
|
||||
case 23040:
|
||||
// 20 MHz @ 23.04 Ms/s
|
||||
Ncp = (Ncp * 3) / 4;
|
||||
dftlen = (dftlen * 3) / 4;
|
||||
break;
|
||||
case 23040:
|
||||
// 20 MHz @ 23.04 Ms/s
|
||||
Ncp = (Ncp * 3) / 4;
|
||||
dftlen = (dftlen * 3) / 4;
|
||||
break;
|
||||
|
||||
case 30720:
|
||||
// 20, 25, 30 MHz @ 30.72 Ms/s
|
||||
break;
|
||||
case 30720:
|
||||
// 20, 25, 30 MHz @ 30.72 Ms/s
|
||||
break;
|
||||
|
||||
case 46080:
|
||||
// 40 MHz @ 46.08 Ms/s
|
||||
Ncp = (Ncp*3)/2;
|
||||
dftlen = (dftlen*3)/2;
|
||||
break;
|
||||
case 46080:
|
||||
// 40 MHz @ 46.08 Ms/s
|
||||
Ncp = (Ncp * 3) / 2;
|
||||
dftlen = (dftlen * 3) / 2;
|
||||
break;
|
||||
|
||||
case 61440:
|
||||
// 40, 50, 60 MHz @ 61.44 Ms/s
|
||||
Ncp <<= 1;
|
||||
dftlen <<= 1;
|
||||
break;
|
||||
case 61440:
|
||||
// 40, 50, 60 MHz @ 61.44 Ms/s
|
||||
Ncp <<= 1;
|
||||
dftlen <<= 1;
|
||||
break;
|
||||
|
||||
case 92160:
|
||||
// 50, 60, 70, 80, 90 MHz @ 92.16 Ms/s
|
||||
Ncp *= 3;
|
||||
dftlen *= 3;
|
||||
break;
|
||||
case 92160:
|
||||
// 50, 60, 70, 80, 90 MHz @ 92.16 Ms/s
|
||||
Ncp *= 3;
|
||||
dftlen *= 3;
|
||||
break;
|
||||
|
||||
case 122880:
|
||||
// 70, 80, 90, 100 MHz @ 122.88 Ms/s
|
||||
Ncp <<= 2;
|
||||
dftlen <<= 2;
|
||||
break;
|
||||
case 122880:
|
||||
// 70, 80, 90, 100 MHz @ 122.88 Ms/s
|
||||
Ncp <<= 2;
|
||||
dftlen <<= 2;
|
||||
break;
|
||||
|
||||
case 184320:
|
||||
// 100 MHz @ 184.32 Ms/s
|
||||
Ncp = Ncp*6;
|
||||
dftlen = dftlen*6;
|
||||
break;
|
||||
case 184320:
|
||||
// 100 MHz @ 184.32 Ms/s
|
||||
Ncp = Ncp * 6;
|
||||
dftlen = dftlen * 6;
|
||||
break;
|
||||
|
||||
case 245760:
|
||||
// 200 MHz @ 245.76 Ms/s
|
||||
Ncp <<= 3;
|
||||
dftlen <<= 3;
|
||||
break;
|
||||
case 245760:
|
||||
// 200 MHz @ 245.76 Ms/s
|
||||
Ncp <<= 3;
|
||||
dftlen <<= 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu);
|
||||
default:
|
||||
AssertFatal(1 == 0, "sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu);
|
||||
}
|
||||
|
||||
#ifdef NR_PRACH_DEBUG
|
||||
LOG_I(PHY, "PRACH [UE %d] Ncp %d, dftlen %d \n", Mod_id, Ncp, dftlen);
|
||||
#endif
|
||||
#ifdef NR_PRACH_DEBUG
|
||||
LOG_I(PHY, "PRACH [UE %d] Ncp %d, dftlen %d \n", ue->Mod_id, Ncp, dftlen);
|
||||
#endif
|
||||
|
||||
/********************************************************
|
||||
*
|
||||
@@ -390,7 +316,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
* to compute quantized roots of unity ru(n) = 32767 * exp j*[ (2 * PI * n) / N_ZC ]
|
||||
*
|
||||
* In compute_prach_seq:
|
||||
* to calculate Xu = DFT xu = xu (inv_u*k) * Xu[0] (This is a Zadoff-Chou sequence property: DFT ZC sequence is another ZC sequence)
|
||||
* to calculate Xu = DFT xu = xu (inv_u*k) * Xu[0] (This is a Zadoff-Chou sequence property: DFT ZC sequence is another ZC
|
||||
* sequence)
|
||||
*
|
||||
* In generate_prach:
|
||||
* to do the cyclic-shifted DFT by multiplying Xu[k] * ru[k*preamble_shift] as:
|
||||
@@ -398,118 +325,55 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
c16_t *Xu = ue->X_u[preamble_offset - first_nonzero_root_idx];
|
||||
const c16_t *Xu = ue->X_u[preamble_offset - first_nonzero_root_idx];
|
||||
|
||||
#if defined (PRACH_WRITE_OUTPUT_DEBUG)
|
||||
LOG_M("X_u.m", "X_u", (int16_t*)ue->X_u[preamble_offset-first_nonzero_root_idx], N_ZC, 1, 1);
|
||||
#endif
|
||||
LOG_M("X_u.m", "X_u", (int16_t *)ue->X_u[preamble_offset - first_nonzero_root_idx], N_ZC, 1, 1);
|
||||
#endif
|
||||
|
||||
for (offset=0,offset2=0; offset<N_ZC; offset++,offset2+=preamble_shift) {
|
||||
c16_t prach[dftlen] __attribute__((aligned(32)));
|
||||
{
|
||||
c16_t prachF[dftlen] __attribute__((aligned(32)));
|
||||
memset(prachF, 0, sizeof(prachF));
|
||||
for (int offset = 0, offset2 = 0; offset < N_ZC; offset++, offset2 += preamble_shift) {
|
||||
if (offset2 >= N_ZC)
|
||||
offset2 -= N_ZC;
|
||||
const c16_t Xu_t = c16xmulConstShift(Xu[offset], amp, 15);
|
||||
const double w = 2 * M_PI * (double)offset2 / N_ZC;
|
||||
const c16_t ru = {.r = (int16_t)(floor(32767.0 * cos(w))), .i = (int16_t)(floor(32767.0 * sin(w)))};
|
||||
const c16_t p = c16mulShift(Xu_t, ru, 15);
|
||||
prachF[k++] = p;
|
||||
if (k == dftlen)
|
||||
k = 0;
|
||||
}
|
||||
|
||||
if (offset2 >= N_ZC)
|
||||
offset2 -= N_ZC;
|
||||
const c16_t Xu_t = c16xmulConstShift(Xu[offset], amp, 15);
|
||||
const double w = 2 * M_PI * (double)offset2 / N_ZC;
|
||||
const c16_t ru = {.r = (int16_t)(floor(32767.0 * cos(w))), .i = (int16_t)(floor(32767.0 * sin(w)))};
|
||||
const c16_t p = c16mulShift(Xu_t, ru, 15);
|
||||
prachF[k++] = p;
|
||||
|
||||
if (k * 2 == dftlen)
|
||||
k = 0;
|
||||
}
|
||||
|
||||
#if defined (PRACH_WRITE_OUTPUT_DEBUG)
|
||||
#if defined(PRACH_WRITE_OUTPUT_DEBUG)
|
||||
LOG_M("prachF.m", "prachF", &prachF[1804], 1024, 1, 1);
|
||||
LOG_M("Xu.m", "Xu", Xu, N_ZC, 1, 1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// This is after cyclic prefix
|
||||
c16_t *prach2 = prach + Ncp;
|
||||
// This is after cyclic prefix
|
||||
const idft_size_idx_t idft_size = get_idft(dftlen);
|
||||
idft(idft_size, (int16_t *)prachF, (int16_t *)prach, 1);
|
||||
memmove(prach2, prach, (dftlen << 2));
|
||||
}
|
||||
|
||||
if (prach_sequence_length == 0) {
|
||||
if (prach_fmt_id == 0) {
|
||||
// here we have | empty | Prach |
|
||||
memcpy(prach, prach + dftlen, (Ncp << 2));
|
||||
// here we have | Prefix | Prach |
|
||||
prach_len = dftlen + Ncp;
|
||||
} else if (prach_fmt_id == 1) {
|
||||
// here we have | empty | Prach | empty |
|
||||
memcpy(prach2 + dftlen, prach2, (dftlen << 2));
|
||||
// here we have | empty | Prach | Prach |
|
||||
memcpy(prach, prach + dftlen * 2, (Ncp << 2));
|
||||
// here we have | Prefix | Prach | Prach |
|
||||
prach_len = (dftlen * 2) + Ncp;
|
||||
} else if (prach_fmt_id == 2 || prach_fmt_id == 3) {
|
||||
// here we have | empty | Prach | empty | empty | empty |
|
||||
memcpy(prach2 + dftlen, prach2, (dftlen << 2));
|
||||
// here we have | empty | Prach | Prach | empty | empty |
|
||||
memcpy(prach2 + dftlen * 2, prach2, (dftlen << 3));
|
||||
// here we have | empty | Prach | Prach | Prach | Prach |
|
||||
memcpy(prach, prach + dftlen * 4, (Ncp << 2));
|
||||
// here we have | Prefix | Prach | Prach | Prach | Prach |
|
||||
prach_len = (dftlen * 4) + Ncp;
|
||||
}
|
||||
} else { // short PRACH sequence
|
||||
if (prach_fmt_id == 9) {
|
||||
// here we have | empty | Prach |
|
||||
memcpy(prach, prach + dftlen, (Ncp << 2));
|
||||
// here we have | Prefix | Prach |
|
||||
prach_len = (dftlen*1)+Ncp;
|
||||
} else if (prach_fmt_id == 4 || prach_fmt_id == 7) {
|
||||
// here we have | empty | Prach | empty |
|
||||
memcpy(prach2 + dftlen, prach2, (dftlen << 2));
|
||||
// here we have | empty | Prach | Prach |
|
||||
memcpy(prach, prach+(dftlen<<1), (Ncp<<2));
|
||||
// here we have | Prefix | Prach | Prach |
|
||||
prach_len = (dftlen*2)+Ncp;
|
||||
} else if (prach_fmt_id == 5 || prach_fmt_id == 10) { // 4xdftlen
|
||||
// here we have | empty | Prach | empty | empty | empty |
|
||||
memcpy(prach2 + dftlen, prach2, (dftlen << 2));
|
||||
// here we have | empty | Prach | Prach | empty | empty |
|
||||
memcpy(prach2 + dftlen * 2, prach2, (dftlen << 3));
|
||||
// here we have | empty | Prach | Prach | Prach | Prach |
|
||||
memcpy(prach, prach + dftlen, (Ncp << 2));
|
||||
// here we have | Prefix | Prach | Prach | Prach | Prach |
|
||||
prach_len = (dftlen*4)+Ncp;
|
||||
} else if (prach_fmt_id == 6) { // 6xdftlen
|
||||
// here we have | empty | Prach | empty | empty | empty | empty | empty |
|
||||
memcpy(prach2 + dftlen, prach2, (dftlen << 2));
|
||||
// here we have | empty | Prach | Prach | empty | empty | empty | empty |
|
||||
memcpy(prach2 + dftlen * 2, prach2, (dftlen << 3));
|
||||
// here we have | empty | Prach | Prach | Prach | Prach | empty | empty |
|
||||
memcpy(prach2 + dftlen * 4, prach2, (dftlen << 3));
|
||||
// here we have | empty | Prach | Prach | Prach | Prach | Prach | Prach |
|
||||
memcpy(prach, prach + dftlen, (Ncp << 2));
|
||||
// here we have | Prefix | Prach | Prach | Prach | Prach | Prach | Prach |
|
||||
prach_len = (dftlen*6)+Ncp;
|
||||
} else if (prach_fmt_id == 8) { // 12xdftlen
|
||||
// here we have | empty | Prach | empty | empty | empty | empty | empty | empty | empty | empty | empty | empty | empty |
|
||||
memcpy(prach2 + dftlen, prach2, (dftlen << 2));
|
||||
// here we have | empty | Prach | Prach | empty | empty | empty | empty | empty | empty | empty | empty | empty | empty |
|
||||
memcpy(prach2 + dftlen * 2, prach2, (dftlen << 3));
|
||||
// here we have | empty | Prach | Prach | Prach | Prach | empty | empty | empty | empty | empty | empty | empty | empty |
|
||||
memcpy(prach2 + dftlen * 4, prach2, (dftlen << 3));
|
||||
// here we have | empty | Prach | Prach | Prach | Prach | Prach | Prach | empty | empty | empty | empty | empty | empty |
|
||||
memcpy(prach2 + dftlen * 6, prach2, (dftlen << 2) * 6);
|
||||
// here we have | empty | Prach | Prach | Prach | Prach | Prach | Prach | Prach | Prach | Prach | Prach | Prach | Prach |
|
||||
memcpy(prach, prach + dftlen, (Ncp << 2));
|
||||
// here we have | Prefix | Prach | Prach | Prach | Prach | Prach | Prach | Prach | Prach | Prach | Prach | Prach | Prach |
|
||||
prach_len = (dftlen*12)+Ncp;
|
||||
}
|
||||
c16_t *out = txData[0] + prach_start;
|
||||
memcpy(out, prach + dftlen - Ncp, Ncp * sizeof(*prach));
|
||||
out += Ncp;
|
||||
const int copies[11] = {1, 2, 4, 4, 2, 4, 6, 2, 12, 1, 4};
|
||||
DevAssert(prach_fmt_id < sizeofArray(copies));
|
||||
for (int i = 0; i < copies[prach_fmt_id]; i++) {
|
||||
memcpy(out, prach, dftlen * sizeof(*prach));
|
||||
out += dftlen;
|
||||
}
|
||||
|
||||
#ifdef NR_PRACH_DEBUG
|
||||
LOG_I(PHY, "PRACH [UE %d] N_RB_UL %d prach_start %d, prach_len %d\n", Mod_id, fp->N_RB_UL, prach_start, prach_len);
|
||||
#endif
|
||||
|
||||
memcpy(txData[0] + prach_start, prach, sizeof(c16_t) * prach_len);
|
||||
|
||||
#ifdef PRACH_WRITE_OUTPUT_DEBUG
|
||||
LOG_M("prach_tx0.m", "prachtx0", prach + (Ncp << 1), prach_len - Ncp, 1, 1);
|
||||
LOG_M("Prach_txsig.m", "txs", (int16_t *)(&txdata[0][prach_start]), 2 * (prach_start + prach_len), 1, 1)
|
||||
LOG_I(PHY,
|
||||
"PRACH [UE %d] N_RB_UL %d prach_start %d, prach_len %d\n",
|
||||
ue->Mod_id,
|
||||
fp->N_RB_UL,
|
||||
prach_start,
|
||||
out - (txData[0] + prach_start));
|
||||
#endif
|
||||
|
||||
return signal_energy((int *)prach, 256);
|
||||
|
||||
Reference in New Issue
Block a user