mirror of https://github.com/PentHertz/srsLTE.git
added pucch enodeb receiver
This commit is contained in:
parent
383dfa63fe
commit
ea4a81c8d0
|
@ -57,6 +57,7 @@ typedef struct {
|
|||
|
||||
cf_t *pilot_estimates;
|
||||
cf_t *pilot_recv_signal;
|
||||
cf_t *pilot_known_signal;
|
||||
cf_t *tmp_noise;
|
||||
|
||||
#ifdef FREQ_SEL_SNR
|
||||
|
@ -99,6 +100,13 @@ SRSLTE_API int srslte_chest_ul_estimate(srslte_chest_ul_t *q,
|
|||
uint32_t cyclic_shift_for_dmrs,
|
||||
uint32_t n_prb[2]);
|
||||
|
||||
SRSLTE_API int srslte_chest_ul_estimate_pucch(srslte_chest_ul_t *q,
|
||||
cf_t *input,
|
||||
cf_t *ce,
|
||||
srslte_pucch_format_t format,
|
||||
uint32_t n_pucch,
|
||||
uint32_t sf_idx);
|
||||
|
||||
SRSLTE_API float srslte_chest_ul_get_noise_estimate(srslte_chest_ul_t *q);
|
||||
|
||||
SRSLTE_API float srslte_chest_ul_get_snr(srslte_chest_ul_t *q);
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
#define SRSLTE_REFSIGNAL_UL_L(ns_idx, cp) ((ns_idx+1)*SRSLTE_CP_NSYMB(cp)-4)
|
||||
|
||||
/* PUSCH DMRS common configuration (received in SIB2) */
|
||||
typedef struct SRSLTE_API {
|
||||
uint32_t cyclic_shift;
|
||||
uint32_t delta_ss;
|
||||
|
@ -53,15 +54,19 @@ typedef struct SRSLTE_API {
|
|||
bool sequence_hopping_en;
|
||||
}srslte_refsignal_dmrs_pusch_cfg_t;
|
||||
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
// Common Configuration
|
||||
uint32_t subframe_config;
|
||||
uint32_t I_srs;
|
||||
uint32_t bw_cfg;
|
||||
uint32_t n_srs;
|
||||
uint32_t k_tc;
|
||||
uint32_t n_rrc;
|
||||
|
||||
// Dedicated configuration
|
||||
uint32_t B;
|
||||
uint32_t b_hop;
|
||||
uint32_t n_srs;
|
||||
uint32_t I_srs;
|
||||
uint32_t k_tc;
|
||||
uint32_t n_rrc;
|
||||
bool configured;
|
||||
}srslte_refsignal_srs_cfg_t;
|
||||
|
||||
|
@ -101,6 +106,13 @@ SRSLTE_API void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q,
|
|||
SRSLTE_API void srslte_refsignal_r_uv_arg_1prb(float *arg,
|
||||
uint32_t u);
|
||||
|
||||
SRSLTE_API uint32_t srslte_refsignal_dmrs_N_rs(srslte_pucch_format_t format,
|
||||
srslte_cp_t cp);
|
||||
|
||||
SRSLTE_API uint32_t srslte_refsignal_dmrs_pucch_symbol(uint32_t m,
|
||||
srslte_pucch_format_t format,
|
||||
srslte_cp_t cp);
|
||||
|
||||
SRSLTE_API bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *cfg,
|
||||
uint32_t nof_prb);
|
||||
|
@ -150,6 +162,12 @@ SRSLTE_API int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t* q,
|
|||
cf_t *r_pucch,
|
||||
cf_t *output);
|
||||
|
||||
SRSLTE_API int srslte_refsignal_dmrs_pucch_get(srslte_refsignal_ul_t* q,
|
||||
srslte_pucch_format_t format,
|
||||
uint32_t n_pucch,
|
||||
cf_t *input,
|
||||
cf_t *r_pucch);
|
||||
|
||||
SRSLTE_API int srslte_refsignal_srs_pregen(srslte_refsignal_ul_t *q,
|
||||
srslte_refsignal_srs_pregen_t *pregen);
|
||||
|
||||
|
|
|
@ -73,7 +73,15 @@ typedef struct SRSLTE_API {
|
|||
srslte_prach_t prach;
|
||||
|
||||
srslte_pusch_cfg_t pusch_cfg;
|
||||
|
||||
|
||||
srslte_pusch_hopping_cfg_t hopping_cfg;
|
||||
|
||||
// Configuration for each user
|
||||
bool *uci_cfg_en;
|
||||
bool *srs_cfg_en;
|
||||
srslte_uci_cfg_t *uci_cfg;
|
||||
srslte_refsignal_srs_cfg_t *srs_cfg;
|
||||
|
||||
} srslte_enb_ul_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -85,6 +93,7 @@ typedef struct {
|
|||
bool needs_pdcch;
|
||||
uint8_t *data;
|
||||
srslte_softbuffer_rx_t *softbuffer;
|
||||
|
||||
} srslte_enb_ul_pusch_t;
|
||||
|
||||
/* This function shall be called just after the initial synchronization */
|
||||
|
@ -92,6 +101,7 @@ SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q,
|
|||
srslte_cell_t cell,
|
||||
srslte_prach_cfg_t* prach_cfg,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
|
||||
srslte_pusch_hopping_cfg_t *hopping_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg,
|
||||
uint32_t nof_rntis);
|
||||
|
||||
|
@ -101,12 +111,24 @@ SRSLTE_API int srslte_enb_ul_cfg_rnti(srslte_enb_ul_t *q,
|
|||
uint32_t idx,
|
||||
uint16_t rnti);
|
||||
|
||||
SRSLTE_API int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint32_t idx,
|
||||
srslte_uci_cfg_t *uci_cfg,
|
||||
srslte_refsignal_srs_cfg_t *srs_cfg);
|
||||
|
||||
|
||||
SRSLTE_API int srslte_enb_ul_rem_rnti(srslte_enb_ul_t *q,
|
||||
uint32_t idx);
|
||||
|
||||
SRSLTE_API void srslte_enb_ul_fft(srslte_enb_ul_t *q,
|
||||
cf_t *signal_buffer);
|
||||
|
||||
SRSLTE_API int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q,
|
||||
srslte_pucch_format_t format,
|
||||
uint32_t n_pucch,
|
||||
uint32_t rnti_idx,
|
||||
srslte_uci_data_t *uci_data,
|
||||
uint32_t tti);
|
||||
|
||||
SRSLTE_API int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q,
|
||||
srslte_ra_ul_grant_t *grant,
|
||||
srslte_softbuffer_rx_t *softbuffer,
|
||||
|
@ -123,7 +145,7 @@ SRSLTE_API int srslte_enb_ul_detect_prach(srslte_enb_ul_t *q,
|
|||
cf_t *signal,
|
||||
uint32_t *indices,
|
||||
float *offsets,
|
||||
float *peak2avg);
|
||||
float *peak2avg);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -110,7 +110,8 @@ typedef enum SRSLTE_API {
|
|||
typedef struct {
|
||||
uint32_t config_idx;
|
||||
uint32_t root_seq_idx;
|
||||
uint32_t zero_corr_zone;
|
||||
uint32_t zero_corr_zone;
|
||||
uint32_t freq_offset;
|
||||
bool hs_flag;
|
||||
} srslte_prach_cfg_t;
|
||||
|
||||
|
|
|
@ -64,15 +64,18 @@ typedef struct SRSLTE_API {
|
|||
}srslte_pucch_sched_t;
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
// Common configuration
|
||||
uint32_t delta_pucch_shift;
|
||||
uint32_t n_rb_2;
|
||||
uint32_t N_cs;
|
||||
|
||||
// SRS configuration
|
||||
bool srs_configured;
|
||||
uint32_t srs_cs_subf_cfg;
|
||||
bool srs_simul_ack;
|
||||
} srslte_pucch_cfg_t;
|
||||
|
||||
/* PUSCH object */
|
||||
/* PUCCH object */
|
||||
typedef struct SRSLTE_API {
|
||||
srslte_cell_t cell;
|
||||
srslte_pucch_cfg_t pucch_cfg;
|
||||
|
@ -85,9 +88,15 @@ typedef struct SRSLTE_API {
|
|||
uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME];
|
||||
float tmp_arg[SRSLTE_PUCCH_N_SEQ];
|
||||
cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS];
|
||||
cf_t z_tmp[SRSLTE_PUCCH_MAX_SYMBOLS];
|
||||
cf_t ce[SRSLTE_PUCCH_MAX_SYMBOLS];
|
||||
bool rnti_is_set;
|
||||
bool shortened;
|
||||
bool group_hopping_en;
|
||||
|
||||
float threshold_format1;
|
||||
float threshold_format1a;
|
||||
|
||||
}srslte_pucch_t;
|
||||
|
||||
|
||||
|
@ -100,6 +109,10 @@ SRSLTE_API bool srslte_pucch_set_cfg(srslte_pucch_t* q,
|
|||
srslte_pucch_cfg_t* cfg,
|
||||
bool group_hopping_en);
|
||||
|
||||
SRSLTE_API void srslte_pucch_set_threshold(srslte_pucch_t *q,
|
||||
float format1,
|
||||
float format1a);
|
||||
|
||||
SRSLTE_API int srslte_pucch_set_crnti(srslte_pucch_t *q,
|
||||
uint16_t c_rnti);
|
||||
|
||||
|
@ -114,6 +127,15 @@ SRSLTE_API int srslte_pucch_encode(srslte_pucch_t *q,
|
|||
uint8_t bits[SRSLTE_PUCCH_MAX_BITS],
|
||||
cf_t *sf_symbols);
|
||||
|
||||
SRSLTE_API int srslte_pucch_decode(srslte_pucch_t *q,
|
||||
srslte_pucch_format_t format,
|
||||
uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format
|
||||
uint32_t sf_idx,
|
||||
cf_t *sf_symbols,
|
||||
cf_t *ce,
|
||||
float noise_estimate,
|
||||
uint8_t bits[SRSLTE_PUCCH_MAX_BITS]);
|
||||
|
||||
SRSLTE_API float srslte_pucch_alpha_format1(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB],
|
||||
srslte_pucch_cfg_t *cfg,
|
||||
uint32_t n_pucch,
|
||||
|
@ -135,6 +157,13 @@ SRSLTE_API uint32_t srslte_pucch_m(srslte_pucch_cfg_t *cfg,
|
|||
uint32_t n_pucch,
|
||||
srslte_cp_t cp);
|
||||
|
||||
SRSLTE_API uint32_t srslte_pucch_n_prb(srslte_pucch_cfg_t *cfg,
|
||||
srslte_pucch_format_t format,
|
||||
uint32_t n_pucch,
|
||||
uint32_t nof_prb,
|
||||
srslte_cp_t cp,
|
||||
uint32_t ns);
|
||||
|
||||
SRSLTE_API int srslte_pucch_n_cs_cell(srslte_cell_t cell,
|
||||
uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB]);
|
||||
|
||||
|
|
|
@ -84,6 +84,12 @@ int srslte_chest_ul_init(srslte_chest_ul_t *q, srslte_cell_t cell)
|
|||
goto clean_exit;
|
||||
}
|
||||
|
||||
q->pilot_known_signal = srslte_vec_malloc(sizeof(cf_t) * (NOF_REFS_SF+1));
|
||||
if (!q->pilot_known_signal) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, NOF_REFS_SYM)) {
|
||||
fprintf(stderr, "Error initializing vector interpolator\n");
|
||||
goto clean_exit;
|
||||
|
@ -122,6 +128,9 @@ void srslte_chest_ul_free(srslte_chest_ul_t *q)
|
|||
if (q->pilot_recv_signal) {
|
||||
free(q->pilot_recv_signal);
|
||||
}
|
||||
if (q->pilot_known_signal) {
|
||||
free(q->pilot_known_signal);
|
||||
}
|
||||
bzero(q, sizeof(srslte_chest_ul_t));
|
||||
}
|
||||
|
||||
|
@ -252,6 +261,59 @@ int srslte_chest_ul_estimate(srslte_chest_ul_t *q, cf_t *input, cf_t *ce,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int srslte_chest_ul_estimate_pucch(srslte_chest_ul_t *q, cf_t *input, cf_t *ce,
|
||||
srslte_pucch_format_t format, uint32_t n_pucch, uint32_t sf_idx)
|
||||
{
|
||||
if (!q->dmrs_signal_configured) {
|
||||
fprintf(stderr, "Error must call srslte_chest_ul_set_cfg() before using the UL estimator\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
int n_rs = srslte_refsignal_dmrs_N_rs(format, q->cell.cp);
|
||||
int nrefs_sf = SRSLTE_NRE*n_rs*2;
|
||||
|
||||
/* Get references from the input signal */
|
||||
srslte_refsignal_dmrs_pucch_get(&q->dmrs_signal, format, n_pucch, input, q->pilot_recv_signal);
|
||||
|
||||
/* Generate known pilots */
|
||||
uint8_t pucch2_bits[2] = {0, 0};
|
||||
srslte_refsignal_dmrs_pucch_gen(&q->dmrs_signal, format, n_pucch, sf_idx, pucch2_bits, q->pilot_known_signal),
|
||||
|
||||
/* Use the known DMRS signal to compute Least-squares estimates */
|
||||
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->pilot_known_signal, q->pilot_estimates, nrefs_sf);
|
||||
|
||||
if (ce != NULL) {
|
||||
/* FIXME: Currently averaging entire slot, performance good enough? */
|
||||
for (int ns=0;ns<2;ns++) {
|
||||
// Average all slot
|
||||
for (int i=1;i<n_rs;i++) {
|
||||
srslte_vec_sum_ccc(&q->pilot_estimates[ns*n_rs*SRSLTE_NRE], &q->pilot_estimates[(i+ns*n_rs)*SRSLTE_NRE],
|
||||
&q->pilot_estimates[ns*n_rs*SRSLTE_NRE],
|
||||
SRSLTE_NRE);
|
||||
}
|
||||
srslte_vec_sc_prod_ccc(&q->pilot_estimates[ns*n_rs*SRSLTE_NRE], (float) 1.0/n_rs,
|
||||
&q->pilot_estimates[ns*n_rs*SRSLTE_NRE],
|
||||
SRSLTE_NRE);
|
||||
|
||||
// Average in freq domain
|
||||
srslte_chest_average_pilots(&q->pilot_estimates[ns*n_rs*SRSLTE_NRE], &q->pilot_recv_signal[ns*n_rs*SRSLTE_NRE],
|
||||
q->smooth_filter, SRSLTE_NRE, 1, q->smooth_filter_len);
|
||||
|
||||
// Determine n_prb
|
||||
uint32_t n_prb = srslte_pucch_n_prb(&q->dmrs_signal.pucch_cfg, format, n_pucch, q->cell.nof_prb, q->cell.cp, ns);
|
||||
|
||||
// copy estimates to slot
|
||||
for (int i=0;i<SRSLTE_CP_NSYMB(q->cell.cp);i++) {
|
||||
memcpy(&ce[SRSLTE_RE_IDX(q->cell.nof_prb, i+ns*SRSLTE_CP_NSYMB(q->cell.cp), n_prb*SRSLTE_NRE)],
|
||||
&q->pilot_recv_signal[ns*n_rs*SRSLTE_NRE], sizeof(cf_t)*SRSLTE_NRE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
float srslte_chest_ul_get_noise_estimate(srslte_chest_ul_t *q) {
|
||||
return q->noise_estimate;
|
||||
}
|
||||
|
|
|
@ -452,7 +452,7 @@ int srslte_refsignal_dmrs_pusch_gen(srslte_refsignal_ul_t *q, uint32_t nof_prb,
|
|||
}
|
||||
|
||||
/* Number of PUCCH demodulation reference symbols per slot N_rs_pucch tABLE 5.5.2.2.1-1 36.211 */
|
||||
static uint32_t get_N_rs(srslte_pucch_format_t format, srslte_cp_t cp) {
|
||||
uint32_t srslte_refsignal_dmrs_N_rs(srslte_pucch_format_t format, srslte_cp_t cp) {
|
||||
switch (format) {
|
||||
case SRSLTE_PUCCH_FORMAT_1:
|
||||
case SRSLTE_PUCCH_FORMAT_1A:
|
||||
|
@ -476,7 +476,7 @@ static uint32_t get_N_rs(srslte_pucch_format_t format, srslte_cp_t cp) {
|
|||
}
|
||||
|
||||
/* Table 5.5.2.2.2-1: Demodulation reference signal location for different PUCCH formats. 36.211 */
|
||||
static uint32_t get_pucch_dmrs_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t cp) {
|
||||
uint32_t srslte_refsignal_dmrs_pucch_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t cp) {
|
||||
switch (format) {
|
||||
case SRSLTE_PUCCH_FORMAT_1:
|
||||
case SRSLTE_PUCCH_FORMAT_1A:
|
||||
|
@ -523,7 +523,7 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
|
|||
if (q && r_pucch) {
|
||||
ret = SRSLTE_ERROR;
|
||||
|
||||
uint32_t N_rs=get_N_rs(format, q->cell.cp);
|
||||
uint32_t N_rs=srslte_refsignal_dmrs_N_rs(format, q->cell.cp);
|
||||
|
||||
cf_t z_m_1 = 1.0;
|
||||
if (format == SRSLTE_PUCCH_FORMAT_2A || format == SRSLTE_PUCCH_FORMAT_2B) {
|
||||
|
@ -543,7 +543,7 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
|
|||
for (uint32_t m=0;m<N_rs;m++) {
|
||||
uint32_t n_oc=0;
|
||||
|
||||
uint32_t l = get_pucch_dmrs_symbol(m, format, q->cell.cp);
|
||||
uint32_t l = srslte_refsignal_dmrs_pucch_symbol(m, format, q->cell.cp);
|
||||
// Add cyclic prefix alpha
|
||||
float alpha = 0.0;
|
||||
if (format < SRSLTE_PUCCH_FORMAT_2) {
|
||||
|
@ -594,36 +594,48 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Maps PUCCH DMRS to the physical resources as defined in 5.5.2.2.2 in 36.211 */
|
||||
int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *r_pucch, cf_t *output)
|
||||
int srslte_refsignal_dmrs_pucch_cp(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *source, cf_t *dest, bool source_is_grid)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
if (q && output && r_pucch) {
|
||||
if (q && source && dest) {
|
||||
ret = SRSLTE_ERROR;
|
||||
uint32_t nsymbols = SRSLTE_CP_ISNORM(q->cell.cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB;
|
||||
|
||||
// Determine m
|
||||
uint32_t m = srslte_pucch_m(&q->pucch_cfg, format, n_pucch, q->cell.cp);
|
||||
|
||||
uint32_t N_rs = get_N_rs(format, q->cell.cp);
|
||||
|
||||
uint32_t N_rs = srslte_refsignal_dmrs_N_rs(format, q->cell.cp);
|
||||
for (uint32_t ns=0;ns<2;ns++) {
|
||||
// Determine n_prb
|
||||
uint32_t n_prb = m/2;
|
||||
if ((m+ns)%2) {
|
||||
n_prb = q->cell.nof_prb-1-m/2;
|
||||
}
|
||||
|
||||
|
||||
// Determine n_prb
|
||||
uint32_t n_prb = srslte_pucch_n_prb(&q->pucch_cfg, format, n_pucch, q->cell.nof_prb, q->cell.cp, ns);
|
||||
|
||||
for (uint32_t i=0;i<N_rs;i++) {
|
||||
uint32_t l = get_pucch_dmrs_symbol(i, format, q->cell.cp);
|
||||
memcpy(&output[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)],
|
||||
&r_pucch[ns*N_rs*SRSLTE_NRE+i*SRSLTE_NRE],
|
||||
SRSLTE_NRE*sizeof(cf_t));
|
||||
uint32_t l = srslte_refsignal_dmrs_pucch_symbol(i, format, q->cell.cp);
|
||||
if (!source_is_grid) {
|
||||
memcpy(&dest[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)],
|
||||
&source[ns*N_rs*SRSLTE_NRE+i*SRSLTE_NRE],
|
||||
SRSLTE_NRE*sizeof(cf_t));
|
||||
} else {
|
||||
memcpy(&dest[ns*N_rs*SRSLTE_NRE+i*SRSLTE_NRE],
|
||||
&source[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)],
|
||||
SRSLTE_NRE*sizeof(cf_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Maps PUCCH DMRS to the physical resources as defined in 5.5.2.2.2 in 36.211 */
|
||||
int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *r_pucch, cf_t *output)
|
||||
{
|
||||
return srslte_refsignal_dmrs_pucch_cp(q, format, n_pucch, r_pucch, output, false);
|
||||
}
|
||||
|
||||
/* Gets PUCCH DMRS from the physical resources as defined in 5.5.2.2.2 in 36.211 */
|
||||
int srslte_refsignal_dmrs_pucch_get(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *input, cf_t *r_pucch)
|
||||
{
|
||||
return srslte_refsignal_dmrs_pucch_cp(q, format, n_pucch, input, r_pucch, true);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell,
|
||||
srslte_prach_cfg_t *prach_cfg,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
|
||||
srslte_pusch_hopping_cfg_t *hopping_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg,
|
||||
uint32_t nof_rnti)
|
||||
{
|
||||
|
@ -57,6 +58,16 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell,
|
|||
q->cell = cell;
|
||||
q->nof_rnti = nof_rnti;
|
||||
|
||||
if (hopping_cfg) {
|
||||
memcpy(&q->hopping_cfg, hopping_cfg, sizeof(srslte_pusch_hopping_cfg_t));
|
||||
}
|
||||
|
||||
q->uci_cfg_en = calloc(sizeof(bool),nof_rnti);
|
||||
q->srs_cfg_en = calloc(sizeof(bool),nof_rnti);
|
||||
|
||||
q->uci_cfg = calloc(sizeof(srslte_uci_cfg_t),nof_rnti);
|
||||
q->srs_cfg = calloc(sizeof(srslte_refsignal_srs_cfg_t),nof_rnti);
|
||||
|
||||
if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating FFT\n");
|
||||
goto clean_exit;
|
||||
|
@ -91,6 +102,9 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell,
|
|||
goto clean_exit;
|
||||
}
|
||||
|
||||
// Configure common PUCCH configuration
|
||||
srslte_pucch_set_cfg(&q->pucch, pucch_cfg, pusch_cfg->group_hopping_en);
|
||||
|
||||
// SRS is a dedicated configuration
|
||||
srslte_chest_ul_set_cfg(&q->chest, pusch_cfg, pucch_cfg, NULL);
|
||||
|
||||
|
@ -123,6 +137,20 @@ clean_exit:
|
|||
void srslte_enb_ul_free(srslte_enb_ul_t *q)
|
||||
{
|
||||
if (q) {
|
||||
|
||||
if (q->uci_cfg) {
|
||||
free(q->uci_cfg);
|
||||
}
|
||||
if (q->uci_cfg_en) {
|
||||
free(q->uci_cfg_en);
|
||||
}
|
||||
if (q->srs_cfg) {
|
||||
free(q->srs_cfg);
|
||||
}
|
||||
if (q->srs_cfg_en) {
|
||||
free(q->srs_cfg_en);
|
||||
}
|
||||
|
||||
srslte_prach_free(&q->prach);
|
||||
srslte_ofdm_rx_free(&q->fft);
|
||||
srslte_pucch_free(&q->pucch);
|
||||
|
@ -143,6 +171,30 @@ int srslte_enb_ul_cfg_rnti(srslte_enb_ul_t *q, uint32_t idx, uint16_t rnti)
|
|||
return srslte_pusch_set_rnti_multi(&q->pusch, idx, rnti);
|
||||
}
|
||||
|
||||
int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint32_t idx,
|
||||
srslte_uci_cfg_t *uci_cfg,
|
||||
srslte_refsignal_srs_cfg_t *srs_cfg)
|
||||
{
|
||||
if (idx < q->nof_rnti) {
|
||||
if (uci_cfg) {
|
||||
memcpy(&q->uci_cfg[idx], uci_cfg, sizeof(srslte_uci_cfg_t));
|
||||
q->uci_cfg_en[idx] = true;
|
||||
} else {
|
||||
q->uci_cfg_en[idx] = false;
|
||||
}
|
||||
if (srs_cfg) {
|
||||
memcpy(&q->srs_cfg[idx], srs_cfg, sizeof(srslte_refsignal_srs_cfg_t));
|
||||
q->srs_cfg_en[idx] = true;
|
||||
} else {
|
||||
q->srs_cfg_en[idx] = false;
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
} else {
|
||||
fprintf(stderr, "Error configuring UE: Invalid idx=%d, max users=%d\n", idx, q->nof_rnti);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
int srslte_enb_ul_rem_rnti(srslte_enb_ul_t *q, uint32_t idx)
|
||||
{
|
||||
return srslte_pusch_set_rnti_multi(&q->pusch, idx, 0);
|
||||
|
@ -153,12 +205,58 @@ void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer)
|
|||
srslte_ofdm_rx_sf(&q->fft, signal_buffer, q->sf_symbols);
|
||||
}
|
||||
|
||||
int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch,
|
||||
uint32_t rnti_idx, srslte_uci_data_t *uci_data, uint32_t tti)
|
||||
{
|
||||
|
||||
if (srslte_chest_ul_estimate_pucch(&q->chest, q->sf_symbols, q->ce, format, n_pucch, tti%10)) {
|
||||
fprintf(stderr,"Error estimating PUCCH DMRS\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
float noise_power = srslte_chest_ul_get_noise_estimate(&q->chest);
|
||||
|
||||
uint8_t bits[SRSLTE_PUCCH_MAX_BITS];
|
||||
if (srslte_pucch_decode(&q->pucch, format, n_pucch, tti%10, q->sf_symbols, q->ce, noise_power, bits)) {
|
||||
fprintf(stderr,"Error decoding PUCCH\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
switch(format) {
|
||||
case SRSLTE_PUCCH_FORMAT_1:
|
||||
if (bits[0]) {
|
||||
uci_data->scheduling_request = true;
|
||||
}
|
||||
break;
|
||||
case SRSLTE_PUCCH_FORMAT_1A:
|
||||
case SRSLTE_PUCCH_FORMAT_1B:
|
||||
uci_data->uci_ack = bits[0];
|
||||
uci_data->uci_ack_len = 1;
|
||||
if (format == SRSLTE_PUCCH_FORMAT_1B) {
|
||||
uci_data->uci_ack_2 = bits[0];
|
||||
uci_data->uci_ack_len = 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error getting PUCCH format %d not supported\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srslte_softbuffer_rx_t *softbuffer,
|
||||
uint32_t rnti_idx, uint32_t rv_idx, uint32_t current_tx_nb,
|
||||
uint8_t *data, srslte_uci_data_t *uci_data, uint32_t tti)
|
||||
{
|
||||
|
||||
if (srslte_pusch_cfg(&q->pusch, &q->pusch_cfg, grant, NULL, NULL, NULL, tti, rv_idx, current_tx_nb)) {
|
||||
if (srslte_pusch_cfg(&q->pusch,
|
||||
&q->pusch_cfg,
|
||||
grant,
|
||||
q->uci_cfg_en[rnti_idx]?&q->uci_cfg[rnti_idx]:NULL,
|
||||
&q->hopping_cfg,
|
||||
q->srs_cfg_en[rnti_idx]?&q->srs_cfg[rnti_idx]:NULL,
|
||||
tti, rv_idx, current_tx_nb)) {
|
||||
fprintf(stderr, "Error configuring PDSCH\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "srslte/phch/pucch.h"
|
||||
#include "srslte/common/sequence.h"
|
||||
#include "srslte/common/phy_common.h"
|
||||
#include "srslte/mimo/precoding.h"
|
||||
#include "srslte/scrambling/scrambling.h"
|
||||
#include "srslte/utils/debug.h"
|
||||
#include "srslte/utils/vector.h"
|
||||
|
@ -159,6 +160,17 @@ uint32_t get_pucch_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t srslte_pucch_n_prb(srslte_pucch_cfg_t *cfg, srslte_pucch_format_t format, uint32_t n_pucch,
|
||||
uint32_t nof_prb, srslte_cp_t cp, uint32_t ns)
|
||||
{
|
||||
uint32_t m = srslte_pucch_m(cfg, format, n_pucch, cp);
|
||||
// Determine n_prb
|
||||
uint32_t n_prb = m/2;
|
||||
if ((m+ns)%2) {
|
||||
n_prb = nof_prb-1-m/2;
|
||||
}
|
||||
return n_prb;
|
||||
}
|
||||
|
||||
// Compute m according to Section 5.4.3 of 36.211
|
||||
uint32_t srslte_pucch_m(srslte_pucch_cfg_t *cfg, srslte_pucch_format_t format, uint32_t n_pucch, srslte_cp_t cp) {
|
||||
|
@ -250,6 +262,9 @@ float srslte_pucch_alpha_format1(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLT
|
|||
n_cs = (n_cs_cell[ns][l]+(n_prime*cfg->delta_pucch_shift+n_oc/n_oc_div)%N_prime)%SRSLTE_NRE;
|
||||
}
|
||||
|
||||
DEBUG("n_cs=%d, N_prime=%d, delta_pucch=%d, n_prime=%d, ns=%d, l=%d, ns_cs_cell=%d\n",
|
||||
n_cs, N_prime, cfg->delta_pucch_shift, n_prime, ns, l, n_cs_cell[ns][l]);
|
||||
|
||||
return 2 * M_PI * (n_cs) / SRSLTE_NRE;
|
||||
}
|
||||
|
||||
|
@ -281,40 +296,55 @@ float srslte_pucch_alpha_format2(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLT
|
|||
}
|
||||
|
||||
/* Map PUCCH symbols to physical resources according to 5.4.3 in 36.211 */
|
||||
static int pucch_put(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *output) {
|
||||
static int pucch_cp(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *source, cf_t *dest, bool source_is_grid) {
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
if (q && output) {
|
||||
if (q && source && dest) {
|
||||
ret = SRSLTE_ERROR;
|
||||
uint32_t nsymbols = SRSLTE_CP_ISNORM(q->cell.cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB;
|
||||
|
||||
// Determine m
|
||||
uint32_t m = srslte_pucch_m(&q->pucch_cfg, format, n_pucch, q->cell.cp);
|
||||
|
||||
uint32_t n_re = 0;
|
||||
uint32_t N_sf_0 = get_N_sf(format, 0, q->shortened);
|
||||
for (uint32_t ns=0;ns<2;ns++) {
|
||||
uint32_t N_sf = get_N_sf(format, ns%2, q->shortened);
|
||||
// Determine n_prb
|
||||
uint32_t n_prb = m/2;
|
||||
if ((m+ns)%2) {
|
||||
n_prb = q->cell.nof_prb-1-m/2;
|
||||
}
|
||||
|
||||
// Determine n_prb
|
||||
uint32_t n_prb = srslte_pucch_n_prb(&q->pucch_cfg, format, n_pucch, q->cell.nof_prb, q->cell.cp, ns);
|
||||
|
||||
if (n_prb < q->cell.nof_prb) {
|
||||
for (uint32_t i=0;i<N_sf;i++) {
|
||||
uint32_t l = get_pucch_symbol(i, format, q->cell.cp);
|
||||
memcpy(&output[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)],
|
||||
&q->z[i*SRSLTE_NRE+ns*N_sf_0*SRSLTE_NRE],
|
||||
SRSLTE_NRE*sizeof(cf_t));
|
||||
if (!source_is_grid) {
|
||||
memcpy(&dest[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)],
|
||||
&source[i*SRSLTE_NRE+ns*N_sf_0*SRSLTE_NRE],
|
||||
SRSLTE_NRE*sizeof(cf_t));
|
||||
} else {
|
||||
memcpy(&dest[i*SRSLTE_NRE+ns*N_sf_0*SRSLTE_NRE],
|
||||
&source[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)],
|
||||
SRSLTE_NRE*sizeof(cf_t));
|
||||
}
|
||||
n_re += SRSLTE_NRE;
|
||||
}
|
||||
} else {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
ret = SRSLTE_SUCCESS;
|
||||
ret = n_re;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pucch_put(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *z, cf_t *output) {
|
||||
return pucch_cp(q, format, n_pucch, z, output, false);
|
||||
}
|
||||
|
||||
static int pucch_get(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *input, cf_t *z) {
|
||||
return pucch_cp(q, format, n_pucch, input, z, true);
|
||||
}
|
||||
|
||||
void srslte_pucch_set_threshold(srslte_pucch_t *q, float format1, float format1a) {
|
||||
q->threshold_format1 = format1;
|
||||
q->threshold_format1a = format1a;
|
||||
}
|
||||
|
||||
/** Initializes the PDCCH transmitter and receiver */
|
||||
int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
|
||||
|
@ -470,9 +500,59 @@ static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_format_t format, uint8_t
|
|||
// Declare this here, since we can not include refsignal_ul.h
|
||||
void srslte_refsignal_r_uv_arg_1prb(float *arg, uint32_t u);
|
||||
|
||||
static int pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format,
|
||||
uint32_t n_pucch, uint32_t sf_idx,
|
||||
uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS])
|
||||
{
|
||||
if (uci_mod_bits(q, format, bits, sf_idx)) {
|
||||
fprintf(stderr, "Error encoding PUCCH bits\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
uint32_t N_sf_0 = get_N_sf(format, 0, q->shortened);
|
||||
for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) {
|
||||
uint32_t N_sf = get_N_sf(format, ns%2, q->shortened);
|
||||
DEBUG("ns=%d, N_sf=%d\n", ns, N_sf);
|
||||
// Get group hopping number u
|
||||
uint32_t f_gh=0;
|
||||
if (q->group_hopping_en) {
|
||||
f_gh = q->f_gh[ns];
|
||||
}
|
||||
uint32_t u = (f_gh + (q->cell.id%30))%30;
|
||||
|
||||
srslte_refsignal_r_uv_arg_1prb(q->tmp_arg, u);
|
||||
uint32_t N_sf_widx = N_sf==3?1:0;
|
||||
for (uint32_t m=0;m<N_sf;m++) {
|
||||
uint32_t l = get_pucch_symbol(m, format, q->cell.cp);
|
||||
float alpha=0;
|
||||
if (format >= SRSLTE_PUCCH_FORMAT_2) {
|
||||
alpha = srslte_pucch_alpha_format2(q->n_cs_cell, &q->pucch_cfg, n_pucch, ns, l);
|
||||
for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) {
|
||||
z[(ns%2)*N_sf*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->d[(ns%2)*N_sf+m]*cexpf(I*(q->tmp_arg[n]+alpha*n));
|
||||
}
|
||||
} else {
|
||||
uint32_t n_prime_ns=0;
|
||||
uint32_t n_oc=0;
|
||||
alpha = srslte_pucch_alpha_format1(q->n_cs_cell, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, &n_prime_ns);
|
||||
float S_ns = 0;
|
||||
if (n_prime_ns%2) {
|
||||
S_ns = M_PI/2;
|
||||
}
|
||||
DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d, n_rb_2=%d\n",
|
||||
__real__ q->d[0], __imag__ q->d[0], alpha, n_oc, n_prime_ns, q->pucch_cfg.n_rb_2);
|
||||
for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) {
|
||||
z[(ns%2)*N_sf_0*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] =
|
||||
q->d[0]*cexpf(I*(w_n_oc[N_sf_widx][n_oc%3][m]+q->tmp_arg[n]+alpha*n+S_ns));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
/* Encode, modulate and resource mapping of PUCCH bits according to Section 5.4.1 of 36.211 */
|
||||
int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format,
|
||||
uint32_t n_pucch, uint32_t sf_idx, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t *sf_symbols)
|
||||
uint32_t n_pucch, uint32_t sf_idx, uint8_t bits[SRSLTE_PUCCH_MAX_BITS],
|
||||
cf_t *sf_symbols)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
if (q != NULL &&
|
||||
|
@ -496,49 +576,10 @@ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format,
|
|||
fprintf(stderr, "Error encoding PUCCH: C-RNTI must be set before encoding PUCCH Format 2/2a/2b\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if (uci_mod_bits(q, format, bits, sf_idx)) {
|
||||
fprintf(stderr, "Error encoding PUCCH bits\n");
|
||||
if (pucch_encode(q, format, n_pucch, sf_idx, bits, q->z)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
uint32_t N_sf_0 = get_N_sf(format, 0, q->shortened);
|
||||
for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) {
|
||||
uint32_t N_sf = get_N_sf(format, ns%2, q->shortened);
|
||||
DEBUG("ns=%d, N_sf=%d\n", ns, N_sf);
|
||||
// Get group hopping number u
|
||||
uint32_t f_gh=0;
|
||||
if (q->group_hopping_en) {
|
||||
f_gh = q->f_gh[ns];
|
||||
}
|
||||
uint32_t u = (f_gh + (q->cell.id%30))%30;
|
||||
|
||||
srslte_refsignal_r_uv_arg_1prb(q->tmp_arg, u);
|
||||
uint32_t N_sf_widx = N_sf==3?1:0;
|
||||
for (uint32_t m=0;m<N_sf;m++) {
|
||||
uint32_t l = get_pucch_symbol(m, format, q->cell.cp);
|
||||
float alpha=0;
|
||||
if (format >= SRSLTE_PUCCH_FORMAT_2) {
|
||||
alpha = srslte_pucch_alpha_format2(q->n_cs_cell, &q->pucch_cfg, n_pucch, ns, l);
|
||||
for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) {
|
||||
q->z[(ns%2)*N_sf*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->d[(ns%2)*N_sf+m]*cexpf(I*(q->tmp_arg[n]+alpha*n));
|
||||
}
|
||||
} else {
|
||||
uint32_t n_prime_ns=0;
|
||||
uint32_t n_oc=0;
|
||||
alpha = srslte_pucch_alpha_format1(q->n_cs_cell, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, &n_prime_ns);
|
||||
float S_ns = 0;
|
||||
if (n_prime_ns%2) {
|
||||
S_ns = M_PI/2;
|
||||
}
|
||||
DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d, n_rb_2=%d\n",
|
||||
__real__ q->d[0], __imag__ q->d[0], alpha, n_oc, n_prime_ns, q->pucch_cfg.n_rb_2);
|
||||
for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) {
|
||||
q->z[(ns%2)*N_sf_0*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] =
|
||||
q->d[0]*cexpf(I*(w_n_oc[N_sf_widx][n_oc%3][m]+q->tmp_arg[n]+alpha*n+S_ns));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pucch_put(q, format, n_pucch, sf_symbols)) {
|
||||
if (pucch_put(q, format, n_pucch, q->z, sf_symbols) < 0) {
|
||||
fprintf(stderr, "Error putting PUCCH symbols\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
@ -549,3 +590,88 @@ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format,
|
|||
}
|
||||
|
||||
|
||||
/* Equalize, demodulate and decode PUCCH bits according to Section 5.4.1 of 36.211 */
|
||||
int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
|
||||
uint32_t n_pucch, uint32_t sf_idx, cf_t *sf_symbols, cf_t *ce, float noise_estimate,
|
||||
uint8_t bits[SRSLTE_PUCCH_MAX_BITS])
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
if (q != NULL &&
|
||||
ce != NULL &&
|
||||
sf_symbols != NULL)
|
||||
{
|
||||
ret = SRSLTE_ERROR;
|
||||
|
||||
// Shortened PUCCH happen in every cell-specific SRS subframes for Format 1/1a/1b
|
||||
if (q->pucch_cfg.srs_configured && format < SRSLTE_PUCCH_FORMAT_2) {
|
||||
q->shortened = false;
|
||||
// If CQI is not transmitted, PUCCH will be normal unless ACK/NACK and SRS simultaneous transmission is enabled
|
||||
if (q->pucch_cfg.srs_simul_ack) {
|
||||
// If simultaneous ACK and SRS is enabled, PUCCH is shortened in cell-specific SRS subframes
|
||||
if (srslte_refsignal_srs_send_cs(q->pucch_cfg.srs_cs_subf_cfg, sf_idx) == 1) {
|
||||
q->shortened = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (format >= SRSLTE_PUCCH_FORMAT_2 && !q->rnti_is_set) {
|
||||
fprintf(stderr, "Error decoding PUCCH: C-RNTI must be set before encoding PUCCH Format 2/2a/2b\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
int nof_re = pucch_get(q, format, n_pucch, sf_symbols, q->z_tmp);
|
||||
if (nof_re < 0) {
|
||||
fprintf(stderr, "Error getting PUCCH symbols\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (pucch_get(q, format, n_pucch, ce, q->ce) < 0) {
|
||||
fprintf(stderr, "Error getting PUCCH symbols\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Equalization
|
||||
srslte_predecoding_single(q->z_tmp, q->ce, q->z, nof_re, noise_estimate);
|
||||
|
||||
// Perform ML-decoding
|
||||
float corr=0, corr_max=-1e9;
|
||||
int b_max = 0; // default bit value, eg. HI is NACK
|
||||
switch(format) {
|
||||
case SRSLTE_PUCCH_FORMAT_1:
|
||||
bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
|
||||
pucch_encode(q, format, n_pucch, sf_idx, bits, q->z_tmp);
|
||||
corr = crealf(srslte_vec_dot_prod_conj_ccc(q->z, q->z_tmp, nof_re))/nof_re;
|
||||
if (corr >= q->threshold_format1) {
|
||||
bits[0] = 1;
|
||||
} else {
|
||||
bits[0] = 0;
|
||||
}
|
||||
printf("format1 corr=%f, nof_re=%d, th=%f\n", corr, nof_re, q->threshold_format1);
|
||||
break;
|
||||
case SRSLTE_PUCCH_FORMAT_1A:
|
||||
bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
|
||||
|
||||
for (int b=0;b<2;b++) {
|
||||
bits[0] = b;
|
||||
pucch_encode(q, format, n_pucch, sf_idx, bits, q->z_tmp);
|
||||
corr = crealf(srslte_vec_dot_prod_conj_ccc(q->z, q->z_tmp, nof_re))/nof_re;
|
||||
if (corr > corr_max && corr >= q->threshold_format1a) {
|
||||
corr_max = corr;
|
||||
b_max = b;
|
||||
}
|
||||
DEBUG("format1a b=%d, corr=%f, nof_re=%d, th=%f\n", b, corr, nof_re, q->threshold_format1);
|
||||
}
|
||||
bits[0] = b_max;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error decoding PUCCH: Format %d not supported\n", format);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ target_link_libraries(pucch_test srslte)
|
|||
add_test(pucch_test pucch_test)
|
||||
|
||||
BuildMex(MEXNAME pucch_encode SOURCES pucch_encode_test_mex.c LIBRARIES srslte_static srslte_mex)
|
||||
|
||||
BuildMex(MEXNAME pucch SOURCES pucch_test_mex.c LIBRARIES srslte_static srslte_mex)
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue