|
|
|
@@ -85,6 +85,382 @@ void nr_pusch_codeword_scrambling(uint8_t *in, uint32_t size, uint32_t Nid, uint
|
|
|
|
|
nr_codeword_scrambling(in, size, 0, Nid, n_RNTI, out);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
The function pointers are set once before calling the mapping funcion for
|
|
|
|
|
all symbols based on different parameters. Then the mapping is done for
|
|
|
|
|
each symbol by calling the function pointers.
|
|
|
|
|
*/
|
|
|
|
|
static void (*map_dmrs_ptr)(const unsigned int, const c16_t *, c16_t *);
|
|
|
|
|
static void (*map_data_dmrs_ptr)(const unsigned int num_cdm_no_data, const c16_t *, c16_t *);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
The following set of functions map dmrs and/or data REs in one RB based on
|
|
|
|
|
configuration of DMRS type, number of CDM groups with no data and delta.
|
|
|
|
|
For all other combinations of the parameters not present below is not
|
|
|
|
|
applicable.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
DMRS mapping in a RB for Type 1.
|
|
|
|
|
Mapping as in TS 38.211 6.4.1.1.3 k = 4n + 2k^prime + delta
|
|
|
|
|
*/
|
|
|
|
|
static void map_dmrs_type1_cdm1_rb(const unsigned int delta, const c16_t *dmrs, c16_t *out)
|
|
|
|
|
{
|
|
|
|
|
*(out + delta) = *dmrs++;
|
|
|
|
|
*(out + delta + 2) = *dmrs++;
|
|
|
|
|
*(out + delta + 4) = *dmrs++;
|
|
|
|
|
*(out + delta + 6) = *dmrs++;
|
|
|
|
|
*(out + delta + 8) = *dmrs++;
|
|
|
|
|
*(out + delta + 10) = *dmrs++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Data in DMRS symbol for Type 1, NumCDMGroupNoData = 1 and delta 0 (antenna port 0 and 1).
|
|
|
|
|
There is no data in DMRS symbol for other scenarios in type 1.
|
|
|
|
|
*/
|
|
|
|
|
static void map_data_dmrs_type1_cdm1_rb(const unsigned int num_cdm_no_data, const c16_t *data, c16_t *out)
|
|
|
|
|
{
|
|
|
|
|
*(out + 1) = *data++;
|
|
|
|
|
*(out + 3) = *data++;
|
|
|
|
|
*(out + 5) = *data++;
|
|
|
|
|
*(out + 7) = *data++;
|
|
|
|
|
*(out + 9) = *data++;
|
|
|
|
|
*(out + 11) = *data++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define NR_DMRS_TYPE2_CDM_GRP_SIZE 2
|
|
|
|
|
#define NR_DMRS_TYPE2_NUM_CDM_GRP 3
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Map DMRS for type 2
|
|
|
|
|
Mapping as in TS 38.211 6.4.1.1.3 k = 6n + k^prime + delta
|
|
|
|
|
*/
|
|
|
|
|
static void map_dmrs_type2_rb(const unsigned int delta, const c16_t *dmrs, c16_t *out)
|
|
|
|
|
{
|
|
|
|
|
memcpy(out + delta, dmrs, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE);
|
|
|
|
|
out += (NR_DMRS_TYPE2_CDM_GRP_SIZE * NR_DMRS_TYPE2_NUM_CDM_GRP);
|
|
|
|
|
dmrs += NR_DMRS_TYPE2_CDM_GRP_SIZE;
|
|
|
|
|
memcpy(out + delta, dmrs, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Map data for type 2 DMRS
|
|
|
|
|
*/
|
|
|
|
|
static void map_data_dmrs_type2_rb(const unsigned int num_cdm_no_data, const c16_t *data, c16_t *out)
|
|
|
|
|
{
|
|
|
|
|
unsigned int offset = num_cdm_no_data * NR_DMRS_TYPE2_CDM_GRP_SIZE;
|
|
|
|
|
const unsigned int size = (NR_DMRS_TYPE2_NUM_CDM_GRP - num_cdm_no_data) * NR_DMRS_TYPE2_CDM_GRP_SIZE;
|
|
|
|
|
memcpy(out + offset, data, sizeof(c16_t) * size);
|
|
|
|
|
offset += NR_DMRS_TYPE2_CDM_GRP_SIZE * NR_DMRS_TYPE2_NUM_CDM_GRP;
|
|
|
|
|
data += size;
|
|
|
|
|
memcpy(out + offset, data, sizeof(c16_t) * size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Map data and PTRS in RB
|
|
|
|
|
*/
|
|
|
|
|
static void map_data_ptrs(const unsigned int ptrsIdx, const c16_t *data, const c16_t *ptrs, c16_t *out)
|
|
|
|
|
{
|
|
|
|
|
memcpy(out, data, sizeof(c16_t) * ptrsIdx);
|
|
|
|
|
data += ptrsIdx;
|
|
|
|
|
*(out + ptrsIdx) = *ptrs;
|
|
|
|
|
memcpy(out + ptrsIdx + 1, data, sizeof(c16_t) * NR_NB_SC_PER_RB - ptrsIdx - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Map data only in RB
|
|
|
|
|
*/
|
|
|
|
|
static void map_data_rb(const c16_t *data, c16_t *out)
|
|
|
|
|
{
|
|
|
|
|
memcpy(out, data, sizeof(c16_t) * NR_NB_SC_PER_RB);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
This function is used when a PRB is on both sides of DC.
|
|
|
|
|
The destination buffer in this case in not contiguous so REs are mapped on to a temporary buffer
|
|
|
|
|
so that we can reuse the existing functions. Then it is copied to the destination buffer.
|
|
|
|
|
*/
|
|
|
|
|
static void map_over_dc(const unsigned int right_dc,
|
|
|
|
|
const unsigned int num_cdm_no_data,
|
|
|
|
|
const unsigned int fft_size,
|
|
|
|
|
const unsigned int dmrs_per_rb,
|
|
|
|
|
const unsigned int data_per_rb,
|
|
|
|
|
const unsigned int delta,
|
|
|
|
|
const unsigned int ptrsIdx,
|
|
|
|
|
const c16_t **ptrs,
|
|
|
|
|
const c16_t **dmrs,
|
|
|
|
|
const c16_t **data,
|
|
|
|
|
c16_t **out)
|
|
|
|
|
{
|
|
|
|
|
// if first RE is DC no need to map in this function
|
|
|
|
|
if (right_dc == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
c16_t *out_tmp = *out;
|
|
|
|
|
c16_t tmp_out_buf[NR_NB_SC_PER_RB];
|
|
|
|
|
const unsigned int left_dc = NR_NB_SC_PER_RB - right_dc;
|
|
|
|
|
/* copy out to temp buffer. incase we want to preserve the REs in the out buffer
|
|
|
|
|
as we call mapping of data in DMRS symbol after mapping DMRS REs
|
|
|
|
|
*/
|
|
|
|
|
memcpy(tmp_out_buf, out_tmp, sizeof(c16_t) * left_dc);
|
|
|
|
|
out_tmp -= (fft_size - left_dc);
|
|
|
|
|
memcpy(tmp_out_buf + left_dc, out_tmp, sizeof(c16_t) * right_dc);
|
|
|
|
|
|
|
|
|
|
/* map on to temp buffer */
|
|
|
|
|
if (dmrs && data) {
|
|
|
|
|
map_data_dmrs_ptr(num_cdm_no_data, *data, tmp_out_buf);
|
|
|
|
|
*data += data_per_rb;
|
|
|
|
|
} else if (dmrs) {
|
|
|
|
|
map_dmrs_ptr(delta, *dmrs, tmp_out_buf);
|
|
|
|
|
*dmrs += dmrs_per_rb;
|
|
|
|
|
} else if (ptrs) {
|
|
|
|
|
map_data_ptrs(ptrsIdx, *data, *ptrs, tmp_out_buf);
|
|
|
|
|
*data += (NR_NB_SC_PER_RB - 1);
|
|
|
|
|
*ptrs += 1;
|
|
|
|
|
} else if (data) {
|
|
|
|
|
map_data_rb(*data, tmp_out_buf);
|
|
|
|
|
*data += NR_NB_SC_PER_RB;
|
|
|
|
|
} else {
|
|
|
|
|
DevAssert(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* copy back to out buffer */
|
|
|
|
|
out_tmp = *out;
|
|
|
|
|
memcpy(out_tmp, tmp_out_buf, sizeof(c16_t) * left_dc);
|
|
|
|
|
out_tmp -= (fft_size - left_dc);
|
|
|
|
|
memcpy(out_tmp, tmp_out_buf + left_dc, sizeof(c16_t) * right_dc);
|
|
|
|
|
out_tmp += right_dc;
|
|
|
|
|
*out = out_tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Holds params needed for PUSCH resoruce mapping
|
|
|
|
|
*/
|
|
|
|
|
typedef struct {
|
|
|
|
|
rnti_t rnti;
|
|
|
|
|
unsigned int K_ptrs;
|
|
|
|
|
unsigned int k_RE_ref;
|
|
|
|
|
unsigned int first_sc_offset;
|
|
|
|
|
unsigned int fft_size;
|
|
|
|
|
unsigned int num_rb_max;
|
|
|
|
|
unsigned int symbols_per_slot;
|
|
|
|
|
unsigned int slot;
|
|
|
|
|
unsigned int dmrs_scrambling_id;
|
|
|
|
|
unsigned int scid;
|
|
|
|
|
unsigned int dmrs_port;
|
|
|
|
|
int Wt;
|
|
|
|
|
int *Wf;
|
|
|
|
|
unsigned int dmrs_symb_pos;
|
|
|
|
|
unsigned int ptrs_symb_pos;
|
|
|
|
|
unsigned int pdu_bit_map;
|
|
|
|
|
transformPrecoder_t transform_precoding;
|
|
|
|
|
unsigned int bwp_start;
|
|
|
|
|
unsigned int start_rb;
|
|
|
|
|
unsigned int nb_rb;
|
|
|
|
|
unsigned int start_symbol;
|
|
|
|
|
unsigned int num_symbols;
|
|
|
|
|
pusch_dmrs_type_t dmrs_type;
|
|
|
|
|
unsigned int delta;
|
|
|
|
|
unsigned int num_cdm_no_data;
|
|
|
|
|
} nr_phy_pxsch_params_t;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Map all REs in one OFDM symbol
|
|
|
|
|
This function operation is as follows:
|
|
|
|
|
mapping is done on RB basis. if RB contains DC and if DC is in middle
|
|
|
|
|
of the RB, then the mapping is done via map_over_dc().
|
|
|
|
|
*/
|
|
|
|
|
static void map_current_symbol(const nr_phy_pxsch_params_t p,
|
|
|
|
|
const bool dmrs_symbol,
|
|
|
|
|
const bool ptrs_symbol,
|
|
|
|
|
const c16_t *dmrs_seq,
|
|
|
|
|
const c16_t *ptrs_seq,
|
|
|
|
|
const c16_t **data,
|
|
|
|
|
c16_t *out)
|
|
|
|
|
{
|
|
|
|
|
const unsigned int abs_start_rb = p.bwp_start + p.start_rb;
|
|
|
|
|
const unsigned int start_sc = (p.first_sc_offset + abs_start_rb * NR_NB_SC_PER_RB) % p.fft_size;
|
|
|
|
|
const unsigned int dc_rb = (p.fft_size - start_sc) / NR_NB_SC_PER_RB;
|
|
|
|
|
const unsigned int rb_over_dc = (p.fft_size - start_sc) % NR_NB_SC_PER_RB;
|
|
|
|
|
const unsigned int n_cdm = p.num_cdm_no_data;
|
|
|
|
|
const c16_t *data_tmp = *data;
|
|
|
|
|
/* If current symbol is DMRS symbol */
|
|
|
|
|
if (dmrs_symbol) {
|
|
|
|
|
const unsigned int dmrs_per_rb = (p.dmrs_type == pusch_dmrs_type1) ? 6 : 4;
|
|
|
|
|
const unsigned int data_per_rb = NR_NB_SC_PER_RB - dmrs_per_rb;
|
|
|
|
|
|
|
|
|
|
const c16_t *p_mod_dmrs = dmrs_seq + abs_start_rb * dmrs_per_rb;
|
|
|
|
|
c16_t *out_tmp = out + start_sc;
|
|
|
|
|
for (unsigned int rb = 0; rb < p.nb_rb; rb++) {
|
|
|
|
|
if (rb == dc_rb) {
|
|
|
|
|
// map RB at DC
|
|
|
|
|
if (rb_over_dc) {
|
|
|
|
|
// if DC is in middle of RB, the following function handles it.
|
|
|
|
|
map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, NULL, &out_tmp);
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
// else just move the pointer and following function will map the rb
|
|
|
|
|
out_tmp -= p.fft_size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
map_dmrs_ptr(p.delta, p_mod_dmrs, out_tmp);
|
|
|
|
|
p_mod_dmrs += dmrs_per_rb;
|
|
|
|
|
out_tmp += NR_NB_SC_PER_RB;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* if there is data in current DMRS symbol, we map it here. */
|
|
|
|
|
if (map_data_dmrs_ptr) {
|
|
|
|
|
c16_t *out_tmp = out + start_sc;
|
|
|
|
|
for (unsigned int rb = 0; rb < p.nb_rb; rb++) {
|
|
|
|
|
if (rb == dc_rb) {
|
|
|
|
|
if (rb_over_dc) {
|
|
|
|
|
map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, &data_tmp, &out_tmp);
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
out_tmp -= p.fft_size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
map_data_dmrs_ptr(n_cdm, data_tmp, out_tmp);
|
|
|
|
|
data_tmp += data_per_rb;
|
|
|
|
|
out_tmp += NR_NB_SC_PER_RB;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* If current symbol is a PTRS symbol */
|
|
|
|
|
} else if (ptrs_symbol) {
|
|
|
|
|
const unsigned int first_ptrs_re = get_first_ptrs_re(p.rnti, p.K_ptrs, p.nb_rb, p.k_RE_ref) + start_sc;
|
|
|
|
|
const unsigned int ptrs_idx_re = (start_sc - first_ptrs_re) % NR_NB_SC_PER_RB; // PTRS RE index within RB
|
|
|
|
|
unsigned int non_ptrs_rb = (start_sc - first_ptrs_re) / NR_NB_SC_PER_RB; // number of RBs before the first PTRS RB
|
|
|
|
|
int ptrs_idx_rb = -non_ptrs_rb; // RB count to check for PTRS RB
|
|
|
|
|
c16_t *out_tmp = out + start_sc;
|
|
|
|
|
const c16_t *p_mod_ptrs = ptrs_seq;
|
|
|
|
|
/* map data to RBs before the first PTRS RB or if current RB has no PTRS */
|
|
|
|
|
for (unsigned int rb = 0; rb < p.nb_rb; rb++) {
|
|
|
|
|
if (rb < non_ptrs_rb || ptrs_idx_rb % p.K_ptrs) {
|
|
|
|
|
if (rb == dc_rb) {
|
|
|
|
|
if (rb_over_dc) {
|
|
|
|
|
map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp);
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
out_tmp -= p.fft_size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
map_data_rb(data_tmp, out_tmp);
|
|
|
|
|
data_tmp += NR_NB_SC_PER_RB;
|
|
|
|
|
out_tmp += NR_NB_SC_PER_RB;
|
|
|
|
|
} else {
|
|
|
|
|
if (rb == dc_rb) {
|
|
|
|
|
if (rb_over_dc) {
|
|
|
|
|
map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, ptrs_idx_re, &p_mod_ptrs, NULL, &data_tmp, &out_tmp);
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
out_tmp -= p.fft_size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
map_data_ptrs(ptrs_idx_re, data_tmp, p_mod_ptrs, out_tmp);
|
|
|
|
|
p_mod_ptrs++; // increament once as only one PTRS RE per RB
|
|
|
|
|
data_tmp += (NR_NB_SC_PER_RB - 1);
|
|
|
|
|
out_tmp += NR_NB_SC_PER_RB;
|
|
|
|
|
}
|
|
|
|
|
ptrs_idx_rb++;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* only data in this symbol */
|
|
|
|
|
c16_t *out_tmp = out + start_sc;
|
|
|
|
|
for (unsigned int rb = 0; rb < p.nb_rb; rb++) {
|
|
|
|
|
if (rb == dc_rb) {
|
|
|
|
|
if (rb_over_dc) {
|
|
|
|
|
map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp);
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
out_tmp -= p.fft_size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
map_data_rb(data_tmp, out_tmp);
|
|
|
|
|
data_tmp += NR_NB_SC_PER_RB;
|
|
|
|
|
out_tmp += NR_NB_SC_PER_RB;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*data = data_tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
TS 38.211 table 6.4.1.1.3-1 and 2
|
|
|
|
|
*/
|
|
|
|
|
static void dmrs_amp_mult(const uint32_t dmrs_port,
|
|
|
|
|
const int Wt,
|
|
|
|
|
const int Wf[2],
|
|
|
|
|
const c16_t *mod_dmrs,
|
|
|
|
|
c16_t *mod_dmrs_out,
|
|
|
|
|
const uint32_t n_dmrs,
|
|
|
|
|
const pusch_dmrs_type_t dmrs_type)
|
|
|
|
|
{
|
|
|
|
|
/* short array that hold amplitude for k_prime = 0 and k_prime = 1 */
|
|
|
|
|
int32_t alpha_dmrs[2] __attribute((aligned(16)));
|
|
|
|
|
for (int_fast8_t i = 0; i < sizeofArray(alpha_dmrs); i++) {
|
|
|
|
|
const int32_t a = Wf[i] * Wt * AMP;
|
|
|
|
|
alpha_dmrs[i] = a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* multiply amplitude with complex DMRS vector */
|
|
|
|
|
for (int_fast16_t i = 0; i < n_dmrs; i++) {
|
|
|
|
|
mod_dmrs_out[i] = c16mulRealShift(mod_dmrs[i], alpha_dmrs[i % 2], 15);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Map ULSCH data and DMRS in all of the scheduled symbols and PRBs
|
|
|
|
|
*/
|
|
|
|
|
static void map_symbols(const nr_phy_pxsch_params_t p,
|
|
|
|
|
const unsigned int slot,
|
|
|
|
|
const c16_t *dmrs_seq,
|
|
|
|
|
const c16_t *data,
|
|
|
|
|
c16_t *out)
|
|
|
|
|
{
|
|
|
|
|
// asign the function pointers
|
|
|
|
|
if (p.dmrs_type == pusch_dmrs_type1) {
|
|
|
|
|
map_dmrs_ptr = map_dmrs_type1_cdm1_rb;
|
|
|
|
|
map_data_dmrs_ptr = (p.num_cdm_no_data == 1) ? map_data_dmrs_type1_cdm1_rb : NULL;
|
|
|
|
|
} else {
|
|
|
|
|
map_dmrs_ptr = map_dmrs_type2_rb;
|
|
|
|
|
map_data_dmrs_ptr = (p.num_cdm_no_data < 3) ? map_data_dmrs_type2_rb : NULL;
|
|
|
|
|
}
|
|
|
|
|
// for all symbols
|
|
|
|
|
const unsigned int n_dmrs = (p.bwp_start + p.start_rb + p.nb_rb) * ((p.dmrs_type == pusch_dmrs_type1) ? 6 : 4);
|
|
|
|
|
const c16_t *cur_data = data;
|
|
|
|
|
for (int l = p.start_symbol; l < p.start_symbol + p.num_symbols; l++) {
|
|
|
|
|
const bool dmrs_symbol = is_dmrs_symbol(l, p.dmrs_symb_pos);
|
|
|
|
|
const bool ptrs_symbol = is_ptrs_symbol(l, p.ptrs_symb_pos);
|
|
|
|
|
c16_t mod_dmrs_amp[ALNARS_16_4(n_dmrs)] __attribute((aligned(16)));
|
|
|
|
|
c16_t mod_ptrs_amp[ALNARS_16_4(p.nb_rb)] __attribute((aligned(16)));
|
|
|
|
|
const uint32_t *gold = NULL;
|
|
|
|
|
if (dmrs_symbol || ptrs_symbol) {
|
|
|
|
|
gold = nr_gold_pusch(p.num_rb_max, p.symbols_per_slot, p.dmrs_scrambling_id, p.scid, slot, l);
|
|
|
|
|
}
|
|
|
|
|
if (dmrs_symbol) {
|
|
|
|
|
c16_t mod_dmrs[ALNARS_16_4(n_dmrs)] __attribute((aligned(16)));
|
|
|
|
|
if (p.transform_precoding == transformPrecoder_disabled) {
|
|
|
|
|
nr_modulation(gold, n_dmrs * 2, DMRS_MOD_ORDER, (int16_t *)mod_dmrs);
|
|
|
|
|
dmrs_amp_mult(p.dmrs_port, p.Wt, p.Wf, mod_dmrs, mod_dmrs_amp, n_dmrs, p.dmrs_type);
|
|
|
|
|
} else {
|
|
|
|
|
dmrs_amp_mult(p.dmrs_port, p.Wt, p.Wf, dmrs_seq, mod_dmrs_amp, n_dmrs, p.dmrs_type);
|
|
|
|
|
}
|
|
|
|
|
} else if ((p.pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) && ptrs_symbol) {
|
|
|
|
|
AssertFatal(p.transform_precoding == transformPrecoder_disabled, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n");
|
|
|
|
|
c16_t mod_ptrs[ALNARS_16_4(p.nb_rb)] __attribute((aligned(16)));
|
|
|
|
|
nr_modulation(gold, p.nb_rb, DMRS_MOD_ORDER, (int16_t *)mod_ptrs);
|
|
|
|
|
const unsigned int beta_ptrs = 1; // temp value until power control is implemented
|
|
|
|
|
multadd_complex_vector_real_scalar((int16_t *)mod_ptrs, beta_ptrs * AMP, (int16_t *)mod_ptrs_amp, 1, p.nb_rb);
|
|
|
|
|
}
|
|
|
|
|
map_current_symbol(p,
|
|
|
|
|
dmrs_symbol,
|
|
|
|
|
ptrs_symbol,
|
|
|
|
|
mod_dmrs_amp,
|
|
|
|
|
mod_ptrs_amp,
|
|
|
|
|
&cur_data, // increments every symbol
|
|
|
|
|
out + l * p.fft_size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|
|
|
|
const unsigned char harq_pid,
|
|
|
|
|
const uint32_t frame,
|
|
|
|
@@ -95,11 +471,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|
|
|
|
{
|
|
|
|
|
LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n",harq_pid,frame,slot);
|
|
|
|
|
|
|
|
|
|
int Wf[2], Wt[2];
|
|
|
|
|
int l_prime[2], delta;
|
|
|
|
|
int l_prime[2];
|
|
|
|
|
uint8_t nb_dmrs_re_per_rb;
|
|
|
|
|
int i;
|
|
|
|
|
int sample_offsetF, N_RE_prime;
|
|
|
|
|
|
|
|
|
|
NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms;
|
|
|
|
|
|
|
|
|
@@ -143,17 +516,18 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|
|
|
|
LOG_D(PHY,"ulsch TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_re_per_rb %d\n",
|
|
|
|
|
rnti,start_rb,nb_rb,mod_order,Nl,pusch_pdu->Tpmi,pusch_pdu->bwp_start,start_sc,start_symbol,number_of_symbols,cdm_grps_no_data,number_dmrs_symbols,nb_dmrs_re_per_rb);
|
|
|
|
|
// TbD num_of_mod_symbols is set but never used
|
|
|
|
|
N_RE_prime = NR_NB_SC_PER_RB*number_of_symbols - nb_dmrs_re_per_rb*number_dmrs_symbols - N_PRB_oh;
|
|
|
|
|
const uint32_t N_RE_prime = NR_NB_SC_PER_RB * number_of_symbols - nb_dmrs_re_per_rb * number_dmrs_symbols - N_PRB_oh;
|
|
|
|
|
harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb;
|
|
|
|
|
|
|
|
|
|
/////////////////////////PTRS parameters' initialization/////////////////////////
|
|
|
|
|
///////////
|
|
|
|
|
|
|
|
|
|
uint8_t L_ptrs, K_ptrs = 0;
|
|
|
|
|
unsigned int K_ptrs = 0, k_RE_ref = 0;
|
|
|
|
|
uint32_t unav_res = 0;
|
|
|
|
|
if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
|
|
|
|
|
K_ptrs = pusch_pdu->pusch_ptrs.ptrs_freq_density;
|
|
|
|
|
L_ptrs = 1 << pusch_pdu->pusch_ptrs.ptrs_time_density;
|
|
|
|
|
k_RE_ref = pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset;
|
|
|
|
|
uint8_t L_ptrs = 1 << pusch_pdu->pusch_ptrs.ptrs_time_density;
|
|
|
|
|
|
|
|
|
|
ulsch_ue->ptrs_symbols = 0;
|
|
|
|
|
|
|
|
|
@@ -197,8 +571,11 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|
|
|
|
.oob_event_value = 0};
|
|
|
|
|
trace_pdu(&tmp);
|
|
|
|
|
|
|
|
|
|
if (nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, tb_size, G) == -1)
|
|
|
|
|
if (nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, tb_size, G) == -1) {
|
|
|
|
|
NR_UL_UE_HARQ_t *harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
|
|
|
|
|
harq_process_ulsch->ULstatus = SCH_IDLE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
@@ -236,23 +613,12 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|
|
|
|
///////////
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/////////////////////////DMRS Modulation/////////////////////////
|
|
|
|
|
///////////
|
|
|
|
|
|
|
|
|
|
uint16_t n_dmrs = (pusch_pdu->bwp_start + start_rb + nb_rb)*((dmrs_type == pusch_dmrs_type1) ? 6:4);
|
|
|
|
|
c16_t mod_dmrs[n_dmrs] __attribute((aligned(16)));
|
|
|
|
|
|
|
|
|
|
///////////
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////ULSCH layer mapping/////////////////////////
|
|
|
|
|
///////////
|
|
|
|
|
const int sz = available_bits / mod_order;
|
|
|
|
|
c16_t tx_layers[Nl][sz];
|
|
|
|
|
memset(tx_layers, 0, sizeof(tx_layers));
|
|
|
|
|
const int sz = available_bits / mod_order / Nl;
|
|
|
|
|
c16_t ulsch_mod[Nl][sz];
|
|
|
|
|
|
|
|
|
|
nr_ue_layer_mapping(d_mod, Nl, available_bits / mod_order, sz, tx_layers);
|
|
|
|
|
nr_ue_layer_mapping(d_mod, Nl, sz, ulsch_mod);
|
|
|
|
|
|
|
|
|
|
///////////
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
@@ -266,8 +632,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|
|
|
|
uint8_t u = 0, v = 0;
|
|
|
|
|
c16_t *dmrs_seq = NULL;
|
|
|
|
|
/// Transform-coded "y"-sequences (for definition see 38-211 V15.3.0 2018-09, subsection 6.3.1.4)
|
|
|
|
|
c16_t y[max_num_re] __attribute__((aligned(16)));
|
|
|
|
|
memset(y, 0, sizeof(y));
|
|
|
|
|
c16_t ulsch_mod_tp[max_num_re] __attribute__((aligned(16)));
|
|
|
|
|
memset(ulsch_mod_tp, 0, sizeof(ulsch_mod_tp));
|
|
|
|
|
|
|
|
|
|
if (pusch_pdu->transform_precoding == transformPrecoder_enabled) {
|
|
|
|
|
|
|
|
|
@@ -292,7 +658,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|
|
|
|
/* In the symbol with DMRS no data would be transmitted CDM groups is 2*/
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
nr_dft(&y[y_offset], &tx_layers[0][y_offset], nb_re_pusch);
|
|
|
|
|
nr_dft(&ulsch_mod_tp[y_offset], &ulsch_mod[0][y_offset], nb_re_pusch);
|
|
|
|
|
|
|
|
|
|
y_offset = y_offset + nb_re_pusch;
|
|
|
|
|
|
|
|
|
@@ -310,7 +676,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|
|
|
|
printf("NR_ULSCH_UE: available_bits: %u, mod_order: %d", available_bits,mod_order);
|
|
|
|
|
|
|
|
|
|
for (int ll = 0; ll < (available_bits/mod_order); ll++) {
|
|
|
|
|
debug_symbols[ll] = ulsch_ue->y[ll];
|
|
|
|
|
debug_symbols[ll] = ulsch_ue->ulsch_mod_tp[ll];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("NR_ULSCH_UE: numSym: %d, num_dmrs_sym: %d", number_of_symbols,number_dmrs_symbols);
|
|
|
|
@@ -318,8 +684,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|
|
|
|
nr_idft(&debug_symbols[offset], nb_re_pusch);
|
|
|
|
|
offset = offset + nb_re_pusch;
|
|
|
|
|
}
|
|
|
|
|
LOG_M("preDFT_all_symbols.m","UE_preDFT", tx_layers[0],number_of_symbols*nb_re_pusch,1,1);
|
|
|
|
|
LOG_M("postDFT_all_symbols.m","UE_postDFT", y,number_of_symbols*nb_re_pusch,1,1);
|
|
|
|
|
LOG_M("preDFT_all_symbols.m", "UE_preDFT", ulsch_mod[0], number_of_symbols * nb_re_pusch, 1, 1);
|
|
|
|
|
LOG_M("postDFT_all_symbols.m", "UE_postDFT", ulsch_mod_tp, number_of_symbols * nb_re_pusch, 1, 1);
|
|
|
|
|
LOG_M("DEBUG_IDFT_SYMBOLS.m","UE_Debug_IDFT", debug_symbols,number_of_symbols*nb_re_pusch,1,1);
|
|
|
|
|
LOG_M("UE_DMRS_SEQ.m","UE_DMRS_SEQ", dmrs_seq,nb_re_pusch,1,1);
|
|
|
|
|
#endif
|
|
|
|
@@ -334,157 +700,57 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|
|
|
|
/////////////////////////ULSCH RE mapping/////////////////////////
|
|
|
|
|
///////////
|
|
|
|
|
|
|
|
|
|
const int encoded_length = frame_parms->N_RB_UL * 14 * NR_NB_SC_PER_RB * mod_order * Nl;
|
|
|
|
|
c16_t tx_precoding[Nl][encoded_length];
|
|
|
|
|
const int slot_sz = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot;
|
|
|
|
|
c16_t tx_precoding[Nl][slot_sz];
|
|
|
|
|
memset(tx_precoding, 0, sizeof(tx_precoding));
|
|
|
|
|
|
|
|
|
|
for (int nl=0; nl < Nl; nl++) {
|
|
|
|
|
uint8_t k_prime = 0;
|
|
|
|
|
uint16_t m = 0;
|
|
|
|
|
|
|
|
|
|
for (int nl = 0; nl < Nl; nl++) {
|
|
|
|
|
#ifdef DEBUG_PUSCH_MAPPING
|
|
|
|
|
printf("NR_ULSCH_UE: Value of CELL ID %d /t, u %d \n", frame_parms->Nid_cell, u);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int dmrs_port = get_dmrs_port(nl,pusch_pdu->dmrs_ports);
|
|
|
|
|
// DMRS params for this dmrs port
|
|
|
|
|
const uint8_t dmrs_port = get_dmrs_port(nl, pusch_pdu->dmrs_ports);
|
|
|
|
|
const uint8_t delta = get_delta(dmrs_port, dmrs_type);
|
|
|
|
|
int Wt[2];
|
|
|
|
|
int Wf[2];
|
|
|
|
|
get_Wt(Wt, dmrs_port, dmrs_type);
|
|
|
|
|
get_Wf(Wf, dmrs_port, dmrs_type);
|
|
|
|
|
delta = get_delta(dmrs_port, dmrs_type);
|
|
|
|
|
|
|
|
|
|
for (int l=start_symbol; l<start_symbol+number_of_symbols; l++) {
|
|
|
|
|
c16_t *data = (pusch_pdu->transform_precoding == transformPrecoder_enabled) ? ulsch_mod_tp : ulsch_mod[nl];
|
|
|
|
|
|
|
|
|
|
uint16_t k = start_sc;
|
|
|
|
|
uint16_t n = 0;
|
|
|
|
|
uint8_t is_dmrs_sym = 0;
|
|
|
|
|
uint8_t is_ptrs_sym = 0;
|
|
|
|
|
uint16_t dmrs_idx = 0, ptrs_idx = 0;
|
|
|
|
|
nr_phy_pxsch_params_t params = {.rnti = rnti,
|
|
|
|
|
.K_ptrs = K_ptrs,
|
|
|
|
|
.k_RE_ref = k_RE_ref,
|
|
|
|
|
.first_sc_offset = frame_parms->first_carrier_offset,
|
|
|
|
|
.fft_size = frame_parms->ofdm_symbol_size,
|
|
|
|
|
.num_rb_max = frame_parms->N_RB_UL,
|
|
|
|
|
.symbols_per_slot = frame_parms->symbols_per_slot,
|
|
|
|
|
.dmrs_scrambling_id = pusch_pdu->ul_dmrs_scrambling_id,
|
|
|
|
|
.scid = pusch_pdu->scid,
|
|
|
|
|
.dmrs_port = dmrs_port,
|
|
|
|
|
.Wt = Wt[l_prime[0]],
|
|
|
|
|
.Wf = Wf,
|
|
|
|
|
.dmrs_symb_pos = ul_dmrs_symb_pos,
|
|
|
|
|
.ptrs_symb_pos = ulsch_ue->ptrs_symbols,
|
|
|
|
|
.pdu_bit_map = pusch_pdu->pdu_bit_map,
|
|
|
|
|
.transform_precoding = pusch_pdu->transform_precoding,
|
|
|
|
|
.bwp_start = pusch_pdu->bwp_start,
|
|
|
|
|
.start_rb = start_rb,
|
|
|
|
|
.nb_rb = nb_rb,
|
|
|
|
|
.start_symbol = start_symbol,
|
|
|
|
|
.num_symbols = number_of_symbols,
|
|
|
|
|
.dmrs_type = dmrs_type,
|
|
|
|
|
.delta = delta,
|
|
|
|
|
.num_cdm_no_data = cdm_grps_no_data};
|
|
|
|
|
|
|
|
|
|
c16_t mod_ptrs[nb_rb] __attribute((aligned(16))); // assume maximum number of PTRS per pusch allocation
|
|
|
|
|
map_symbols(params, slot, dmrs_seq, data, tx_precoding[nl]);
|
|
|
|
|
|
|
|
|
|
if ((ul_dmrs_symb_pos >> l) & 0x01) {
|
|
|
|
|
is_dmrs_sym = 1;
|
|
|
|
|
|
|
|
|
|
if (pusch_pdu->transform_precoding == transformPrecoder_disabled){
|
|
|
|
|
|
|
|
|
|
if (dmrs_type == pusch_dmrs_type1)
|
|
|
|
|
dmrs_idx = (pusch_pdu->bwp_start + start_rb)*6;
|
|
|
|
|
else
|
|
|
|
|
dmrs_idx = (pusch_pdu->bwp_start + start_rb)*4;
|
|
|
|
|
|
|
|
|
|
// TODO: performance improvement, we can skip the modulation of DMRS symbols outside the bandwidth part
|
|
|
|
|
// Perform this on gold sequence, not required when SC FDMA operation is done,
|
|
|
|
|
LOG_D(PHY,"DMRS in symbol %d\n",l);
|
|
|
|
|
const uint32_t *gold = nr_gold_pusch(frame_parms->N_RB_UL,
|
|
|
|
|
frame_parms->symbols_per_slot,
|
|
|
|
|
pusch_pdu->ul_dmrs_scrambling_id,
|
|
|
|
|
pusch_pdu->scid,
|
|
|
|
|
slot,
|
|
|
|
|
l);
|
|
|
|
|
nr_modulation(gold,
|
|
|
|
|
n_dmrs * 2,
|
|
|
|
|
DMRS_MOD_ORDER,
|
|
|
|
|
(int16_t *)mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
|
|
|
|
|
} else {
|
|
|
|
|
dmrs_idx = 0;
|
|
|
|
|
}
|
|
|
|
|
} else if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
|
|
|
|
|
|
|
|
|
|
AssertFatal(pusch_pdu->transform_precoding == transformPrecoder_disabled, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n");
|
|
|
|
|
|
|
|
|
|
if(is_ptrs_symbol(l, ulsch_ue->ptrs_symbols)) {
|
|
|
|
|
is_ptrs_sym = 1;
|
|
|
|
|
const uint32_t *gold = nr_gold_pusch(frame_parms->N_RB_UL,
|
|
|
|
|
frame_parms->symbols_per_slot,
|
|
|
|
|
pusch_pdu->ul_dmrs_scrambling_id,
|
|
|
|
|
pusch_pdu->scid,
|
|
|
|
|
slot,
|
|
|
|
|
l);
|
|
|
|
|
nr_modulation(gold, nb_rb, DMRS_MOD_ORDER, (int16_t *)mod_ptrs);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++) {
|
|
|
|
|
uint8_t is_dmrs = 0;
|
|
|
|
|
uint8_t is_ptrs = 0;
|
|
|
|
|
|
|
|
|
|
sample_offsetF = l*frame_parms->ofdm_symbol_size + k;
|
|
|
|
|
|
|
|
|
|
if (is_dmrs_sym) {
|
|
|
|
|
if (k == ((start_sc+get_dmrs_freq_idx_ul(n, k_prime, delta, dmrs_type))%frame_parms->ofdm_symbol_size))
|
|
|
|
|
is_dmrs = 1;
|
|
|
|
|
} else if (is_ptrs_sym) {
|
|
|
|
|
is_ptrs = is_ptrs_subcarrier(k,
|
|
|
|
|
rnti,
|
|
|
|
|
K_ptrs,
|
|
|
|
|
nb_rb,
|
|
|
|
|
pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset,
|
|
|
|
|
start_sc,
|
|
|
|
|
frame_parms->ofdm_symbol_size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_dmrs == 1) {
|
|
|
|
|
// if transform precoding is enabled
|
|
|
|
|
const int tmp = Wt[l_prime[0]] * Wf[k_prime] * AMP;
|
|
|
|
|
if (pusch_pdu->transform_precoding == transformPrecoder_enabled)
|
|
|
|
|
tx_precoding[nl][sample_offsetF] = c16mulRealShift(dmrs_seq[dmrs_idx], tmp, 15);
|
|
|
|
|
else
|
|
|
|
|
tx_precoding[nl][sample_offsetF] = c16mulRealShift(mod_dmrs[dmrs_idx], tmp, 15);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_PUSCH_MAPPING
|
|
|
|
|
printf("DMRS: Layer: %d\t, dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t dmrs: %d %d\n",
|
|
|
|
|
nl,
|
|
|
|
|
dmrs_idx,
|
|
|
|
|
l,
|
|
|
|
|
k,
|
|
|
|
|
k_prime,
|
|
|
|
|
n,
|
|
|
|
|
tx_precoding[nl][sample_offsetF].r,
|
|
|
|
|
tx_precoding[nl][sample_offsetF].i);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
dmrs_idx++;
|
|
|
|
|
k_prime++;
|
|
|
|
|
k_prime &= 1;
|
|
|
|
|
n += (k_prime) ? 0 : 1;
|
|
|
|
|
|
|
|
|
|
} else if (is_ptrs == 1) {
|
|
|
|
|
uint16_t beta_ptrs = 1; // temp value until power control is implemented
|
|
|
|
|
tx_precoding[nl][sample_offsetF] = c16mulRealShift(mod_ptrs[ptrs_idx], beta_ptrs * AMP, 15);
|
|
|
|
|
ptrs_idx++;
|
|
|
|
|
} else if (!is_dmrs_sym
|
|
|
|
|
|| allowed_xlsch_re_in_dmrs_symbol(k, start_sc, frame_parms->ofdm_symbol_size, cdm_grps_no_data, dmrs_type)) {
|
|
|
|
|
if (pusch_pdu->transform_precoding == transformPrecoder_disabled)
|
|
|
|
|
tx_precoding[nl][sample_offsetF] = tx_layers[nl][m];
|
|
|
|
|
else
|
|
|
|
|
tx_precoding[nl][sample_offsetF] = y[m];
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_PUSCH_MAPPING
|
|
|
|
|
printf("DATA: layer %d\t m %d\t l %d \t k %d \t tx_precoding: %d %d\n",
|
|
|
|
|
nl,
|
|
|
|
|
m,
|
|
|
|
|
l,
|
|
|
|
|
k,
|
|
|
|
|
tx_precoding[nl][sample_offsetF].r,
|
|
|
|
|
tx_precoding[nl][sample_offsetF].i);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
m++;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
tx_precoding[nl][sample_offsetF] = (c16_t){0};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (++k >= frame_parms->ofdm_symbol_size)
|
|
|
|
|
k -= frame_parms->ofdm_symbol_size;
|
|
|
|
|
} // for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++)
|
|
|
|
|
} // for (l=start_symbol; l<start_symbol+number_of_symbols; l++)
|
|
|
|
|
} // for (nl=0; nl < Nl; nl++)
|
|
|
|
|
|
|
|
|
|
/////////////////////////ULSCH precoding/////////////////////////
|
|
|
|
|
///////////
|
|
|
|
|
/// Layer Precoding and Antenna port mapping
|
|
|
|
|
// tx_layers 0-3 are mapped on antenna ports
|
|
|
|
|
// ulsch_mod 0-3 are mapped on antenna ports
|
|
|
|
|
// The precoding info is supported by nfapi such as num_prgs, prg_size, prgs_list and pm_idx
|
|
|
|
|
// The same precoding matrix is applied on prg_size RBs, Thus
|
|
|
|
|
// pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1
|
|
|
|
@@ -555,7 +821,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < NR_NB_SC_PER_RB; i++) {
|
|
|
|
|
int32_t re_offset = l * frame_parms->ofdm_symbol_size + k;
|
|
|
|
|
txdataF[ap][re_offset] = nr_layer_precoder(encoded_length, tx_precoding, W_prec, pusch_pdu->nrOfLayers, re_offset);
|
|
|
|
|
txdataF[ap][re_offset] = nr_layer_precoder(slot_sz, tx_precoding, W_prec, pusch_pdu->nrOfLayers, re_offset);
|
|
|
|
|
if (++k >= frame_parms->ofdm_symbol_size) {
|
|
|
|
|
k -= frame_parms->ofdm_symbol_size;
|
|
|
|
|
}
|
|
|
|
|