mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-14 21:20:30 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14e47ed9f4 | ||
|
|
b3581ecfa4 | ||
|
|
33ebe98a34 | ||
|
|
9da5dd472c | ||
|
|
eebe5f0373 | ||
|
|
ae4c690c7e | ||
|
|
444587bf53 | ||
|
|
80cbb0348d | ||
|
|
0a7dbe6aa7 | ||
|
|
f624629a78 | ||
|
|
ec2f9f489d | ||
|
|
1a29bd120d | ||
|
|
57ca0458fc | ||
|
|
59054cb34e | ||
|
|
882b34c10d |
@@ -256,9 +256,8 @@ static void UE_synch(void *arg) {
|
||||
((ret.rx_offset << 1) / fp->samples_per_subframe * fp->slots_per_subframe)
|
||||
+ round((float)((ret.rx_offset << 1) % fp->samples_per_subframe) / fp->samples_per_slot0);
|
||||
|
||||
if (get_nrUE_params()->cont_fo_comp) {
|
||||
UE->freq_offset = freq_offset;
|
||||
} else {
|
||||
UE->freq_offset = freq_offset;
|
||||
if (!get_nrUE_params()->cont_fo_comp) {
|
||||
// rerun with new cell parameters and frequency-offset
|
||||
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset);
|
||||
UE->rfdevice.trx_set_freq_func(&UE->rfdevice, cfg0);
|
||||
@@ -773,6 +772,38 @@ static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
|
||||
}
|
||||
}
|
||||
|
||||
void trs_freq_correction(PHY_VARS_NR_UE *ue)
|
||||
{
|
||||
if (ue->trs_cfo[NUM_TRS_SLOT - 1].valid) { // last slot in a TRS burst
|
||||
const int avg_trs_cfo = (ue->trs_cfo[0].cfo + ue->trs_cfo[1].cfo) / 2;
|
||||
if (abs(avg_trs_cfo) > TRS_CFO_THRESH) {
|
||||
LOG_A(PHY, "CFO estimated (%d) from TRS exceeded threshold (%d). Adjusting radio CF\n", avg_trs_cfo, TRS_CFO_THRESH);
|
||||
ue->freq_offset += avg_trs_cfo;
|
||||
uint64_t dl_carrier;
|
||||
uint64_t ul_carrier;
|
||||
nr_get_carrier_frequencies(ue, &dl_carrier, &ul_carrier);
|
||||
openair0_config_t *cfg0 = &ue->openair0_cfg[ue->rf_map.card];
|
||||
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, ue->freq_offset);
|
||||
ue->rfdevice.trx_set_freq_func(&ue->rfdevice, cfg0);
|
||||
}
|
||||
ue->trs_cfo[0].valid = ue->trs_cfo[1].valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_is_last_trs_slot(const int current_slot, const int last_slot)
|
||||
{
|
||||
// TRS can be 2 consequtive slots or 1 slot in a frame
|
||||
return (current_slot == (last_slot + 1) || current_slot == last_slot);
|
||||
}
|
||||
|
||||
static void update_trs_info(nr_phy_data_t *d, int *last_slot, const int current_slot)
|
||||
{
|
||||
if (d->csirs_vars[0].active && d->csirs_vars[0].csirs_config_pdu.csi_type == 0) {
|
||||
d->is_last_trs_slot = get_is_last_trs_slot(current_slot, *last_slot);
|
||||
*last_slot = current_slot;
|
||||
}
|
||||
}
|
||||
|
||||
void *UE_thread(void *arg)
|
||||
{
|
||||
//this thread should be over the processing thread to keep in real time
|
||||
@@ -825,6 +856,7 @@ void *UE_thread(void *arg)
|
||||
int intialSyncOffset = 0;
|
||||
openair0_timestamp sync_timestamp;
|
||||
bool stats_printed = false;
|
||||
int last_trs_slot = 0;
|
||||
|
||||
if (get_softmodem_params()->sync_ref && UE->sl_mode == 2) {
|
||||
UE->is_synchronized = 1;
|
||||
@@ -1055,6 +1087,7 @@ void *UE_thread(void *arg)
|
||||
nr_rxtx_thread_data_t *curMsgRx = (nr_rxtx_thread_data_t *)NotifiedFifoData(newRx);
|
||||
*curMsgRx = (nr_rxtx_thread_data_t){.proc = curMsg.proc, .UE = UE};
|
||||
int ret = UE_dl_preprocessing(UE, &curMsgRx->proc, tx_wait_for_dlsch, &curMsgRx->phy_data, &stats_printed);
|
||||
update_trs_info(&curMsgRx->phy_data, &last_trs_slot, curMsgRx->proc.nr_slot_rx);
|
||||
if (ret != INT_MAX)
|
||||
shiftForNextFrame = ret;
|
||||
if (get_nrUE_params()->num_dl_actors > 0) {
|
||||
|
||||
@@ -253,6 +253,13 @@ typedef struct
|
||||
|
||||
} nfapi_nr_ue_pusch_data_t;
|
||||
|
||||
typedef struct csi_payload {
|
||||
uint64_t part1_payload;
|
||||
uint64_t part2_payload;
|
||||
int p1_bits;
|
||||
int p2_bits;
|
||||
} nfapi_nr_ue_csi_payload_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// payloads with fixed array size
|
||||
@@ -260,10 +267,7 @@ typedef struct
|
||||
// vector without L1 implementation
|
||||
uint16_t harq_ack_bit_length;
|
||||
uint64_t harq_payload;
|
||||
uint16_t csi_part1_bit_length;
|
||||
uint64_t csi_part1_payload;
|
||||
uint16_t csi_part2_bit_length;
|
||||
uint64_t csi_part2_payload;
|
||||
nfapi_nr_ue_csi_payload_t csi_payload;
|
||||
uint8_t alpha_scaling; // 0 = 0.5, 1 = 0.65, 2 = 0.8, 3 = 1
|
||||
uint8_t beta_offset_harq_ack;
|
||||
uint8_t beta_offset_csi1;
|
||||
|
||||
@@ -265,6 +265,7 @@ uint32_t calc_power_csirs(const uint16_t *x, const fapi_nr_dl_config_csirs_pdu_r
|
||||
|
||||
static int nr_csi_rs_channel_estimation(
|
||||
const NR_DL_FRAME_PARMS *fp,
|
||||
const int meas_bitmap,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const nr_csi_info_t *nr_csi_info,
|
||||
@@ -317,10 +318,16 @@ static int nr_csi_rs_channel_estimation(
|
||||
const c16_t *tx_csi_rs_signal = &csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset];
|
||||
const c16_t *rx_csi_rs_signal = &csi_rs_received_signal[ant_rx][symbol_offset];
|
||||
c16_t tmp = c16MulConjShift(tx_csi_rs_signal[k], rx_csi_rs_signal[k], nr_csi_info->csi_rs_generated_signal_bits);
|
||||
// This is not just the LS estimation for each (k,l), but also the sum of the different contributions
|
||||
// for the sake of optimizing the memory used.
|
||||
csi_rs_ls_estimated_channel[ant_rx][port_tx][kinit].r += tmp.r;
|
||||
csi_rs_ls_estimated_channel[ant_rx][port_tx][kinit].i += tmp.i;
|
||||
if (csirs_config_pdu->csi_type != 0) {
|
||||
// This is not just the LS estimation for each (k,l), but also the sum of the different contributions
|
||||
// for the sake of optimizing the memory used.
|
||||
csi_rs_ls_estimated_channel[ant_rx][port_tx][kinit].r += tmp.r;
|
||||
csi_rs_ls_estimated_channel[ant_rx][port_tx][kinit].i += tmp.i;
|
||||
} else {
|
||||
// for tracking we want estimates of all sub carriers having CSI-RS
|
||||
csi_rs_ls_estimated_channel[ant_rx][port_tx][k].r = tmp.r;
|
||||
csi_rs_ls_estimated_channel[ant_rx][port_tx][k].i = tmp.i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -381,6 +388,10 @@ static int nr_csi_rs_channel_estimation(
|
||||
}
|
||||
}
|
||||
|
||||
// we need only ls estimates for tracing CSI
|
||||
if (meas_bitmap < 2)
|
||||
continue;
|
||||
|
||||
/// Power noise estimation
|
||||
AssertFatal(csirs_config_pdu->nr_of_rbs > 0, " nr_of_rbs needs to be greater than 0\n");
|
||||
uint16_t noise_real[fp->nb_antennas_rx][csi_mapping->ports][csirs_config_pdu->nr_of_rbs];
|
||||
@@ -425,9 +436,11 @@ static int nr_csi_rs_channel_estimation(
|
||||
|
||||
}
|
||||
|
||||
*noise_power /= (fp->nb_antennas_rx * csi_mapping->ports);
|
||||
*log2_maxh = log2_approx(maxh - 1);
|
||||
*log2_re = log2_approx(count - 1);
|
||||
if (meas_bitmap > 1) {
|
||||
*noise_power /= (fp->nb_antennas_rx * csi_mapping->ports);
|
||||
*log2_maxh = log2_approx(maxh - 1);
|
||||
*log2_re = log2_approx(count - 1);
|
||||
}
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
LOG_I(NR_PHY, "Noise power estimation based on CSI-RS: %i\n", *noise_power);
|
||||
@@ -804,6 +817,75 @@ static void nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue,
|
||||
#endif
|
||||
}
|
||||
|
||||
static double get_cfo(const double phase_diff, const int sym0, const int sym1, const NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
const double one_fs = 1.0 / (fp->samples_per_frame * 100);
|
||||
int sample_count = 0;
|
||||
for (int s = sym0 + 1; s <= sym1; s++) {
|
||||
const int prefix = (s % (7 * (1 << fp->numerology_index))) ? fp->nb_prefix_samples : fp->nb_prefix_samples0;
|
||||
sample_count += (fp->ofdm_symbol_size + prefix);
|
||||
}
|
||||
const double delta_time = sample_count * one_fs;
|
||||
const double cfo = phase_diff / (2 * M_PI * delta_time);
|
||||
return cfo;
|
||||
}
|
||||
|
||||
static void nr_ue_trs_processing(PHY_VARS_NR_UE *ue,
|
||||
const c16_t res0_est[][1][ue->frame_parms.ofdm_symbol_size],
|
||||
const c16_t res1_est[][1][ue->frame_parms.ofdm_symbol_size],
|
||||
const c16_t freq_interp_est[][1][ue->frame_parms.ofdm_symbol_size + FILTER_MARGIN],
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const csi_mapping_parms_t *csi_mapping,
|
||||
const int sym0,
|
||||
const int sym1,
|
||||
int *cfo,
|
||||
int *time_offset)
|
||||
{
|
||||
AssertFatal((sym0 > -1) && (sym1 > -1), "Invalid symbol index for TRS estimation\n");
|
||||
const NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
for (int ant_rx = 0; ant_rx < fp->nb_antennas_rx; ant_rx++) {
|
||||
// CFO estimation
|
||||
double phase_diff = 0.0;
|
||||
int count = 0;
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb + csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
// for freq density 0.5 checks if even or odd RB
|
||||
if (csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int cdm_id = 0; cdm_id < csi_mapping->size; cdm_id++) {
|
||||
// loop over frequency resource elements within a group
|
||||
for (int kp = 0; kp <= csi_mapping->kprime; kp++) {
|
||||
uint16_t kinit = (fp->first_carrier_offset + rb * NR_NB_SC_PER_RB) % fp->ofdm_symbol_size;
|
||||
uint16_t k = kinit + csi_mapping->koverline[cdm_id] + kp;
|
||||
|
||||
// loop over time resource elements within a group
|
||||
for (int lp = 0; lp <= csi_mapping->lprime; lp++) {
|
||||
const c16_t *res0 = res0_est[ant_rx][0];
|
||||
const c16_t *res1 = res1_est[ant_rx][0];
|
||||
double tmp_phase = atan2((double)res1[k].i, (double)res1[k].r) - atan2((double)res0[k].i, (double)res0[k].r);
|
||||
// wrap around phase
|
||||
tmp_phase = (tmp_phase > M_PI) ? tmp_phase - 2 * M_PI : tmp_phase;
|
||||
tmp_phase = (tmp_phase < -M_PI) ? tmp_phase + 2 * M_PI : tmp_phase;
|
||||
phase_diff += tmp_phase;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
phase_diff /= count;
|
||||
*cfo = (int)get_cfo(phase_diff, sym0, sym1, fp);
|
||||
|
||||
// Time offset estimation
|
||||
__attribute__((aligned(32))) c16_t time_est[fp->ofdm_symbol_size];
|
||||
delay_t delay = {0};
|
||||
nr_est_delay(fp->ofdm_symbol_size, freq_interp_est[ant_rx][0], time_est, &delay);
|
||||
*time_offset = delay.delay_max_pos;
|
||||
// estimate only for first antenna port
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
@@ -827,7 +909,10 @@ void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue,
|
||||
void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu)
|
||||
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
c16_t trs_estimates[][1][ue->frame_parms.ofdm_symbol_size],
|
||||
const int res_idx,
|
||||
const int trs_sym0)
|
||||
{
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
@@ -847,11 +932,6 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
LOG_I(NR_PHY, "csirs_config_pdu->power_control_offset_ss = %i\n", csirs_config_pdu->power_control_offset_ss);
|
||||
#endif
|
||||
|
||||
if(csirs_config_pdu->csi_type == 0) {
|
||||
LOG_E(NR_PHY, "Handling of CSI-RS for tracking not handled yet at PHY\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(csirs_config_pdu->csi_type == 2) {
|
||||
LOG_E(NR_PHY, "Handling of ZP CSI-RS not handled yet at PHY\n");
|
||||
return;
|
||||
@@ -904,31 +984,26 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
&rsrp_dBm,
|
||||
rxdataF);
|
||||
|
||||
|
||||
if (csirs_config_pdu->measurement_bitmap == 0) {
|
||||
LOG_D(NR_PHY, "No CSI-RS measurements configured\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t noise_power = 0;
|
||||
int16_t log2_re = 0;
|
||||
int16_t log2_maxh = 0;
|
||||
// if we need to measure only RSRP no need to do channel estimation
|
||||
if (csirs_config_pdu->measurement_bitmap > 1)
|
||||
nr_csi_rs_channel_estimation(frame_parms,
|
||||
proc,
|
||||
csirs_config_pdu,
|
||||
csi_info,
|
||||
(const c16_t **)csi_info->csi_rs_generated_signal,
|
||||
csi_rs_received_signal,
|
||||
&mapping_parms,
|
||||
CDM_group_size,
|
||||
mem_offset,
|
||||
csi_rs_ls_estimated_channel,
|
||||
csi_rs_estimated_channel_freq,
|
||||
&log2_re,
|
||||
&log2_maxh,
|
||||
&noise_power);
|
||||
const bool use_trs_buff = (csirs_config_pdu->csi_type == 0 && res_idx == 0);
|
||||
nr_csi_rs_channel_estimation(frame_parms,
|
||||
csirs_config_pdu->measurement_bitmap,
|
||||
proc,
|
||||
csirs_config_pdu,
|
||||
csi_info,
|
||||
(const c16_t **)csi_info->csi_rs_generated_signal,
|
||||
csi_rs_received_signal,
|
||||
&mapping_parms,
|
||||
CDM_group_size,
|
||||
mem_offset,
|
||||
(use_trs_buff) ? trs_estimates : csi_rs_ls_estimated_channel,
|
||||
csi_rs_estimated_channel_freq,
|
||||
&log2_re,
|
||||
&log2_maxh,
|
||||
&noise_power);
|
||||
|
||||
uint8_t rank_indicator = 0;
|
||||
// bit 1 in bitmap to indicate RI measurment
|
||||
@@ -967,9 +1042,54 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
nr_csi_rs_cqi_estimation(precoded_sinr_dB, &cqi);
|
||||
}
|
||||
|
||||
int trs_cfo = 0;
|
||||
int trs_time = 0;
|
||||
const bool do_trs_est = (csirs_config_pdu->csi_type == 0) && (res_idx == 1);
|
||||
if (do_trs_est) {
|
||||
start_meas_nr_ue_phy(ue, TRS_PROCESSING);
|
||||
nr_ue_trs_processing(ue,
|
||||
trs_estimates,
|
||||
csi_rs_ls_estimated_channel,
|
||||
csi_rs_estimated_channel_freq,
|
||||
csirs_config_pdu,
|
||||
&mapping_parms,
|
||||
trs_sym0,
|
||||
csirs_config_pdu->symb_l0,
|
||||
&trs_cfo,
|
||||
&trs_time);
|
||||
stop_meas_nr_ue_phy(ue, TRS_PROCESSING);
|
||||
for (int i = 0; i < NUM_TRS_SLOT; i++) {
|
||||
if (ue->trs_cfo[i].valid)
|
||||
continue;
|
||||
ue->trs_cfo[i].cfo = trs_cfo;
|
||||
ue->trs_cfo[i].valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// dump csi estimates for csi tracking resource in slot
|
||||
if (csirs_config_pdu->csi_type == 0 && proc->frame_rx == 344) {
|
||||
char fname[40];
|
||||
snprintf(fname, sizeof(fname), "trs_slot%d_sym%d", proc->nr_slot_rx, csirs_config_pdu->symb_l0);
|
||||
if (do_trs_est)
|
||||
LOG_M(fname, "trs", csi_rs_ls_estimated_channel[0][0], frame_parms->ofdm_symbol_size, 1, 1 | MATLAB_RAW);
|
||||
else
|
||||
LOG_M(fname, "trs", trs_estimates[0][0], frame_parms->ofdm_symbol_size, 1, 1 | MATLAB_RAW);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (csirs_config_pdu->measurement_bitmap) {
|
||||
case 1 :
|
||||
LOG_I(NR_PHY, "[UE %d] RSRP = %i dBm\n", ue->Mod_id, rsrp_dBm);
|
||||
case 0:
|
||||
if (do_trs_est)
|
||||
LOG_I(NR_PHY,
|
||||
"%d.%d TRS estimated CFO: %d Hz, estimated time offset: %d samples\n",
|
||||
proc->frame_rx,
|
||||
proc->nr_slot_rx,
|
||||
trs_cfo,
|
||||
trs_time);
|
||||
break;
|
||||
case 1:
|
||||
LOG_I(NR_PHY, "%d.%d [UE %d] RSRP = %i dBm\n", proc->frame_rx, proc->nr_slot_rx, ue->Mod_id, rsrp_dBm);
|
||||
break;
|
||||
case 26 :
|
||||
LOG_I(NR_PHY, "RI = %i i1 = %i.%i.%i, i2 = %i, SINR = %i dB, CQI = %i\n",
|
||||
|
||||
@@ -398,12 +398,6 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
LOG_D(PHY, "nr_initial sync ue RB_DL %d\n", fp->N_RB_DL);
|
||||
|
||||
if (res) {
|
||||
// digital compensation of FFO for SSB symbols
|
||||
if (res->freqOffset && ue->UE_fo_compensation) {
|
||||
// In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1
|
||||
// and we do not know yet in which slot it goes.
|
||||
compensate_freq_offset(ue->common_vars.rxdata, fp, res->freqOffset, res->syncRes.frame_id);
|
||||
}
|
||||
// sync at symbol ue->symbol_offset
|
||||
// computing the offset wrt the beginning of the frame
|
||||
int mu = fp->numerology_index;
|
||||
|
||||
@@ -152,6 +152,10 @@ typedef struct {
|
||||
uint16_t E_uci_ACK; // number of coded HARQ-ACK bits
|
||||
uint16_t Q_dash_ACK_rvd; // number of coded HARQ-ACK symbols reserved
|
||||
uint16_t E_uci_ACK_rvd; // number of coded HARQ-ACK bits reserved
|
||||
uint16_t Q_dash_CSI1; // number of coded CSI part 1 symbols
|
||||
uint16_t E_uci_CSI1; // number of coded CSI part 1 bits
|
||||
uint16_t Q_dash_CSI2; // number of coded CSI part 2 symbols
|
||||
uint16_t E_uci_CSI2; // number of coded CSI part 2 bits
|
||||
uint32_t G_ulsch; // bit capacity of ULSCH
|
||||
} rate_match_info_uci_t;
|
||||
|
||||
|
||||
@@ -517,6 +517,99 @@ static void map_symbols(const nr_phy_pxsch_params_t p,
|
||||
}
|
||||
}
|
||||
|
||||
// Function to lookup beta offset value from Table 9.3-2 in TS 38.213
|
||||
static double get_beta_offset_csi(const uint8_t beta_offset_idx)
|
||||
{
|
||||
static const double beta_offset_values[19] = {1.125,
|
||||
1.250,
|
||||
1.375,
|
||||
1.625,
|
||||
1.750,
|
||||
2.000,
|
||||
2.250,
|
||||
2.500,
|
||||
2.875,
|
||||
3.125,
|
||||
3.500,
|
||||
4.000,
|
||||
5.000,
|
||||
6.250,
|
||||
8.000,
|
||||
10.000,
|
||||
12.625,
|
||||
15.875,
|
||||
20.000};
|
||||
|
||||
if (beta_offset_idx >= sizeofArray(beta_offset_values)) {
|
||||
LOG_E(PHY, "Invalid beta_offset_index %d, using default value\n", beta_offset_idx);
|
||||
return beta_offset_values[9];
|
||||
}
|
||||
|
||||
return beta_offset_values[beta_offset_idx];
|
||||
}
|
||||
|
||||
/*
|
||||
* This function maps the CSI part 1 bits
|
||||
*/
|
||||
static void map_csi(uci_on_pusch_bit_type_t *template,
|
||||
const nfapi_nr_ue_pusch_pdu_t *pusch_pdu,
|
||||
const bool is_csi1,
|
||||
uint16_t G_csi,
|
||||
uint8_t l1_c,
|
||||
const uint32_t *m_uci_current,
|
||||
const uint32_t *m_ulsch_initial)
|
||||
{
|
||||
const uint8_t n_symbols = pusch_pdu->nr_of_symbols;
|
||||
const uint32_t nlqm = pusch_pdu->qam_mod_order * pusch_pdu->nrOfLayers;
|
||||
|
||||
uint32_t symbol_start_bit_idx[NR_SYMBOLS_PER_SLOT] = {0};
|
||||
for (uint8_t s = 1; s < n_symbols; s++) {
|
||||
symbol_start_bit_idx[s] = symbol_start_bit_idx[s - 1] + (m_ulsch_initial[s - 1] * nlqm);
|
||||
}
|
||||
|
||||
uint32_t total_placed = 0;
|
||||
for (uint8_t sym = l1_c; sym < n_symbols && total_placed < G_csi; sym++) {
|
||||
const uint32_t uci_re_on_sym = m_uci_current[sym];
|
||||
|
||||
if (uci_re_on_sym <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint32_t remaining_to_place = G_csi - total_placed;
|
||||
uint32_t d_factor_re;
|
||||
const uint32_t num_re_to_select = ceil((double)remaining_to_place / nlqm);
|
||||
|
||||
if (num_re_to_select >= uci_re_on_sym) {
|
||||
d_factor_re = 1;
|
||||
} else {
|
||||
d_factor_re = floor((double)uci_re_on_sym / num_re_to_select);
|
||||
if (d_factor_re == 0) {
|
||||
d_factor_re = 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t re_offset = 0;
|
||||
while (re_offset < uci_re_on_sym && total_placed < G_csi) {
|
||||
if (template[symbol_start_bit_idx[sym] + (re_offset * nlqm)] != BIT_TYPE_ULSCH) {
|
||||
re_offset++;
|
||||
continue; // if RE already allocated to UCI or reserved for ACK
|
||||
}
|
||||
for (uint32_t bit_in_re = 0; bit_in_re < nlqm; bit_in_re++) {
|
||||
if (total_placed >= G_csi) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t bit_offset_in_sym = (re_offset * nlqm) + bit_in_re;
|
||||
uint32_t cw_idx = symbol_start_bit_idx[sym] + bit_offset_in_sym;
|
||||
template[cw_idx] = is_csi1 ? BIT_TYPE_CSI1 : BIT_TYPE_CSI2;
|
||||
|
||||
total_placed++;
|
||||
}
|
||||
re_offset += d_factor_re;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to lookup beta offset value from Table 9.3-1 in TS 38.213
|
||||
static double get_beta_offset_harq_ack(uint8_t beta_offset_index)
|
||||
{
|
||||
@@ -586,13 +679,19 @@ static int get_crc_uci(const uint16_t ouci)
|
||||
return L;
|
||||
}
|
||||
|
||||
static uint16_t get_Qd(const uint16_t oack, double beta, double alpha, const uint32_t sumKr, const uint32_t s1, const uint32_t s2)
|
||||
static uint16_t get_Qd(const uint16_t oack,
|
||||
double beta,
|
||||
double alpha,
|
||||
const uint32_t sumKr,
|
||||
const uint32_t s1,
|
||||
const uint32_t s2,
|
||||
const uint32_t sub)
|
||||
{
|
||||
if (oack == 0)
|
||||
return 0;
|
||||
|
||||
uint16_t first_term = ceil(((double)oack + get_crc_uci(oack)) * (double)beta * s1 / sumKr);
|
||||
uint16_t second_term = ceil(alpha * s2);
|
||||
uint16_t second_term = ceil(alpha * s2) - sub;
|
||||
|
||||
return (first_term < second_term) ? first_term : second_term;
|
||||
}
|
||||
@@ -661,26 +760,41 @@ static rate_match_info_uci_t calc_rate_match_info_uci(const nfapi_nr_ue_pusch_pd
|
||||
rate_match_info_uci_t rminfo = {0};
|
||||
|
||||
// get the number of coded HARQ-ACK symbols and bits, TS 38.212 section 6.3.2.4.1.1
|
||||
rminfo.Q_dash_ACK = get_Qd(oack, beta, alpha, sumKr, s1, s2);
|
||||
rminfo.Q_dash_ACK = get_Qd(oack, beta, alpha, sumKr, s1, s2, 0);
|
||||
rminfo.E_uci_ACK = rminfo.Q_dash_ACK * nlqm;
|
||||
|
||||
if (oack_rvd > 0) {
|
||||
rminfo.Q_dash_ACK_rvd = get_Qd(oack_rvd, beta, alpha, sumKr, s1, s2);
|
||||
rminfo.Q_dash_ACK_rvd = get_Qd(oack_rvd, beta, alpha, sumKr, s1, s2, 0);
|
||||
rminfo.E_uci_ACK_rvd = rminfo.Q_dash_ACK_rvd * nlqm;
|
||||
}
|
||||
|
||||
// get beta offset for csi
|
||||
const double beta_csi1 = get_beta_offset_csi(pusch_pdu->pusch_uci.beta_offset_csi1);
|
||||
|
||||
// get the number of coded CSI part 1 symbols and bits, TS 38.212 section 6.3.2.4.1.2
|
||||
const uint16_t ocsi1 = pusch_pdu->pusch_uci.csi_payload.p1_bits;
|
||||
rminfo.Q_dash_CSI1 = get_Qd(ocsi1, beta_csi1, alpha, sumKr, s1, s1, rminfo.Q_dash_ACK);
|
||||
rminfo.E_uci_CSI1 = rminfo.Q_dash_CSI1 * nlqm;
|
||||
|
||||
// get the number of coded CSI part 1 symbols and bits, TS 38.212 section 6.3.2.4.1.3
|
||||
const double beta_csi2 = get_beta_offset_csi(pusch_pdu->pusch_uci.beta_offset_csi2);
|
||||
const uint16_t ocsi2 = pusch_pdu->pusch_uci.csi_payload.p2_bits;
|
||||
rminfo.Q_dash_CSI2 = get_Qd(ocsi2, beta_csi2, alpha, sumKr, s1, s1, rminfo.Q_dash_ACK + rminfo.Q_dash_CSI1);
|
||||
rminfo.E_uci_CSI2 = rminfo.Q_dash_CSI2 * nlqm;
|
||||
|
||||
rminfo.G_ulsch = *G - (rminfo.E_uci_CSI1 + rminfo.E_uci_CSI2);
|
||||
if (oack_rvd == 0) {
|
||||
rminfo.G_ulsch = *G - rminfo.E_uci_ACK;
|
||||
} else {
|
||||
rminfo.G_ulsch = *G;
|
||||
rminfo.G_ulsch -= rminfo.E_uci_ACK;
|
||||
}
|
||||
|
||||
*G = rminfo.G_ulsch;
|
||||
LOG_D(PHY, "[UCI_RATE_MATCH] sumKr=%u, s1=%u, s2=%u, Final G_ulsch (output G): %u\n", sumKr, s1, s2, *G);
|
||||
LOG_D(PHY,
|
||||
"[UCI_RATE_MATCH] rate matching info returned: E_uci_ACK=%u, E_uci_ACK_rvd=%u, G_ulsch=%u\n",
|
||||
LOG_I(PHY,
|
||||
"[UCI_RATE_MATCH] rate matching info returned: E_uci_ACK=%u, E_uci_ACK_rvd=%u, E_uci_CSI1=%u, E_uci_CSI2=%u, G_ulsch=%u\n",
|
||||
rminfo.E_uci_ACK,
|
||||
rminfo.E_uci_ACK_rvd,
|
||||
rminfo.E_uci_CSI1,
|
||||
rminfo.E_uci_CSI2,
|
||||
rminfo.G_ulsch);
|
||||
|
||||
return rminfo;
|
||||
@@ -909,11 +1023,17 @@ static void apply_template_to_codeword(uint8_t *codeword,
|
||||
uint32_t codeword_len,
|
||||
const uint8_t *ulsch_bits,
|
||||
const uint64_t *cack,
|
||||
const uint64_t *csi1,
|
||||
const uint64_t *csi2,
|
||||
uint16_t G_ack,
|
||||
uint32_t G_csi1,
|
||||
uint32_t G_csi2,
|
||||
uint32_t G_ulsch)
|
||||
{
|
||||
uint32_t ulsch_idx = 0;
|
||||
uint32_t ack_idx = 0;
|
||||
uint32_t csi1_idx = 0;
|
||||
uint32_t csi2_idx = 0;
|
||||
|
||||
for (uint32_t i = 0; i < codeword_len; i++) {
|
||||
switch (template[i]) {
|
||||
@@ -935,6 +1055,24 @@ static void apply_template_to_codeword(uint8_t *codeword,
|
||||
}
|
||||
break;
|
||||
|
||||
case BIT_TYPE_CSI1:
|
||||
if (G_csi1 > 0 && csi1_idx < G_csi1) {
|
||||
uint32_t word_idx = csi1_idx / 64;
|
||||
uint32_t bit_in_word_idx = csi1_idx % 64;
|
||||
codeword[i] = (csi1[word_idx] >> bit_in_word_idx) & 1;
|
||||
csi1_idx++;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIT_TYPE_CSI2:
|
||||
if (G_csi2 > 0 && csi2_idx < G_csi2) {
|
||||
uint32_t word_idx = csi2_idx / 64;
|
||||
uint32_t bit_in_word_idx = csi2_idx % 64;
|
||||
codeword[i] = (csi2[word_idx] >> bit_in_word_idx) & 1;
|
||||
csi2_idx++;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIT_TYPE_ACK_RESERVED:
|
||||
case BIT_TYPE_ULSCH:
|
||||
default:
|
||||
@@ -957,10 +1095,14 @@ static uci_on_pusch_bit_type_t *nr_data_control_mapping(const nfapi_nr_ue_pusch_
|
||||
unsigned int G_ulsch,
|
||||
uint16_t G_ack,
|
||||
uint32_t G_ack_rvd,
|
||||
uint32_t G_csi1,
|
||||
uint32_t G_csi2,
|
||||
uint8_t *codeword,
|
||||
uint32_t codeword_len,
|
||||
const uint8_t *ulsch_bits,
|
||||
const uint64_t *cack)
|
||||
const uint64_t *cack,
|
||||
const uint64_t *csi1,
|
||||
const uint64_t *csi2)
|
||||
{
|
||||
if (!pusch_pdu || !codeword || codeword_len == 0 || !template)
|
||||
return NULL;
|
||||
@@ -1002,11 +1144,16 @@ static uci_on_pusch_bit_type_t *nr_data_control_mapping(const nfapi_nr_ue_pusch_
|
||||
map_non_overlapped_ack(template, pusch_pdu, G_ack, l1_c, m_uci_current, m_ulsch_initial);
|
||||
}
|
||||
|
||||
// CSI part 1
|
||||
map_csi(template, pusch_pdu, true, G_csi1, first_non_dmrs_sym, m_uci_current, m_ulsch_initial);
|
||||
// CSI part 2
|
||||
map_csi(template, pusch_pdu, false, G_csi2, first_non_dmrs_sym, m_uci_current, m_ulsch_initial);
|
||||
|
||||
if (G_ack > 0 && G_ack_rvd > 0) {
|
||||
map_overlapped_ack(template, G_ack, l1_c, n_symbols, positions_by_sym, count_by_sym);
|
||||
}
|
||||
|
||||
apply_template_to_codeword(codeword, template, codeword_len, ulsch_bits, cack, G_ack, G_ulsch);
|
||||
apply_template_to_codeword(codeword, template, codeword_len, ulsch_bits, cack, csi1, csi2, G_ack, G_csi1, G_csi2, G_ulsch);
|
||||
|
||||
return template;
|
||||
}
|
||||
@@ -1106,7 +1253,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
return;
|
||||
}
|
||||
|
||||
if (pusch_pdu->pusch_uci.harq_ack_bit_length != 0) {
|
||||
bool uci_present = (pusch_pdu->pusch_uci.harq_ack_bit_length != 0) || (pusch_pdu->pusch_uci.csi_payload.p1_bits != 0);
|
||||
if (uci_present) {
|
||||
rm_info = calc_rate_match_info_uci(pusch_pdu, harq_process_ul_ue, nl_qm, &G[pusch_id]);
|
||||
}
|
||||
|
||||
@@ -1123,12 +1271,10 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
int N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig
|
||||
|
||||
if (pusch_pdu->pusch_uci.harq_ack_bit_length != 0) {
|
||||
LOG_D(PHY, "[UCI_ON_PUSCH] Original HARQ-ACK bit length: %u\n", pusch_pdu->pusch_uci.harq_ack_bit_length);
|
||||
LOG_D(PHY, "[UCI_ON_PUSCH] Initial G: %u\n", G_initial_total_pusch_bits);
|
||||
// b is the block of bits transmitted on the physical channel after payload coding
|
||||
uint64_t b[16] = {0}; // limit to 1024-bit encoded length
|
||||
// b is the block of bits transmitted on the physical channel after payload coding
|
||||
uint64_t b_ack[16] = {0}; // limit to 1024-bit encoded length
|
||||
|
||||
if (pusch_pdu->pusch_uci.harq_ack_bit_length != 0) {
|
||||
if (pucch_pdu == NULL) {
|
||||
LOG_E(PHY, "nr_ue_ulsch_procedures: pucch_pdu is NULL but HARQ-ACK is present. Cannot proceed with UCI encoding.\n");
|
||||
stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
|
||||
@@ -1141,7 +1287,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
true,
|
||||
rm_info.E_uci_ACK,
|
||||
mod_order,
|
||||
&b[0]);
|
||||
&b_ack[0]);
|
||||
|
||||
LOG_D(PHY,
|
||||
"[UCI_ON_PUSCH] G_ulsch=%u (updated G[pusch_id]), G_ack=%u (M_bit), G_ack_rvd=%u, total_len=%u "
|
||||
@@ -1150,7 +1296,34 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
rm_info.E_uci_ACK,
|
||||
rm_info.E_uci_ACK_rvd,
|
||||
G_initial_total_pusch_bits);
|
||||
uci_present |= true;
|
||||
}
|
||||
|
||||
uint64_t b_csi1[16] = {0}; // limit to 1024-bit encoded length
|
||||
uint64_t b_csi2[16] = {0}; // limit to 1024-bit encoded length
|
||||
if (pusch_pdu->pusch_uci.csi_payload.p1_bits != 0) {
|
||||
nr_uci_encoding(pusch_pdu->pusch_uci.csi_payload.part1_payload,
|
||||
pusch_pdu->pusch_uci.csi_payload.p1_bits,
|
||||
pucch_pdu->prb_size,
|
||||
true,
|
||||
rm_info.E_uci_CSI1,
|
||||
mod_order,
|
||||
&b_csi1[0]);
|
||||
|
||||
uci_present |= true;
|
||||
|
||||
// Process CSI Part 2 if any
|
||||
if (pusch_pdu->pusch_uci.csi_payload.p2_bits > 0)
|
||||
nr_uci_encoding(pusch_pdu->pusch_uci.csi_payload.part2_payload,
|
||||
pusch_pdu->pusch_uci.csi_payload.p2_bits,
|
||||
pucch_pdu->prb_size,
|
||||
true,
|
||||
rm_info.E_uci_CSI2,
|
||||
mod_order,
|
||||
&b_csi2[0]);
|
||||
}
|
||||
|
||||
if (uci_present) {
|
||||
uint8_t temp_codeword[G_initial_total_pusch_bits];
|
||||
start_meas_nr_ue_phy(UE, UCI_ON_PUSCH_MAPPING);
|
||||
nr_data_control_mapping(pusch_pdu,
|
||||
@@ -1158,18 +1331,19 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
G[pusch_id],
|
||||
rm_info.E_uci_ACK,
|
||||
rm_info.E_uci_ACK_rvd,
|
||||
rm_info.E_uci_CSI1,
|
||||
rm_info.E_uci_CSI2,
|
||||
temp_codeword,
|
||||
G_initial_total_pusch_bits,
|
||||
harq_process_ul_ue->f,
|
||||
b);
|
||||
b_ack,
|
||||
b_csi1,
|
||||
b_csi2);
|
||||
stop_meas_nr_ue_phy(UE, UCI_ON_PUSCH_MAPPING);
|
||||
memcpy(harq_process_ul_ue->f, temp_codeword, G_initial_total_pusch_bits);
|
||||
uci_mapping_template = template_buffer;
|
||||
}
|
||||
|
||||
AssertFatal(pusch_pdu->pusch_uci.csi_part1_bit_length == 0 && pusch_pdu->pusch_uci.csi_part2_bit_length == 0,
|
||||
"UCI (CSI) on PUSCH not supported at PHY\n");
|
||||
|
||||
uint16_t start_rb = pusch_pdu->rb_start;
|
||||
uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB;
|
||||
|
||||
@@ -1202,7 +1376,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
/////////////////////////ULSCH scrambling/////////////////////////
|
||||
|
||||
uint32_t available_bits;
|
||||
bool is_uci_on_pusch = (pusch_pdu->pusch_uci.harq_ack_bit_length != 0);
|
||||
bool is_uci_on_pusch = (pusch_pdu->pusch_uci.harq_ack_bit_length != 0 || pusch_pdu->pusch_uci.csi_payload.p1_bits != 0);
|
||||
|
||||
if (is_uci_on_pusch) {
|
||||
// UCI on PUSCH is present, so available bits are the total codeword length
|
||||
|
||||
@@ -91,6 +91,13 @@
|
||||
// (0 + 0 * 20) % 512 = 0
|
||||
#define NUM_PROCESS_SLOT_TX_BARRIERS 512
|
||||
|
||||
// CSI for tracking can have up to 2 resources per slot
|
||||
#define MAX_CSI_RES_SLOT 2
|
||||
// Number of consequtive slots carrying TRS
|
||||
#define NUM_TRS_SLOT 2
|
||||
// Threshold to change radio frequency
|
||||
#define TRS_CFO_THRESH 500
|
||||
|
||||
#include "impl_defs_top.h"
|
||||
#include "impl_defs_nr.h"
|
||||
#include "time_meas.h"
|
||||
@@ -334,6 +341,11 @@ typedef struct {
|
||||
fapi_nr_dl_ntn_config_command_pdu ntn_config_params;
|
||||
} ntn_config_message_t;
|
||||
|
||||
typedef struct {
|
||||
_Atomic bool valid;
|
||||
int cfo;
|
||||
} trs_cfo_t;
|
||||
|
||||
/// Top-level PHY Data Structure for UE
|
||||
typedef struct PHY_VARS_NR_UE_s {
|
||||
openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
@@ -465,6 +477,9 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
double freq_offset; /// currently compensated frequency offset
|
||||
double freq_off_acc; /// accumulated frequency error (for PI controller)
|
||||
|
||||
/// Frequency offset estimated from TRS
|
||||
trs_cfo_t trs_cfo[NUM_TRS_SLOT];
|
||||
|
||||
/// Timing Advance updates variables
|
||||
/// Timing advance update computed from the TA command signalled from gNB
|
||||
int timing_advance;
|
||||
@@ -589,7 +604,9 @@ typedef struct nr_phy_data_s {
|
||||
|
||||
// Sidelink Rx action decided by MAC
|
||||
sl_nr_rx_config_type_enum_t sl_rx_action;
|
||||
NR_UE_CSI_RS csirs_vars;
|
||||
int num_csirs;
|
||||
NR_UE_CSI_RS csirs_vars[MAX_CSI_RES_SLOT];
|
||||
bool is_last_trs_slot;
|
||||
NR_UE_CSI_IM csiim_vars;
|
||||
} nr_phy_data_t;
|
||||
|
||||
|
||||
@@ -54,7 +54,8 @@
|
||||
FN(ULSCH_INTERLEAVING_STATS),\
|
||||
FN(ULSCH_ENCODING_STATS),\
|
||||
FN(OFDM_MOD_STATS),\
|
||||
FN(PRACH_GEN_STATS)
|
||||
FN(PRACH_GEN_STATS),\
|
||||
FN(TRS_PROCESSING)
|
||||
|
||||
typedef enum {
|
||||
FOREACH_NR_PHY_CPU_MEAS(NOOP),
|
||||
|
||||
@@ -163,7 +163,12 @@ void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue,
|
||||
void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu);
|
||||
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
c16_t trs_estimates[][1][ue->frame_parms.ofdm_symbol_size],
|
||||
const int res_idx,
|
||||
const int trs_sym0);
|
||||
|
||||
void trs_freq_correction(PHY_VARS_NR_UE *ue);
|
||||
|
||||
int psbch_pscch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
|
||||
void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txp);
|
||||
|
||||
@@ -193,8 +193,15 @@ static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac,
|
||||
phy_data->csiim_vars.active = true;
|
||||
break;
|
||||
case FAPI_NR_DL_CONFIG_TYPE_CSI_RS:
|
||||
phy_data->csirs_vars.csirs_config_pdu = pdu->csirs_config_pdu.csirs_config_rel15;
|
||||
phy_data->csirs_vars.active = true;
|
||||
AssertFatal(phy_data->num_csirs < MAX_CSI_RES_SLOT, "CSI resources per slot exceeded limit\n");
|
||||
const int c = phy_data->num_csirs;
|
||||
if (phy_data->csirs_vars[c].active) {
|
||||
AssertFatal(false, "Resource should not be active before its configured\n");
|
||||
continue;
|
||||
}
|
||||
phy_data->csirs_vars[c].csirs_config_pdu = pdu->csirs_config_pdu.csirs_config_rel15;
|
||||
phy_data->csirs_vars[c].active = true;
|
||||
phy_data->num_csirs++;
|
||||
break;
|
||||
case FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH: {
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15;
|
||||
|
||||
@@ -1218,16 +1218,35 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
|
||||
}
|
||||
|
||||
// do procedures for CSI-RS
|
||||
if (phy_data->csirs_vars.active == 1) {
|
||||
for(int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) {
|
||||
if(is_csi_rs_in_symbol(phy_data->csirs_vars.csirs_config_pdu, symb)) {
|
||||
if (!slot_fep_map[symb]) {
|
||||
nr_slot_fep(ue, &ue->frame_parms, proc->nr_slot_rx, symb, rxdataF, link_type_dl, 0, ue->common_vars.rxdata);
|
||||
slot_fep_map[symb] = true;
|
||||
{
|
||||
/*
|
||||
CSI-RS for tracking use only one port.
|
||||
Number of CSI-RS resources for tracking is always 2 per slot.
|
||||
Computed estimates from first resource is saved and used while estimating second resource.
|
||||
*/
|
||||
c16_t trs_estimates[ue->frame_parms.nb_antennas_rx][1][ue->frame_parms.ofdm_symbol_size];
|
||||
for (int res = 0; res < MAX_CSI_RES_SLOT; res++) {
|
||||
if (phy_data->csirs_vars[res].active == 1) {
|
||||
for (int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) {
|
||||
if (is_csi_rs_in_symbol(phy_data->csirs_vars[res].csirs_config_pdu, symb)) {
|
||||
if (!slot_fep_map[symb]) {
|
||||
nr_slot_fep(ue, &ue->frame_parms, proc->nr_slot_rx, symb, rxdataF, link_type_dl, 0, ue->common_vars.rxdata);
|
||||
slot_fep_map[symb] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
nr_ue_csi_rs_procedures(ue,
|
||||
proc,
|
||||
rxdataF,
|
||||
&phy_data->csirs_vars[res].csirs_config_pdu,
|
||||
trs_estimates,
|
||||
res,
|
||||
(res == 1) ? phy_data->csirs_vars[0].csirs_config_pdu.symb_l0 : -1);
|
||||
}
|
||||
}
|
||||
nr_ue_csi_rs_procedures(ue, proc, rxdataF, &phy_data->csirs_vars.csirs_config_pdu);
|
||||
if (!get_nrUE_params()->cont_fo_comp && phy_data->is_last_trs_slot) {
|
||||
trs_freq_correction(ue);
|
||||
}
|
||||
}
|
||||
|
||||
if (dlsch[0].active) {
|
||||
|
||||
@@ -187,3 +187,7 @@ void nr_mac_rrc_meas_ind_ue(module_id_t module_id,
|
||||
int rsrp_dBm)
|
||||
{
|
||||
}
|
||||
|
||||
void trs_freq_correction(PHY_VARS_NR_UE *ue)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -249,15 +249,15 @@ static void prepare_ue_pusch_pdu_from_matlab_vector(const bool uci_on_pusch,
|
||||
p_vec_bits += var.A;
|
||||
copy_bytes_to_packed_bits(p_vec_bits, var.oack, false, pb);
|
||||
|
||||
pusch_config_pdu->pusch_uci.csi_part1_bit_length = var.ocsi1;
|
||||
pb = (uint8_t *)&pusch_config_pdu->pusch_uci.csi_part1_payload;
|
||||
memset(pb, 0, sizeof(pusch_config_pdu->pusch_uci.csi_part1_payload));
|
||||
pusch_config_pdu->pusch_uci.csi_payload.p1_bits = var.ocsi1;
|
||||
pb = (uint8_t *)&pusch_config_pdu->pusch_uci.csi_payload.part1_payload;
|
||||
memset(pb, 0, sizeof(pusch_config_pdu->pusch_uci.csi_payload.part1_payload));
|
||||
p_vec_bits += var.oack;
|
||||
copy_bytes_to_packed_bits(p_vec_bits, var.ocsi1, false, pb);
|
||||
|
||||
pusch_config_pdu->pusch_uci.csi_part2_bit_length = var.ocsi2;
|
||||
pb = (uint8_t *)&pusch_config_pdu->pusch_uci.csi_part2_payload;
|
||||
memset(pb, 0, sizeof(pusch_config_pdu->pusch_uci.csi_part2_payload));
|
||||
pusch_config_pdu->pusch_uci.csi_payload.p2_bits = var.ocsi2;
|
||||
pb = (uint8_t *)&pusch_config_pdu->pusch_uci.csi_payload.part2_payload;
|
||||
memset(pb, 0, sizeof(pusch_config_pdu->pusch_uci.csi_payload.part2_payload));
|
||||
p_vec_bits += var.ocsi1;
|
||||
copy_bytes_to_packed_bits(p_vec_bits, var.ocsi2, false, pb);
|
||||
}
|
||||
@@ -1347,9 +1347,7 @@ int main(int argc, char *argv[])
|
||||
.beta_offset_harq_ack = 11,
|
||||
.harq_ack_bit_length = 3,
|
||||
.harq_payload = 3,
|
||||
//.csi_part1_bit_length = 4,
|
||||
//.csi_part1_payload = 15
|
||||
};
|
||||
.csi_payload = {.p1_bits = 4, .part1_payload = 15, .p2_bits = 4, .part2_payload = 15}};
|
||||
pusch_config_pdu->pusch_uci = pusch_uci;
|
||||
prepare_ue_pusch_pdu_from_matlab_vector(uci_on_pusch, uci_ulsch_matlab_vec, pusch_config_pdu, cw_buf);
|
||||
}
|
||||
@@ -1620,7 +1618,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
}
|
||||
round++;
|
||||
if (uci_on_pusch && uci_ulsch_matlab_vec && (errors_scrambling[round] == 0)) {
|
||||
ret = 0;
|
||||
printf("*************\n");
|
||||
@@ -1628,6 +1625,7 @@ int main(int argc, char *argv[])
|
||||
printf("*************\n");
|
||||
break;
|
||||
}
|
||||
round++;
|
||||
} // round
|
||||
|
||||
if (n_trials == 1 && errors_scrambling[0] > 0) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
% ulsim command for same pusch config
|
||||
% ./nr_ulsim -m 27 -u 1 -R 51 -r 51 -s 300 -o uci_on_pusch_7.bin
|
||||
% ./nr_ulsim -m 27 -u 1 -R 51 -r 51 -s 300 -ouci_on_pusch_oack3_ocsi14_ocsi20.bin
|
||||
|
||||
carrier = nrCarrierConfig;
|
||||
carrier.NSizeGrid = 51;
|
||||
@@ -32,7 +32,7 @@ pusch.DMRS.SequenceHopping = 0;
|
||||
|
||||
pusch.BetaOffsetACK = 20;
|
||||
pusch.BetaOffsetCSI1 = 6.25;
|
||||
pusch.BetaOffsetCSI2 = 1;
|
||||
pusch.BetaOffsetCSI2 = 6.25;
|
||||
pusch.UCIScaling = 1;
|
||||
|
||||
A = 37896;
|
||||
@@ -41,17 +41,17 @@ rv = 0;
|
||||
modulation = pusch.Modulation;
|
||||
nlayers = pusch.NumLayers; % Number of layers for decoding
|
||||
|
||||
oack = 7;
|
||||
ocsi1 = 0;
|
||||
ocsi2 = 0;
|
||||
oack = 3;
|
||||
ocsi1 = 4;
|
||||
ocsi2 = 4;
|
||||
cbsInfo = nrULSCHInfo(pusch, rate, A, oack, ocsi1, ocsi2); % Get ULSCH information
|
||||
|
||||
ack = randi([0 1],oack,1);
|
||||
csi1 = randi([0 1],ocsi1,1);
|
||||
csi2 = randi([0 1],ocsi2,1);
|
||||
cack = nrUCIEncode(ack,cbsInfo.GACK,pusch.Modulation);
|
||||
ccsi1 = [];
|
||||
ccsi2 = [];
|
||||
ccsi1 = nrUCIEncode(csi1,cbsInfo.GCSI1,pusch.Modulation);
|
||||
ccsi2 = nrUCIEncode(csi2,cbsInfo.GCSI2,pusch.Modulation);
|
||||
|
||||
tb_data = randi([0 1],A,1);
|
||||
% Transport block CRC attachment
|
||||
@@ -73,7 +73,8 @@ culsch = chIn;
|
||||
cw_scr = nrPUSCHScramble(cw,pusch.NID,pusch.RNTI);
|
||||
|
||||
% Write to bin file
|
||||
fid = fopen('uci_on_pusch_7.bin', 'wb');
|
||||
file_name = sprintf('uci_on_pusch_oack%d_ocsi1%d_ocsi2%d.bin', oack, ocsi1, ocsi2);
|
||||
fid = fopen(file_name, 'wb');
|
||||
to_write = [A,oack,ocsi1,ocsi2,length(cw),length(cw_scr)];
|
||||
fwrite(fid, to_write, 'uint32'); % Write the data to the binary file
|
||||
fwrite(fid, tb_data, "uint8");
|
||||
|
||||
@@ -3401,11 +3401,11 @@ uint16_t get_ssb_start_symbol(const long band, NR_SubcarrierSpacing_t scs, int i
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
|
||||
struct NR_CSI_ResourcePeriodicityAndOffset *periodicityAndOffset,
|
||||
int *period, int *offset) {
|
||||
|
||||
void csi_period_offset(const NR_CSI_ReportConfig_t *csirep,
|
||||
const struct NR_CSI_ResourcePeriodicityAndOffset *periodicityAndOffset,
|
||||
int *period,
|
||||
int *offset)
|
||||
{
|
||||
if(periodicityAndOffset != NULL) {
|
||||
|
||||
NR_CSI_ResourcePeriodicityAndOffset_PR p_and_o = periodicityAndOffset->present;
|
||||
|
||||
@@ -287,9 +287,10 @@ unsigned int get_N_RA_RB(const unsigned int delta_f_RA_PRACH, const unsigned int
|
||||
|
||||
void find_period_offset_SR(const NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset);
|
||||
|
||||
void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
|
||||
struct NR_CSI_ResourcePeriodicityAndOffset *periodicityAndOffset,
|
||||
int *period, int *offset);
|
||||
void csi_period_offset(const NR_CSI_ReportConfig_t *csirep,
|
||||
const struct NR_CSI_ResourcePeriodicityAndOffset *periodicityAndOffset,
|
||||
int *period,
|
||||
int *offset);
|
||||
|
||||
bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config,
|
||||
uint16_t rbSize, uint8_t mcsIndex, uint8_t mcsTable,
|
||||
|
||||
@@ -307,10 +307,8 @@ typedef struct {
|
||||
NR_PUCCH_Resource_t *pucch_resource;
|
||||
uint32_t ack_payload;
|
||||
uint8_t sr_payload;
|
||||
uint64_t csi_part1_payload;
|
||||
uint64_t csi_part2_payload;
|
||||
nfapi_nr_ue_csi_payload_t csi_payload;
|
||||
int n_sr;
|
||||
int n_csi;
|
||||
int n_harq;
|
||||
int n_CCE;
|
||||
int N_CCE;
|
||||
@@ -487,13 +485,6 @@ typedef struct {
|
||||
A_SEQUENCE_OF(NR_SearchSpace_t) list_SS;
|
||||
} NR_BWP_PDCCH_t;
|
||||
|
||||
typedef struct csi_payload {
|
||||
uint64_t part1_payload;
|
||||
uint64_t part2_payload;
|
||||
int p1_bits;
|
||||
int p2_bits;
|
||||
} csi_payload_t;
|
||||
|
||||
typedef enum {
|
||||
WIDEBAND_ON_PUCCH,
|
||||
SUBBAND_ON_PUCCH,
|
||||
|
||||
@@ -113,7 +113,7 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac,
|
||||
void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info);
|
||||
void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info);
|
||||
|
||||
csi_payload_t nr_ue_aperiodic_csi_reporting(NR_UE_MAC_INST_t *mac, dci_field_t csi_request, int tda, long *K2);
|
||||
nfapi_nr_ue_csi_payload_t nr_ue_aperiodic_csi_reporting(NR_UE_MAC_INST_t *mac, dci_field_t csi_request, int tda, long *K2);
|
||||
|
||||
nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci);
|
||||
|
||||
@@ -126,12 +126,17 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame,
|
||||
int slot);
|
||||
|
||||
int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch);
|
||||
int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
nfapi_nr_ue_csi_payload_t *csi_payload,
|
||||
NR_PUCCH_Resource_t **csi_pucch,
|
||||
bool csi_on_pusch);
|
||||
|
||||
csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
|
||||
nfapi_nr_ue_csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
|
||||
int csi_report_id,
|
||||
CSI_mapping_t mapping_type,
|
||||
NR_CSI_MeasConfig_t *csi_MeasConfig);
|
||||
const NR_CSI_MeasConfig_t *csi_MeasConfig);
|
||||
|
||||
/* \brief Get payload (MAC PDU) from UE PHY
|
||||
@param dl_info pointer to dl indication
|
||||
@@ -319,7 +324,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
|
||||
NR_tda_info_t *tda_info,
|
||||
nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu,
|
||||
dci_pdu_rel15_t *dci,
|
||||
csi_payload_t *csi_report,
|
||||
nfapi_nr_ue_csi_payload_t *csi_report,
|
||||
RAR_grant_t *rar_grant,
|
||||
rnti_t rnti,
|
||||
int ss_type,
|
||||
@@ -361,4 +366,11 @@ void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t
|
||||
|
||||
NR_SearchSpace_t *get_common_search_space(const NR_UE_MAC_INST_t *mac, const NR_SearchSpaceId_t ss_id);
|
||||
|
||||
void get_pusch_frame_slot(const int current_frame,
|
||||
const int current_slot,
|
||||
const int k2,
|
||||
const int delta,
|
||||
const int slots_per_frame,
|
||||
frame_t *frame_tx,
|
||||
int *slot_tx);
|
||||
#endif
|
||||
|
||||
@@ -125,19 +125,19 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d
|
||||
If the max number of retransmissions is reached, it triggers a new RA */
|
||||
static int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id);
|
||||
|
||||
static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
|
||||
struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
NR_CSI_MeasConfig_t *csi_MeasConfig);
|
||||
static nfapi_nr_ue_csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
|
||||
const struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
const NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
const NR_CSI_MeasConfig_t *csi_MeasConfig);
|
||||
|
||||
static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac,
|
||||
struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
NR_CSI_MeasConfig_t *csi_MeasConfig,
|
||||
CSI_mapping_t mapping_type);
|
||||
static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac,
|
||||
struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
static nfapi_nr_ue_csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac,
|
||||
const struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
const NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
const NR_CSI_MeasConfig_t *csi_MeasConfig,
|
||||
const CSI_mapping_t mapping_type);
|
||||
static nfapi_nr_ue_csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac,
|
||||
const struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
const NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
const NR_CSI_MeasConfig_t *csi_MeasConfig);
|
||||
|
||||
static uint8_t get_rsrp_diff_index(int best_rsrp, int current_rsrp);
|
||||
@@ -628,7 +628,7 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac,
|
||||
|
||||
/* CSI_REQUEST */
|
||||
long csi_K2 = -1;
|
||||
csi_payload_t csi_report = {0};
|
||||
nfapi_nr_ue_csi_payload_t csi_report = {0};
|
||||
if (dci->csi_request.nbits > 0 && dci->csi_request.val > 0)
|
||||
csi_report = nr_ue_aperiodic_csi_reporting(mac, dci->csi_request, dci->time_domain_assignment.val, &csi_K2);
|
||||
|
||||
@@ -1691,7 +1691,7 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
|
||||
pucch_pdu->second_hop_prb = pucchres->secondHopPRB!= NULL ? *pucchres->secondHopPRB : 0;
|
||||
pucch_pdu->prb_size = 1; // format 0 or 1
|
||||
|
||||
int n_uci = pucch->n_sr + pucch->n_harq + pucch->n_csi;
|
||||
int n_uci = pucch->n_sr + pucch->n_harq + pucch->csi_payload.p1_bits;
|
||||
if (n_uci > (sizeof(uint64_t) * 8)) {
|
||||
LOG_E(NR_MAC, "PUCCH number of UCI bits exceeds payload size\n");
|
||||
return -1;
|
||||
@@ -1733,14 +1733,15 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
|
||||
pucch_pdu->dmrs_scrambling_id = id0 != NULL ? *id0 : mac->physCellId;
|
||||
pucch_pdu->prb_size = compute_pucch_prb_size(2,
|
||||
pucchres->format.choice.format2->nrofPRBs,
|
||||
pucch->n_csi,
|
||||
pucch->csi_payload.p1_bits,
|
||||
pucch->n_harq,
|
||||
pucch->n_sr,
|
||||
pucch_Config->format2->choice.setup->maxCodeRate,
|
||||
2,
|
||||
pucchres->format.choice.format2->nrofSymbols,
|
||||
8);
|
||||
pucch_pdu->payload = (pucch->csi_part1_payload << (pucch->n_harq + pucch->n_sr)) | (pucch->sr_payload << pucch->n_harq) | pucch->ack_payload;
|
||||
pucch_pdu->payload = (pucch->csi_payload.part1_payload << (pucch->n_harq + pucch->n_sr))
|
||||
| (pucch->sr_payload << pucch->n_harq) | pucch->ack_payload;
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format3 :
|
||||
pucch_pdu->format_type = 3;
|
||||
@@ -1768,14 +1769,15 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
|
||||
}
|
||||
pucch_pdu->prb_size = compute_pucch_prb_size(3,
|
||||
pucchres->format.choice.format3->nrofPRBs,
|
||||
pucch->n_csi,
|
||||
pucch->csi_payload.p1_bits,
|
||||
pucch->n_harq,
|
||||
pucch->n_sr,
|
||||
pucch_Config->format3->choice.setup->maxCodeRate,
|
||||
2 - pucch_pdu->pi_2bpsk,
|
||||
pucchres->format.choice.format3->nrofSymbols - f3_dmrs_symbols,
|
||||
12);
|
||||
pucch_pdu->payload = (pucch->csi_part1_payload << (pucch->n_harq + pucch->n_sr)) | (pucch->sr_payload << pucch->n_harq) | pucch->ack_payload;
|
||||
pucch_pdu->payload = (pucch->csi_payload.part1_payload << (pucch->n_harq + pucch->n_sr))
|
||||
| (pucch->sr_payload << pucch->n_harq) | pucch->ack_payload;
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format4 :
|
||||
pucch_pdu->format_type = 4;
|
||||
@@ -1793,7 +1795,8 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
|
||||
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0;
|
||||
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0;
|
||||
}
|
||||
pucch_pdu->payload = (pucch->csi_part1_payload << (pucch->n_harq + pucch->n_sr)) | (pucch->sr_payload << pucch->n_harq) | pucch->ack_payload;
|
||||
pucch_pdu->payload = (pucch->csi_payload.part1_payload << (pucch->n_harq + pucch->n_sr))
|
||||
| (pucch->sr_payload << pucch->n_harq) | pucch->ack_payload;
|
||||
break;
|
||||
default :
|
||||
LOG_E(NR_MAC, "Undefined PUCCH format \n");
|
||||
@@ -2234,8 +2237,8 @@ void merge_resources(PUCCH_sched_t *res, int num_res, NR_PUCCH_Config_t *pucch_C
|
||||
case NR_PUCCH_Resource__format_PR_format2:
|
||||
case NR_PUCCH_Resource__format_PR_format4:
|
||||
case NR_PUCCH_Resource__format_PR_format3:
|
||||
if (res[i + 1].n_csi > 0) {
|
||||
AssertFatal(res[i].n_csi == 0, "Multiplexing multiple CSI report in a single PUCCH not supported yet\n");
|
||||
if (res[i + 1].csi_payload.p1_bits > 0) {
|
||||
AssertFatal(res[i].csi_payload.p1_bits == 0, "Multiplexing multiple CSI report in a single PUCCH not supported yet\n");
|
||||
AssertFatal(res[i].n_harq > 0 && res[i + 1].n_harq == 0,
|
||||
"There is CSI in next F2 or above resource, since there is no CSI in current one, we expect HARQ in "
|
||||
"there and not in next\n");
|
||||
@@ -2248,8 +2251,8 @@ void merge_resources(PUCCH_sched_t *res, int num_res, NR_PUCCH_Config_t *pucch_C
|
||||
res[i].n_sr = res[i + 1].n_sr;
|
||||
res[i].sr_payload = res[i + 1].sr_payload;
|
||||
}
|
||||
res[i].n_csi = res[i + 1].n_csi;
|
||||
res[i].csi_part1_payload = res[i + 1].csi_part1_payload;
|
||||
res[i].csi_payload.p1_bits = res[i + 1].csi_payload.p1_bits;
|
||||
res[i].csi_payload.part1_payload = res[i + 1].csi_payload.part1_payload;
|
||||
res[i + 1] = res[i];
|
||||
res[i] = empty;
|
||||
} else {
|
||||
@@ -2270,8 +2273,8 @@ void merge_resources(PUCCH_sched_t *res, int num_res, NR_PUCCH_Config_t *pucch_C
|
||||
res[i] = empty;
|
||||
}
|
||||
}
|
||||
} else if (res[i].n_csi > 0) {
|
||||
AssertFatal(res[i + 1].n_csi == 0, "Multiplexing multiple CSI report in a single PUCCH not supported yet\n");
|
||||
} else if (res[i].csi_payload.p1_bits > 0) {
|
||||
AssertFatal(res[i + 1].csi_payload.p1_bits == 0, "Multiplexing multiple CSI report in a single PUCCH not supported yet\n");
|
||||
AssertFatal(res[i + 1].n_harq > 0 && res[i].n_harq == 0,
|
||||
"There is CSI in next F2 or above resource, since there is no CSI in current one, we expect HARQ in "
|
||||
"there and not in next\n");
|
||||
@@ -2284,8 +2287,8 @@ void merge_resources(PUCCH_sched_t *res, int num_res, NR_PUCCH_Config_t *pucch_C
|
||||
res[i + 1].n_sr = res[i].n_sr;
|
||||
res[i + 1].sr_payload = res[i].sr_payload;
|
||||
}
|
||||
res[i + 1].n_csi = res[i].n_csi;
|
||||
res[i + 1].csi_part1_payload = res[i].csi_part1_payload;
|
||||
res[i + 1].csi_payload.p1_bits = res[i].csi_payload.p1_bits;
|
||||
res[i + 1].csi_payload.part1_payload = res[i].csi_payload.part1_payload;
|
||||
res[i] = empty;
|
||||
} else {
|
||||
if (res[i + 1].n_sr > 0) {
|
||||
@@ -2675,68 +2678,72 @@ int compute_csi_priority(NR_UE_MAC_INST_t *mac, NR_CSI_ReportConfig_t *csirep)
|
||||
return 2 * Ncells * Ms * y + Ncells * Ms * k + Ms * c + s;
|
||||
}
|
||||
|
||||
int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch)
|
||||
int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
nfapi_nr_ue_csi_payload_t *csi_payload,
|
||||
NR_PUCCH_Resource_t **csi_pucch,
|
||||
bool csi_on_pusch)
|
||||
{
|
||||
NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
|
||||
NR_PUCCH_Config_t *pucch_Config = current_UL_BWP ? current_UL_BWP->pucch_Config : NULL;
|
||||
int num_csi = 0;
|
||||
|
||||
if (mac->sc_info.csi_MeasConfig) {
|
||||
NR_CSI_MeasConfig_t *csi_measconfig = mac->sc_info.csi_MeasConfig;
|
||||
if (!mac->sc_info.csi_MeasConfig || !pucch_Config)
|
||||
return num_csi;
|
||||
|
||||
int csi_priority = INT_MAX;
|
||||
for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++) {
|
||||
NR_CSI_ReportConfig_t *csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
|
||||
NR_CSI_MeasConfig_t *csi_measconfig = mac->sc_info.csi_MeasConfig;
|
||||
|
||||
if(csirep->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_periodic) {
|
||||
int period, offset;
|
||||
csi_period_offset(csirep, NULL, &period, &offset);
|
||||
const int n_slots_frame = mac->frame_structure.numb_slots_frame;
|
||||
if (((n_slots_frame*frame + slot - offset)%period) == 0 && pucch_Config) {
|
||||
int csi_res_id = -1;
|
||||
for (int i = 0; i < csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.count; i++) {
|
||||
const NR_PUCCH_CSI_Resource_t *pucchcsires =
|
||||
csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[i];
|
||||
if (pucchcsires->uplinkBandwidthPartId == current_UL_BWP->bwp_id) {
|
||||
csi_res_id = pucchcsires->pucch_Resource;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (csi_res_id < 0) {
|
||||
// This CSI Report ID is not associated with current active BWP
|
||||
continue;
|
||||
}
|
||||
NR_PUCCH_Resource_t *csi_pucch = find_pucch_resource_from_list(pucch_Config->resourceToAddModList, csi_res_id);
|
||||
AssertFatal(csi_pucch != NULL, "Couldn't find PUCCH Resource ID for SR in PUCCH resource list\n");
|
||||
LOG_D(NR_MAC, "Preparing CSI report in frame %d slot %d CSI report ID %d\n", frame, slot, csi_report_id);
|
||||
int temp_priority = compute_csi_priority(mac, csirep);
|
||||
if (num_csi > 0) {
|
||||
// need to verify if we can multiplex multiple CSI report
|
||||
if (pucch_Config->multi_CSI_PUCCH_ResourceList) {
|
||||
AssertFatal(false, "Multiplexing multiple CSI report in a single PUCCH not supported yet\n");
|
||||
} else if (temp_priority < csi_priority) {
|
||||
// we discard previous report
|
||||
csi_priority = temp_priority;
|
||||
num_csi = 1;
|
||||
csi_payload_t csi = nr_get_csi_payload(mac, csi_report_id, WIDEBAND_ON_PUCCH, csi_measconfig);
|
||||
pucch->n_csi = csi.p1_bits;
|
||||
pucch->csi_part1_payload = csi.part1_payload;
|
||||
pucch->pucch_resource = csi_pucch;
|
||||
} else
|
||||
continue;
|
||||
} else {
|
||||
num_csi = 1;
|
||||
csi_priority = temp_priority;
|
||||
csi_payload_t csi = nr_get_csi_payload(mac, csi_report_id, WIDEBAND_ON_PUCCH, csi_measconfig);
|
||||
pucch->n_csi = csi.p1_bits;
|
||||
pucch->csi_part1_payload = csi.part1_payload;
|
||||
pucch->pucch_resource = csi_pucch;
|
||||
}
|
||||
}
|
||||
int csi_priority = INT_MAX;
|
||||
for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++) {
|
||||
NR_CSI_ReportConfig_t *csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
|
||||
|
||||
AssertFatal(csirep->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_aperiodic
|
||||
|| csirep->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_periodic,
|
||||
"Not supported CSI report type\n");
|
||||
|
||||
// Only periodic CSI measurements is handled for now
|
||||
if (csirep->reportConfigType.present != NR_CSI_ReportConfig__reportConfigType_PR_periodic)
|
||||
continue;
|
||||
|
||||
int period, offset;
|
||||
csi_period_offset(csirep, NULL, &period, &offset);
|
||||
const int n_slots_frame = mac->frame_structure.numb_slots_frame;
|
||||
// Check if current slot falls in the report period
|
||||
if (((n_slots_frame * frame + slot - offset) % period) != 0)
|
||||
continue;
|
||||
|
||||
int csi_res_id = -1;
|
||||
for (int i = 0; i < csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.count; i++) {
|
||||
const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[i];
|
||||
if (pucchcsires->uplinkBandwidthPartId == current_UL_BWP->bwp_id) {
|
||||
csi_res_id = pucchcsires->pucch_Resource;
|
||||
break;
|
||||
}
|
||||
else
|
||||
AssertFatal(csirep->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_aperiodic,
|
||||
"Not supported CSI report type\n");
|
||||
}
|
||||
if (csi_res_id < 0) {
|
||||
// This CSI Report ID is not associated with current active BWP
|
||||
continue;
|
||||
}
|
||||
*csi_pucch = find_pucch_resource_from_list(pucch_Config->resourceToAddModList, csi_res_id);
|
||||
AssertFatal(*csi_pucch != NULL, "Couldn't find PUCCH Resource ID for CSI in PUCCH resource list\n");
|
||||
LOG_D(NR_MAC, "Preparing CSI report in frame %d slot %d CSI report ID %d\n", frame, slot, csi_report_id);
|
||||
int temp_priority = compute_csi_priority(mac, csirep);
|
||||
if (num_csi > 0) {
|
||||
// need to verify if we can multiplex multiple CSI report
|
||||
if (pucch_Config->multi_CSI_PUCCH_ResourceList) {
|
||||
AssertFatal(false, "Multiplexing multiple CSI report in a single PUCCH not supported yet\n");
|
||||
} else if (temp_priority < csi_priority) {
|
||||
// we discard previous report
|
||||
csi_priority = temp_priority;
|
||||
num_csi = 1;
|
||||
*csi_payload = nr_get_csi_payload(mac, csi_report_id, csi_on_pusch ? ON_PUSCH : WIDEBAND_ON_PUCCH, csi_measconfig);
|
||||
} else
|
||||
continue;
|
||||
} else {
|
||||
num_csi = 1;
|
||||
csi_priority = temp_priority;
|
||||
*csi_payload = nr_get_csi_payload(mac, csi_report_id, csi_on_pusch ? ON_PUSCH : WIDEBAND_ON_PUCCH, csi_measconfig);
|
||||
}
|
||||
}
|
||||
return num_csi;
|
||||
@@ -2774,10 +2781,10 @@ static int compare_ssb_sinr(const void *a, const void *b)
|
||||
return mb->ssb_sinr_dB - ma->ssb_sinr_dB;
|
||||
}
|
||||
|
||||
static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac,
|
||||
struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
NR_CSI_MeasConfig_t *csi_MeasConfig)
|
||||
static nfapi_nr_ue_csi_payload_t get_ssb_sinr_payload(const NR_UE_MAC_INST_t *mac,
|
||||
const struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
const NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
const NR_CSI_MeasConfig_t *csi_MeasConfig)
|
||||
{
|
||||
int nb_ssb = 0; // nb of ssb in the resource
|
||||
int nb_meas = 0; // nb of ssb to report measurements on
|
||||
@@ -2795,7 +2802,7 @@ static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac,
|
||||
} else
|
||||
nb_meas = 2;
|
||||
|
||||
struct NR_CSI_SSB_ResourceSet__csi_SSB_ResourceList *SSB_resource = NULL;
|
||||
const struct NR_CSI_SSB_ResourceSet__csi_SSB_ResourceList *SSB_resource = NULL;
|
||||
for (int csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) {
|
||||
if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId
|
||||
== *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) {
|
||||
@@ -2848,19 +2855,19 @@ static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac,
|
||||
break; // resource found
|
||||
}
|
||||
}
|
||||
int max_bits = sizeof(((csi_payload_t *)0)->part1_payload) * 8;
|
||||
int max_bits = sizeof(((nfapi_nr_ue_csi_payload_t *)0)->part1_payload) * 8;
|
||||
AssertFatal(bits <= max_bits, "Not supporting CSI report with more than %d bits (payload: %d bits)\n", max_bits, bits);
|
||||
csi_payload_t csi = {.part1_payload = temp_payload, .part2_payload = 0, .p1_bits = bits, csi.p2_bits = 0};
|
||||
nfapi_nr_ue_csi_payload_t csi = {.part1_payload = temp_payload, .part2_payload = 0, .p1_bits = bits, csi.p2_bits = 0};
|
||||
return csi;
|
||||
}
|
||||
|
||||
csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
|
||||
nfapi_nr_ue_csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
|
||||
int csi_report_id,
|
||||
CSI_mapping_t mapping_type,
|
||||
NR_CSI_MeasConfig_t *csi_MeasConfig)
|
||||
const NR_CSI_MeasConfig_t *csi_MeasConfig)
|
||||
{
|
||||
AssertFatal(csi_MeasConfig->csi_ReportConfigToAddModList->list.count > 0,"No CSI Report configuration available\n");
|
||||
csi_payload_t csi = {0};
|
||||
nfapi_nr_ue_csi_payload_t csi = {0};
|
||||
struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
|
||||
NR_CSI_ResourceConfigId_t csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement;
|
||||
if (csi_reportconfig->ext2 && csi_reportconfig->ext2->reportQuantity_r16) {
|
||||
@@ -2909,10 +2916,10 @@ static int compare_ssb_rsrp(const void *a, const void *b)
|
||||
}
|
||||
|
||||
|
||||
static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
|
||||
struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
NR_CSI_MeasConfig_t *csi_MeasConfig)
|
||||
static nfapi_nr_ue_csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
|
||||
const struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
const NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
const NR_CSI_MeasConfig_t *csi_MeasConfig)
|
||||
{
|
||||
int nb_ssb = 0; // nb of ssb in the resource
|
||||
int nb_meas = 0; // nb of ssb to report measurements on
|
||||
@@ -2931,7 +2938,7 @@ static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
|
||||
} else
|
||||
nb_meas = 2;
|
||||
|
||||
struct NR_CSI_SSB_ResourceSet__csi_SSB_ResourceList *SSB_resource = NULL;
|
||||
const struct NR_CSI_SSB_ResourceSet__csi_SSB_ResourceList *SSB_resource = NULL;
|
||||
for (int csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) {
|
||||
if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId ==
|
||||
*(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){
|
||||
@@ -2984,18 +2991,18 @@ static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
|
||||
break; // resource found
|
||||
}
|
||||
}
|
||||
int max_bits = sizeof(((csi_payload_t *)0)->part1_payload) * 8;
|
||||
int max_bits = sizeof(((nfapi_nr_ue_csi_payload_t *)0)->part1_payload) * 8;
|
||||
AssertFatal(bits <= max_bits, "Not supporting CSI report with more than %d bits (payload: %d bits)\n", max_bits, bits);
|
||||
|
||||
csi_payload_t csi = {.part1_payload = temp_payload, .part2_payload = 0, .p1_bits = bits, .p2_bits = 0};
|
||||
nfapi_nr_ue_csi_payload_t csi = {.part1_payload = temp_payload, .part2_payload = 0, .p1_bits = bits, .p2_bits = 0};
|
||||
return csi;
|
||||
}
|
||||
|
||||
static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac,
|
||||
struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
NR_CSI_MeasConfig_t *csi_MeasConfig,
|
||||
CSI_mapping_t mapping_type)
|
||||
static nfapi_nr_ue_csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac,
|
||||
const struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
const NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
const NR_CSI_MeasConfig_t *csi_MeasConfig,
|
||||
const CSI_mapping_t mapping_type)
|
||||
{
|
||||
int p1_bits = 0;
|
||||
int p2_bits = 0;
|
||||
@@ -3063,13 +3070,13 @@ static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac,
|
||||
}
|
||||
}
|
||||
AssertFatal(p1_bits <= 32 && p2_bits <= 32, "Not supporting CSI report with more than 32 bits\n");
|
||||
csi_payload_t csi = {.part1_payload = temp_payload_1, .part2_payload = temp_payload_2, .p1_bits = p1_bits, csi.p2_bits = p2_bits};
|
||||
nfapi_nr_ue_csi_payload_t csi = {.part1_payload = temp_payload_1, .part2_payload = temp_payload_2, .p1_bits = p1_bits, csi.p2_bits = p2_bits};
|
||||
return csi;
|
||||
}
|
||||
|
||||
static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac,
|
||||
struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
static nfapi_nr_ue_csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac,
|
||||
const struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||
const NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||
const NR_CSI_MeasConfig_t *csi_MeasConfig)
|
||||
{
|
||||
int n_bits = 0;
|
||||
@@ -3116,7 +3123,7 @@ static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac,
|
||||
}
|
||||
}
|
||||
AssertFatal(n_bits <= 32, "Not supporting CSI report with more than 32 bits\n");
|
||||
csi_payload_t csi = {.part1_payload = temp_payload, .p1_bits = n_bits, csi.p2_bits = 0};
|
||||
nfapi_nr_ue_csi_payload_t csi = {.part1_payload = temp_payload, .p1_bits = n_bits, csi.p2_bits = 0};
|
||||
return csi;
|
||||
}
|
||||
|
||||
|
||||
@@ -366,6 +366,26 @@ void ul_layers_config(NR_UE_MAC_INST_t *mac, nfapi_nr_ue_pusch_pdu_t *pusch_conf
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_pusch_uci_struct(const NR_PUSCH_Config_t *pusch_Config,
|
||||
const nfapi_nr_ue_csi_payload_t *csi_payload,
|
||||
nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu)
|
||||
{
|
||||
pusch_config_pdu->pusch_uci.csi_payload = *csi_payload;
|
||||
AssertFatal(pusch_Config && pusch_Config->uci_OnPUSCH, "UCI on PUSCH need to be configured\n");
|
||||
NR_UCI_OnPUSCH_t *onPusch = pusch_Config->uci_OnPUSCH->choice.setup;
|
||||
AssertFatal(onPusch && onPusch->betaOffsets && onPusch->betaOffsets->present == NR_UCI_OnPUSCH__betaOffsets_PR_semiStatic,
|
||||
"Only semistatic beta offset is supported\n");
|
||||
NR_BetaOffsets_t *beta_offsets = onPusch->betaOffsets->choice.semiStatic;
|
||||
|
||||
pusch_config_pdu->pusch_uci.beta_offset_csi1 = pusch_config_pdu->pusch_uci.csi_payload.p1_bits < 12
|
||||
? *beta_offsets->betaOffsetCSI_Part1_Index1
|
||||
: *beta_offsets->betaOffsetCSI_Part1_Index2;
|
||||
pusch_config_pdu->pusch_uci.beta_offset_csi2 = pusch_config_pdu->pusch_uci.csi_payload.p2_bits < 12
|
||||
? *beta_offsets->betaOffsetCSI_Part2_Index1
|
||||
: *beta_offsets->betaOffsetCSI_Part2_Index2;
|
||||
pusch_config_pdu->pusch_uci.alpha_scaling = onPusch->scaling;
|
||||
}
|
||||
|
||||
// Configuration of Msg3 PDU according to clauses:
|
||||
// - 8.3 of 3GPP TS 38.213 version 16.3.0 Release 16
|
||||
// - 6.1.2.2 of TS 38.214
|
||||
@@ -378,7 +398,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
|
||||
NR_tda_info_t *tda_info,
|
||||
nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu,
|
||||
dci_pdu_rel15_t *dci,
|
||||
csi_payload_t *csi_report,
|
||||
nfapi_nr_ue_csi_payload_t *csi_report,
|
||||
RAR_grant_t *rar_grant,
|
||||
rnti_t rnti,
|
||||
int ss_type,
|
||||
@@ -558,29 +578,10 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
|
||||
pusch_config_pdu->ulsch_indicator = dci->ulsch_indicator;
|
||||
if (dci->csi_request.nbits > 0 && dci->csi_request.val > 0) {
|
||||
AssertFatal(csi_report, "CSI report needs to be present in case of CSI request\n");
|
||||
pusch_config_pdu->pusch_uci.csi_part1_bit_length = csi_report->p1_bits;
|
||||
pusch_config_pdu->pusch_uci.csi_part1_payload = csi_report->part1_payload;
|
||||
pusch_config_pdu->pusch_uci.csi_part2_bit_length = csi_report->p2_bits;
|
||||
pusch_config_pdu->pusch_uci.csi_part2_payload = csi_report->part2_payload;
|
||||
AssertFatal(pusch_Config && pusch_Config->uci_OnPUSCH, "UCI on PUSCH need to be configured\n");
|
||||
NR_UCI_OnPUSCH_t *onPusch = pusch_Config->uci_OnPUSCH->choice.setup;
|
||||
AssertFatal(onPusch &&
|
||||
onPusch->betaOffsets &&
|
||||
onPusch->betaOffsets->present == NR_UCI_OnPUSCH__betaOffsets_PR_semiStatic,
|
||||
"Only semistatic beta offset is supported\n");
|
||||
NR_BetaOffsets_t *beta_offsets = onPusch->betaOffsets->choice.semiStatic;
|
||||
|
||||
pusch_config_pdu->pusch_uci.beta_offset_csi1 = pusch_config_pdu->pusch_uci.csi_part1_bit_length < 12 ?
|
||||
*beta_offsets->betaOffsetCSI_Part1_Index1 :
|
||||
*beta_offsets->betaOffsetCSI_Part1_Index2;
|
||||
pusch_config_pdu->pusch_uci.beta_offset_csi2 = pusch_config_pdu->pusch_uci.csi_part2_bit_length < 12 ?
|
||||
*beta_offsets->betaOffsetCSI_Part2_Index1 :
|
||||
*beta_offsets->betaOffsetCSI_Part2_Index2;
|
||||
pusch_config_pdu->pusch_uci.alpha_scaling = onPusch->scaling;
|
||||
}
|
||||
else {
|
||||
pusch_config_pdu->pusch_uci.csi_part1_bit_length = 0;
|
||||
pusch_config_pdu->pusch_uci.csi_part2_bit_length = 0;
|
||||
fill_pusch_uci_struct(pusch_Config, csi_report, pusch_config_pdu);
|
||||
} else {
|
||||
pusch_config_pdu->pusch_uci.csi_payload.p1_bits = 0;
|
||||
pusch_config_pdu->pusch_uci.csi_payload.p2_bits = 0;
|
||||
}
|
||||
|
||||
pusch_config_pdu->pusch_uci.harq_ack_bit_length = 0;
|
||||
@@ -889,13 +890,13 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
|
||||
return 0;
|
||||
}
|
||||
|
||||
csi_payload_t nr_ue_aperiodic_csi_reporting(NR_UE_MAC_INST_t *mac, dci_field_t csi_request, int tda, long *k2)
|
||||
nfapi_nr_ue_csi_payload_t nr_ue_aperiodic_csi_reporting(NR_UE_MAC_INST_t *mac, dci_field_t csi_request, int tda, long *k2)
|
||||
{
|
||||
NR_CSI_AperiodicTriggerStateList_t *aperiodicTriggerStateList = mac->sc_info.aperiodicTriggerStateList;
|
||||
AssertFatal(aperiodicTriggerStateList, "Received CSI request via DCI but aperiodicTriggerStateList is not present\n");
|
||||
int n_states = aperiodicTriggerStateList->list.count;
|
||||
int n_ts = csi_request.nbits;
|
||||
csi_payload_t csi = {0};
|
||||
nfapi_nr_ue_csi_payload_t csi = {0};
|
||||
AssertFatal(n_states <= ((1 << n_ts) - 1), "Case of subselection indication of trigger states not supported yet\n");
|
||||
int num_trig = 0;
|
||||
for (int i = 0; i < n_ts; i++) {
|
||||
@@ -916,8 +917,8 @@ csi_payload_t nr_ue_aperiodic_csi_reporting(NR_UE_MAC_INST_t *mac, dci_field_t c
|
||||
if (report_config->reportConfigId == id) {
|
||||
struct NR_CSI_ReportConfig__reportConfigType__aperiodic__reportSlotOffsetList *offset_list = &report_config->reportConfigType.choice.aperiodic->reportSlotOffsetList;
|
||||
AssertFatal(tda < offset_list->list.count, "TDA index from DCI %d exceeds slot offset list %d\n", tda, offset_list->list.count);
|
||||
if (k2 == NULL || *k2 < *offset_list->list.array[tda])
|
||||
k2 = offset_list->list.array[tda];
|
||||
if (*k2 < *offset_list->list.array[tda])
|
||||
*k2 = *offset_list->list.array[tda];
|
||||
found = c;
|
||||
break;
|
||||
}
|
||||
@@ -1541,6 +1542,18 @@ static uint8_t nr_locate_BsrIndexByBufferSize(int size, int value)
|
||||
}
|
||||
}
|
||||
|
||||
void get_pusch_frame_slot(const int current_frame,
|
||||
const int current_slot,
|
||||
const int k2,
|
||||
const int delta,
|
||||
const int slots_per_frame,
|
||||
frame_t *frame_tx,
|
||||
int *slot_tx)
|
||||
{
|
||||
*slot_tx = (current_slot + k2 + delta) % slots_per_frame;
|
||||
*frame_tx = (current_frame + (current_slot + k2 + delta) / slots_per_frame) % MAX_FRAME_NUMBER;
|
||||
}
|
||||
|
||||
// PUSCH scheduler:
|
||||
// - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2,
|
||||
// - where K2 is the offset between the slot in which UL DCI is received and the slot
|
||||
@@ -1578,8 +1591,7 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
|
||||
GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
|
||||
GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu));
|
||||
|
||||
*slot_tx = (current_slot + k2 + delta) % slots_per_frame;
|
||||
*frame_tx = (current_frame + (current_slot + k2 + delta) / slots_per_frame) % MAX_FRAME_NUMBER;
|
||||
get_pusch_frame_slot(current_frame, current_slot, k2, delta, slots_per_frame, frame_tx, slot_tx);
|
||||
} else {
|
||||
AssertFatal(k2 >= GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
|
||||
"Slot offset K2 (%ld) needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to %ld in "
|
||||
@@ -1595,8 +1607,7 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
|
||||
}
|
||||
|
||||
// Calculate TX slot and frame
|
||||
*slot_tx = (current_slot + k2) % slots_per_frame;
|
||||
*frame_tx = (current_frame + (current_slot + k2) / slots_per_frame) % MAX_FRAME_NUMBER;
|
||||
get_pusch_frame_slot(current_frame, current_slot, k2, 0, slots_per_frame, frame_tx, slot_tx);
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "[%04d.%02d] UL transmission in [%04d.%02d] (k2 %ld delta %d)\n", current_frame, current_slot, *frame_tx, *slot_tx, k2, delta);
|
||||
@@ -1703,9 +1714,17 @@ static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac,
|
||||
LOG_E(NR_MAC, "UCI on PUSCH need to be configured to schedule UCI on PUSCH\n");
|
||||
}
|
||||
}
|
||||
if (pusch_pdu->pusch_uci.csi_part1_bit_length == 0 && pusch_pdu->pusch_uci.csi_part2_bit_length == 0) {
|
||||
// To support this we would need to shift some bits into CSI part2 -> need to change the logic
|
||||
AssertFatal(pucch->n_csi == 0, "Multiplexing periodic CSI on PUSCH not supported\n");
|
||||
|
||||
AssertFatal(pusch_pdu->pusch_uci.csi_payload.p1_bits == 0, "PUSCH already has CSI report\n");
|
||||
|
||||
// Check if this PUCCH has CSI report to send. If so, multiplex it on PUSCH
|
||||
if (pucch->csi_payload.p1_bits > 0) {
|
||||
nfapi_nr_ue_csi_payload_t csi_payload = {0};
|
||||
NR_PUSCH_Config_t *pusch_Config = mac->current_UL_BWP->pusch_Config;
|
||||
NR_PUCCH_Resource_t *csi_pucch = NULL;
|
||||
nr_get_csi_measurements(mac, frame_tx, slot_tx, &csi_payload, &csi_pucch, true);
|
||||
fill_pusch_uci_struct(pusch_Config, &csi_payload, pusch_pdu);
|
||||
mux_done = true;
|
||||
}
|
||||
|
||||
release_ul_config(ulcfg_pdu, false);
|
||||
@@ -1736,7 +1755,7 @@ static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frame, int slot
|
||||
// CSI
|
||||
int csi_res = 0;
|
||||
if (mac->state == UE_CONNECTED)
|
||||
csi_res = nr_get_csi_measurements(mac, frame, slot, &pucch[num_res]);
|
||||
csi_res = nr_get_csi_measurements(mac, frame, slot, &pucch[num_res].csi_payload, &pucch[num_res].pucch_resource, false);
|
||||
if (csi_res > 0) {
|
||||
num_res += csi_res;
|
||||
}
|
||||
@@ -1757,14 +1776,14 @@ static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frame, int slot
|
||||
}
|
||||
|
||||
for (int j = 0; j < num_res; j++) {
|
||||
if (pucch[j].n_harq + pucch[j].n_sr + pucch[j].n_csi != 0) {
|
||||
if (pucch[j].n_harq + pucch[j].n_sr + pucch[j].csi_payload.p1_bits != 0) {
|
||||
LOG_D(NR_MAC,
|
||||
"%d.%d configure pucch, O_ACK %d, O_SR %d, O_CSI %d\n",
|
||||
frame,
|
||||
slot,
|
||||
pucch[j].n_harq,
|
||||
pucch[j].n_sr,
|
||||
pucch[j].n_csi);
|
||||
pucch[j].csi_payload.p1_bits);
|
||||
|
||||
// checking if we need to schedule pucch[j] on PUSCH
|
||||
if (schedule_uci_on_pusch(mac, frame, slot, &pucch[j], mac->current_UL_BWP))
|
||||
|
||||
Reference in New Issue
Block a user