diff --git a/srslte/examples/prach_ue.c b/srslte/examples/prach_ue.c index b87711f35..4f5dc6e9e 100644 --- a/srslte/examples/prach_ue.c +++ b/srslte/examples/prach_ue.c @@ -388,7 +388,7 @@ int main(int argc, char **argv) { dmrs_cfg.cyclic_shift = 0; dmrs_cfg.cyclic_shift_for_dmrs = 0; dmrs_cfg.en_dmrs_2 = false; - srslte_ue_ul_set_pusch_cfg(&ue_ul, &dmrs_cfg, &hop_cfg); + srslte_ue_ul_set_cfg(&ue_ul, &dmrs_cfg, &hop_cfg, NULL, NULL); cf_t *ul_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); if (!ul_signal) { diff --git a/srslte/include/srslte/ch_estimation/refsignal_ul.h b/srslte/include/srslte/ch_estimation/refsignal_ul.h index d36832ef1..7bd242e50 100644 --- a/srslte/include/srslte/ch_estimation/refsignal_ul.h +++ b/srslte/include/srslte/ch_estimation/refsignal_ul.h @@ -105,9 +105,9 @@ SRSLTE_API void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q, SRSLTE_API int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, - uint8_t pucch2_bits[2], uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format uint32_t sf_idx, + uint8_t pucch2_bits[2], cf_t *r_pucch); SRSLTE_API int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t* q, diff --git a/srslte/include/srslte/phch/pucch.h b/srslte/include/srslte/phch/pucch.h index 980e3cee6..4b9eaebb1 100644 --- a/srslte/include/srslte/phch/pucch.h +++ b/srslte/include/srslte/phch/pucch.h @@ -54,6 +54,16 @@ typedef enum SRSLTE_API { SRSLTE_PUCCH_FORMAT_2B, } srslte_pucch_format_t; +typedef struct SRSLTE_API { + uint32_t n_cce; + bool sps_enabled; + uint32_t tpc_for_pucch; + uint32_t N_pucch_1; + uint32_t n_pucch_1[4]; // 4 n_pucch resources specified by RRC + uint32_t n_pucch_2; + uint32_t n_pucch_sr; +}srslte_pucch_sched_t; + typedef struct SRSLTE_API { float beta_pucch; uint32_t delta_pucch_shift; diff --git a/srslte/include/srslte/phch/uci.h b/srslte/include/srslte/phch/uci.h index d7c1ed6b6..0df2c7768 100644 --- a/srslte/include/srslte/phch/uci.h +++ b/srslte/include/srslte/phch/uci.h @@ -28,7 +28,7 @@ /****************************************************************************** * File: uci.h * - * Description: Uplink control information. + * Description: Uplink control information. Only 1-bit ACK for UCI on PUSCCH is supported * * Reference: 3GPP TS 36.212 version 10.0.0 Release 10 Sec. 5.2.3, 5.2.4 *****************************************************************************/ @@ -59,9 +59,12 @@ typedef struct SRSLTE_API { uint8_t uci_ri; // Only 1-bit supported for RI uint32_t uci_ri_len; uint32_t I_offset_ri; - uint8_t uci_ack; // Only 1-bit supported for HARQ + uint8_t uci_ack; // 1st codeword bit for HARQ-ACK + uint8_t uci_ack_2; // 2st codeword bit for HARQ-ACK uint32_t uci_ack_len; uint32_t I_offset_ack; + bool scheduling_request; + bool channel_selection; } srslte_uci_data_t; SRSLTE_API int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t *q); diff --git a/srslte/include/srslte/ue/ue_dl.h b/srslte/include/srslte/ue/ue_dl.h index 99540f371..4e04ea519 100644 --- a/srslte/include/srslte/ue/ue_dl.h +++ b/srslte/include/srslte/ue/ue_dl.h @@ -84,6 +84,7 @@ typedef struct SRSLTE_API { uint64_t nof_detected; uint16_t current_rnti; + uint32_t last_n_cce; }srslte_ue_dl_t; /* This function shall be called just after the initial synchronization */ @@ -117,6 +118,8 @@ SRSLTE_API int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, uint32_t sf_idx, uint16_t rnti); +SRSLTE_API uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q); + SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t * q, cf_t *input, uint8_t *data, diff --git a/srslte/include/srslte/ue/ue_ul.h b/srslte/include/srslte/ue/ue_ul.h index c13da11ec..f5e29e60f 100644 --- a/srslte/include/srslte/ue/ue_ul.h +++ b/srslte/include/srslte/ue/ue_ul.h @@ -66,6 +66,9 @@ typedef struct SRSLTE_API { srslte_refsignal_ul_t dmrs; srslte_harq_t harq_process[SRSLTE_UE_UL_NOF_HARQ_PROCESSES]; srslte_pusch_t pusch; + srslte_pucch_t pucch; + + srslte_pucch_sched_t pucch_sched; cf_t *refsignal; cf_t *sf_symbols; @@ -88,9 +91,16 @@ SRSLTE_API void srslte_ue_ul_set_cfo_enable(srslte_ue_ul_t *q, SRSLTE_API void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q, bool enabled); -SRSLTE_API void srslte_ue_ul_set_pusch_cfg(srslte_ue_ul_t *q, - srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg, - srslte_pusch_hopping_cfg_t *pusch_hopping_cfg); +SRSLTE_API void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q, + srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg, + srslte_pusch_hopping_cfg_t *pusch_hopping_cfg, + srslte_pucch_cfg_t *pucch_cfg, + srslte_pucch_sched_t *pucch_sched); + +SRSLTE_API int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, + srslte_uci_data_t uci_data, + uint32_t sf_idx, + cf_t *output_signal); SRSLTE_API int srslte_ue_ul_pusch_encode(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, diff --git a/srslte/include/srslte/ue_itf/dl_buffer.h b/srslte/include/srslte/ue_itf/dl_buffer.h index e4bcbe3be..ef95ab298 100644 --- a/srslte/include/srslte/ue_itf/dl_buffer.h +++ b/srslte/include/srslte/ue_itf/dl_buffer.h @@ -66,8 +66,8 @@ namespace ue { bool recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time); bool get_ul_grant(pdcch_ul_search_t mode, sched_grant *grant); bool get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant); - bool decode_phich(srslte::ue::sched_grant pusch_grant); - bool decode_pdsch(sched_grant pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/KO + bool decode_ack(srslte::ue::sched_grant pusch_grant); + bool decode_data(sched_grant pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/KO private: params *params_db; srslte_cell_t cell; diff --git a/srslte/include/srslte/ue_itf/params.h b/srslte/include/srslte/ue_itf/params.h index d4890662d..61fd02586 100644 --- a/srslte/include/srslte/ue_itf/params.h +++ b/srslte/include/srslte/ue_itf/params.h @@ -45,7 +45,6 @@ namespace ue { CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD, // integer that will be divided by 10 PUSCH_BETA, - PUSCH_RS_GROUP_HOPPING_EN, PUSCH_RS_SEQUENCE_HOPPING_EN, PUSCH_RS_CYCLIC_SHIFT, @@ -55,6 +54,18 @@ namespace ue { PUSCH_HOPPING_INTRA_SF, PUSCH_HOPPING_OFFSET, + PUCCH_BETA, + PUCCH_DELTA_SHIFT, + PUCCH_CYCLIC_SHIFT, + PUCCH_N_RB_2, + PUCCH_N_PUCCH_1_0, + PUCCH_N_PUCCH_1_1, + PUCCH_N_PUCCH_1_2, + PUCCH_N_PUCCH_1_3, + PUCCH_N_PUCCH_1, + PUCCH_N_PUCCH_2, + PUCCH_N_PUCCH_SR, + UCI_I_OFFSET_ACK, UCI_I_OFFSET_RI, UCI_I_OFFSET_CQI, diff --git a/srslte/include/srslte/ue_itf/sched_grant.h b/srslte/include/srslte/ue_itf/sched_grant.h index 825bba1f7..c293ce3f8 100644 --- a/srslte/include/srslte/ue_itf/sched_grant.h +++ b/srslte/include/srslte/ue_itf/sched_grant.h @@ -49,6 +49,8 @@ namespace ue { bool is_uplink(); bool is_downlink(); void* get_grant_ptr(); + void set_ncce(uint32_t ncce); + uint32_t get_ncce(); uint32_t get_tbs(); uint32_t get_current_tx_nb(); void set_current_tx_nb(uint32_t current_tx_nb); @@ -60,6 +62,7 @@ namespace ue { uint32_t current_tx_nb; direction_t dir; uint16_t rnti; + uint32_t ncce; }; } diff --git a/srslte/include/srslte/ue_itf/ul_buffer.h b/srslte/include/srslte/ue_itf/ul_buffer.h index 81d645d3f..74fdc6a2a 100644 --- a/srslte/include/srslte/ue_itf/ul_buffer.h +++ b/srslte/include/srslte/ue_itf/ul_buffer.h @@ -39,7 +39,7 @@ namespace srslte { namespace ue { /* Uplink scheduling assignment. The MAC instructs the PHY to prepare an UL packet (PUSCH or PUCCH) - * for transmission. The MAC must call generate_pusch() to set the packet ready for transmission + * for transmission. The MAC must call generate_data() to set the packet ready for transmission */ class SRSLTE_API ul_buffer : public queue::element { @@ -48,9 +48,13 @@ namespace ue { void free_cell(); void set_tti(uint32_t tti); void set_current_tx_nb(uint32_t current_tx_nb); - bool generate_pusch(sched_grant pusch_grant, uint8_t *payload); - bool generate_pusch(sched_grant pusch_grant, uint8_t *payload, srslte_uci_data_t uci_data); - bool generate_pucch(srslte_uci_data_t uci_data); + bool generate_ack(bool ack, sched_grant last_dl_grant); + bool generate_ack(bool ack[2]); + bool generate_sr(); + bool generate_cqi_report(); + bool uci_ready(); + bool generate_data(); + bool generate_data(sched_grant pusch_grant, uint8_t *payload); bool send(radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time); static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission @@ -61,6 +65,9 @@ namespace ue { bool cell_initiated; cf_t* signal_buffer; uint32_t current_tx_nb; + uint32_t last_n_cce; + srslte_uci_data_t uci_data; + bool uci_pending; }; } diff --git a/srslte/lib/ch_estimation/src/refsignal_ul.c b/srslte/lib/ch_estimation/src/refsignal_ul.c index 51f13449b..d9150b082 100644 --- a/srslte/lib/ch_estimation/src/refsignal_ul.c +++ b/srslte/lib/ch_estimation/src/refsignal_ul.c @@ -172,7 +172,9 @@ void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) { void srslte_refsignal_ul_set_pusch_cfg(srslte_refsignal_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *cfg) { - memcpy(&q->pusch_cfg, cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t)); + if (cfg) { + memcpy(&q->pusch_cfg, cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t)); + } } bool srslte_refsignal_ul_set_pucch_cfg(srslte_refsignal_ul_t *q, srslte_pucch_cfg_t *cfg) @@ -375,7 +377,8 @@ static uint32_t get_pucch_dmrs_symbol(uint32_t m, srslte_pucch_format_t format, } /* Generates DMRS for PUCCH according to 5.5.2.2 in 36.211 */ -int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint8_t pucch_bits[2], uint32_t n_pucch, uint32_t sf_idx, cf_t *r_pucch) +int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, + uint32_t sf_idx, uint8_t pucch_bits[2], cf_t *r_pucch) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q && r_pucch) { diff --git a/srslte/lib/phch/src/pucch.c b/srslte/lib/phch/src/pucch.c index 6ddde019b..722cc14ea 100644 --- a/srslte/lib/phch/src/pucch.c +++ b/srslte/lib/phch/src/pucch.c @@ -289,7 +289,6 @@ static int pucch_put(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n return SRSLTE_ERROR; } } - ret = SRSLTE_SUCCESS; } return ret; @@ -350,9 +349,13 @@ int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t c_rnti) { bool srslte_pucch_set_cfg(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg) { - if (srslte_pucch_cfg_isvalid(cfg, q->cell.nof_prb)) { - memcpy(&q->pucch_cfg, cfg, sizeof(srslte_pucch_cfg_t)); - return true; + if (cfg) { + if (srslte_pucch_cfg_isvalid(cfg, q->cell.nof_prb)) { + memcpy(&q->pucch_cfg, cfg, sizeof(srslte_pucch_cfg_t)); + return true; + } else { + return false; + } } else { return false; } diff --git a/srslte/lib/phch/src/pusch.c b/srslte/lib/phch/src/pusch.c index 2f461b6d7..7ac183d39 100644 --- a/srslte/lib/phch/src/pusch.c +++ b/srslte/lib/phch/src/pusch.c @@ -282,7 +282,9 @@ void srslte_pusch_free(srslte_pusch_t *q) { void srslte_pusch_set_hopping_cfg(srslte_pusch_t *q, srslte_pusch_hopping_cfg_t *cfg) { - memcpy(&q->hopping_cfg, cfg, sizeof(srslte_pusch_hopping_cfg_t)); + if (cfg) { + memcpy(&q->hopping_cfg, cfg, sizeof(srslte_pusch_hopping_cfg_t)); + } } /* Precalculate the PUSCH scramble sequences for a given RNTI. This function takes a while diff --git a/srslte/lib/phch/test/pucch_encode_test_mex.c b/srslte/lib/phch/test/pucch_encode_test_mex.c index 9ccf02277..98ff3d22e 100644 --- a/srslte/lib/phch/test/pucch_encode_test_mex.c +++ b/srslte/lib/phch/test/pucch_encode_test_mex.c @@ -191,7 +191,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) return; } - if (srslte_refsignal_dmrs_pucch_gen(&pucch_dmrs, format, pucch2_bits, n_pucch, sf_idx, dmrs_pucch)) { + if (srslte_refsignal_dmrs_pucch_gen(&pucch_dmrs, format, n_pucch, sf_idx, pucch2_bits, dmrs_pucch)) { mexErrMsgTxt("Error generating PUCCH DMRS\n"); return; } diff --git a/srslte/lib/ue/src/ue_dl.c b/srslte/lib/ue/src/ue_dl.c index dda5fd843..08151509b 100644 --- a/srslte/lib/ue/src/ue_dl.c +++ b/srslte/lib/ue/src/ue_dl.c @@ -259,6 +259,10 @@ int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint3 return crc_rem == rnti; } +uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q) { + return q->last_n_cce; +} + int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, uint16_t rnti) { srslte_dci_location_t locations[MAX_CANDIDATES]; @@ -281,6 +285,7 @@ int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint3 for (int f=0;flast_n_cce = locations[i].ncce; if (srslte_pdcch_decode_msg(&q->pdcch, dci_msg, &locations[i], formats[f], &crc_rem)) { fprintf(stderr, "Error decoding DCI msg\n"); return SRSLTE_ERROR; diff --git a/srslte/lib/ue/src/ue_ul.c b/srslte/lib/ue/src/ue_ul.c index 42ac58e75..3f0668108 100644 --- a/srslte/lib/ue/src/ue_ul.c +++ b/srslte/lib/ue/src/ue_ul.c @@ -70,6 +70,10 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q, fprintf(stderr, "Error creating PUSCH object\n"); goto clean_exit; } + if (srslte_pucch_init(&q->pucch, q->cell)) { + fprintf(stderr, "Error creating PUSCH object\n"); + goto clean_exit; + } for (uint32_t i=0;iharq_process[i], q->cell)) { fprintf(stderr, "Error initiating HARQ process\n"); @@ -108,6 +112,7 @@ void srslte_ue_ul_free(srslte_ue_ul_t *q) { if (q) { srslte_ofdm_rx_free(&q->fft); srslte_pusch_free(&q->pusch); + srslte_pucch_free(&q->pucch); for (uint32_t i=0;iharq_process[i]); } @@ -145,16 +150,142 @@ void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q, bool enabled) void srslte_ue_ul_set_rnti(srslte_ue_ul_t *q, uint16_t rnti) { q->current_rnti = rnti; srslte_pusch_set_rnti(&q->pusch, rnti); + srslte_pucch_set_crnti(&q->pucch, rnti); } void srslte_ue_ul_reset(srslte_ue_ul_t *q) { srslte_harq_reset(&q->harq_process[0]); } -void srslte_ue_ul_set_pusch_cfg(srslte_ue_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg, srslte_pusch_hopping_cfg_t *pusch_hopping_cfg) +void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q, + srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg, + srslte_pusch_hopping_cfg_t *pusch_hopping_cfg, + srslte_pucch_cfg_t *pucch_cfg, + srslte_pucch_sched_t *pucch_sched) { srslte_refsignal_ul_set_pusch_cfg(&q->dmrs, dmrs_cfg); srslte_pusch_set_hopping_cfg(&q->pusch, pusch_hopping_cfg); + srslte_pucch_set_cfg(&q->pucch, pucch_cfg); + if (pucch_sched) { + memcpy(&q->pucch_sched, pucch_sched, sizeof(srslte_pucch_sched_t)); + } +} + +/* Choose PUCCH format as in Sec 10.1 of 36.213 and generate PUCCH signal + */ +int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data, + uint32_t sf_idx, + cf_t *output_signal) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + output_signal != NULL) + { + + ret = SRSLTE_ERROR; + bzero(q->sf_symbols, sizeof(cf_t)*SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)); + + srslte_pucch_format_t format; + uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS]; + uint8_t pucch2_bits[2]; + bzero(pucch_bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); + bzero(pucch2_bits, 2*sizeof(uint8_t)); + + // 1-bit ACK + SR + if (uci_data.uci_ack_len == 1) { + format = SRSLTE_PUCCH_FORMAT_1A; + pucch_bits[0] = uci_data.uci_ack; + } + // 2-bit ACK + SR + else if (uci_data.uci_ack_len == 2 && uci_data.scheduling_request) { + format = SRSLTE_PUCCH_FORMAT_1B; + pucch_bits[0] = uci_data.uci_ack; + pucch_bits[1] = uci_data.uci_ack_2; + } + // 2-bit ACK with channel selection + else if (uci_data.uci_ack_len == 2 && uci_data.channel_selection) { + format = SRSLTE_PUCCH_FORMAT_1B; + pucch_bits[0] = uci_data.uci_ack; + pucch_bits[1] = uci_data.uci_ack_2; + } + // scheduling_request + else if (uci_data.scheduling_request) { + format = SRSLTE_PUCCH_FORMAT_1; + } + // CQI and no ack + else if (uci_data.uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data.uci_ack_len == 0) { + format = SRSLTE_PUCCH_FORMAT_2; + memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); + } + // CQI + 1-bit ACK + else if (uci_data.uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data.uci_ack_len == 1) { + format = SRSLTE_PUCCH_FORMAT_2A; + memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); + pucch2_bits[0] = uci_data.uci_ack; + } + // CQI + 2-bit ACK + else if (uci_data.uci_cqi_len == 20 && uci_data.uci_ack_len == 2) { + format = SRSLTE_PUCCH_FORMAT_2B; + memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); + pucch2_bits[0] = uci_data.uci_ack; + pucch2_bits[1] = uci_data.uci_ack_2; + } + // CQI + 2-bit ACK + cyclic prefix + else if (uci_data.uci_cqi_len == 20 && uci_data.uci_ack_len == 1 && SRSLTE_CP_ISEXT(q->cell.cp)) { + format = SRSLTE_PUCCH_FORMAT_2B; + memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); + pucch2_bits[0] = uci_data.uci_ack; + pucch2_bits[1] = uci_data.uci_ack_2; + } else { + fprintf(stderr, "Unsupported combination of UCI parameters\n"); + return SRSLTE_ERROR; + } + + // Choose n_pucch + uint32_t n_pucch = 0; + if (format == SRSLTE_PUCCH_FORMAT_1) { + n_pucch = q->pucch_sched.n_pucch_sr; + } else if (format < SRSLTE_PUCCH_FORMAT_2) { + if (q->pucch_sched.sps_enabled) { + n_pucch = q->pucch_sched.n_pucch_1[q->pucch_sched.tpc_for_pucch%4]; + } else { + n_pucch = q->pucch_sched.n_cce + q->pucch_sched.N_pucch_1; + } + } else { + n_pucch = q->pucch_sched.n_pucch_2; + } + if (srslte_pucch_encode(&q->pucch, format, n_pucch, sf_idx, pucch_bits, q->sf_symbols)) { + fprintf(stderr, "Error encoding TB\n"); + return ret; + } + + if (srslte_refsignal_dmrs_pucch_gen(&q->dmrs, format, n_pucch, sf_idx, pucch2_bits, q->refsignal)) + { + fprintf(stderr, "Error generating PUSCH DRMS signals\n"); + return ret; + } + srslte_refsignal_dmrs_pucch_put(&q->dmrs, format, n_pucch, q->refsignal, q->sf_symbols); + + srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); + + if (q->cfo_en) { + srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); + } + + if (q->normalize_en) { + uint32_t n_prb = 1; + if (q->harq_process[0].ul_alloc.L_prb > 0) { + n_prb = q->harq_process[0].ul_alloc.L_prb; + } + float norm_factor = (float) q->cell.nof_prb/10/sqrtf(n_prb); + srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); + } + srslte_vec_save_file("pucch", output_signal, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); + ret = SRSLTE_SUCCESS; + } + + return ret; } int srslte_ue_ul_pusch_encode(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, uint32_t sf_idx, cf_t *output_signal) diff --git a/srslte/lib/ue_itf/src/dl_buffer.cc b/srslte/lib/ue_itf/src/dl_buffer.cc index 4d372ec98..f3155a6e0 100644 --- a/srslte/lib/ue_itf/src/dl_buffer.cc +++ b/srslte/lib/ue_itf/src/dl_buffer.cc @@ -145,6 +145,8 @@ bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant) return false; } + grant->set_ncce(srslte_ue_dl_get_ncce(&ue_dl)); + if (srslte_dci_msg_to_ra_dl(&dci_msg, grant->get_rnti(), cell, cfi, (srslte_ra_pdsch_t*) grant->get_grant_ptr())) { return false; @@ -154,7 +156,7 @@ bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant) } } -bool dl_buffer::decode_phich(sched_grant pusch_grant) +bool dl_buffer::decode_ack(sched_grant pusch_grant) { if (signal_buffer && is_ready()) { if (!sf_symbols_and_ce_done) { @@ -170,7 +172,7 @@ bool dl_buffer::decode_phich(sched_grant pusch_grant) } } -bool dl_buffer::decode_pdsch(sched_grant pdsch_grant, uint8_t *payload) +bool dl_buffer::decode_data(sched_grant pdsch_grant, uint8_t *payload) { if (signal_buffer && is_ready()) { INFO("DL Buffer TTI %d: Decoding PDSCH\n", tti); diff --git a/srslte/lib/ue_itf/src/phy.cc b/srslte/lib/ue_itf/src/phy.cc index 816fa3f15..e0983f791 100644 --- a/srslte/lib/ue_itf/src/phy.cc +++ b/srslte/lib/ue_itf/src/phy.cc @@ -398,9 +398,13 @@ void phy::run_rx_tx_state() prach_buffer.send(radio_handler, cfo, last_rx_time); } // send ul buffer if we have to - if (get_ul_buffer_adv(current_tti)->is_released()) { + if (get_ul_buffer_adv(current_tti)->is_released() || get_ul_buffer_adv(current_tti)->uci_ready()) { + // Generate PUCCH if no UL grant + if (!get_ul_buffer_adv(current_tti)->is_released()) { + get_ul_buffer_adv(current_tti)->generate_data(); + } get_ul_buffer_adv(current_tti)->send(radio_handler, time_adv_sec, cfo, last_rx_time); - } + } // Receive alligned buffer for the current tti get_dl_buffer(current_tti)->recv_ue_sync(&ue_sync, &last_rx_time); diff --git a/srslte/lib/ue_itf/src/prach.cc b/srslte/lib/ue_itf/src/prach.cc index 6cb5caec6..bd101ea1b 100644 --- a/srslte/lib/ue_itf/src/prach.cc +++ b/srslte/lib/ue_itf/src/prach.cc @@ -140,7 +140,7 @@ bool prach::send(radio *radio_handler, float cfo, srslte_timestamp_t rx_time) srslte_timestamp_add(&tx_time, 0, 1e-3*tx_advance_sf); // Correct CFO before transmission - srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, 1.7*cfo / srslte_symbol_sz(cell.nof_prb)); + srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, 2*cfo / srslte_symbol_sz(cell.nof_prb)); // transmit radio_handler->tx(signal_buffer, len, tx_time); diff --git a/srslte/lib/ue_itf/src/sched_grant.cc b/srslte/lib/ue_itf/src/sched_grant.cc index c610c8d68..8076120a7 100644 --- a/srslte/lib/ue_itf/src/sched_grant.cc +++ b/srslte/lib/ue_itf/src/sched_grant.cc @@ -62,6 +62,16 @@ namespace ue { } } + uint32_t sched_grant::get_ncce() + { + return ncce; + } + + void sched_grant::set_ncce(uint32_t ncce_) + { + ncce = ncce_; + } + uint32_t sched_grant::get_current_tx_nb() { return current_tx_nb; diff --git a/srslte/lib/ue_itf/src/ul_buffer.cc b/srslte/lib/ue_itf/src/ul_buffer.cc index 76485ba19..8de147651 100644 --- a/srslte/lib/ue_itf/src/ul_buffer.cc +++ b/srslte/lib/ue_itf/src/ul_buffer.cc @@ -46,6 +46,8 @@ bool ul_buffer::init_cell(srslte_cell_t cell_, params *params_db_) { signal_buffer = (cf_t*) srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); cell_initiated = signal_buffer?true:false; srslte_ue_ul_set_cfo_enable(&ue_ul, false); + bzero(&uci_data, sizeof(srslte_uci_data_t)); + uci_pending = false; return cell_initiated; } else { return false; @@ -61,27 +63,45 @@ void ul_buffer::free_cell() { } } -bool ul_buffer::generate_pusch(sched_grant pusch_grant, - uint8_t *payload) +bool ul_buffer::generate_ack(bool ack, sched_grant last_dl_grant) { - srslte_uci_data_t uci_data; - bzero(&uci_data, sizeof(srslte_uci_data_t)); - return generate_pusch(pusch_grant, payload, uci_data); + uci_data.uci_ack_len = 1; + uci_data.uci_ack = ack?1:0; + uci_pending = true; + last_n_cce = last_dl_grant.get_ncce(); } -bool ul_buffer::generate_pusch(sched_grant pusch_grant, - uint8_t *payload, - srslte_uci_data_t uci_data) +bool ul_buffer::generate_ack(bool ack[2]) +{ + uci_data.uci_ack_len = 2; + uci_data.uci_ack = ack[0]?1:0; + uci_data.uci_ack_2 = ack[1]?1:0; + uci_pending = true; +} + +bool ul_buffer::generate_sr() { + uci_data.scheduling_request = true; + uci_pending = true; +} + +bool ul_buffer::uci_ready() { + return uci_pending; +} + +bool ul_buffer::generate_data() { + sched_grant dummy(sched_grant::DOWNLINK, 0); + return generate_data(dummy, NULL); +} + +bool ul_buffer::generate_data(sched_grant pusch_grant, + uint8_t *payload) { if (is_ready()) { - if (!pusch_grant.is_uplink()) { - fprintf(stderr, "Error in UL buffer: Invalid scheduling grant. Grant is for Downlink\n"); - return false; - } - srslte_refsignal_dmrs_pusch_cfg_t dmrs_cfg; - bzero(&dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t)); + bzero(signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb)); + srslte_refsignal_dmrs_pusch_cfg_t dmrs_cfg; + bzero(&dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t)); dmrs_cfg.beta_pusch = (float) params_db->get_param(params::PUSCH_BETA)/10; dmrs_cfg.group_hopping_en = params_db->get_param(params::PUSCH_RS_GROUP_HOPPING_EN); dmrs_cfg.sequence_hopping_en = params_db->get_param(params::PUSCH_RS_SEQUENCE_HOPPING_EN); @@ -89,6 +109,7 @@ bool ul_buffer::generate_pusch(sched_grant pusch_grant, dmrs_cfg.delta_ss = params_db->get_param(params::PUSCH_RS_GROUP_ASSIGNMENT); srslte_pusch_hopping_cfg_t pusch_hopping; + bzero(&pusch_hopping, sizeof(srslte_pusch_hopping_cfg_t)); pusch_hopping.n_sb = params_db->get_param(params::PUSCH_HOPPING_N_SB); pusch_hopping.hop_mode = params_db->get_param(params::PUSCH_HOPPING_INTRA_SF) ? pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF : @@ -96,30 +117,57 @@ bool ul_buffer::generate_pusch(sched_grant pusch_grant, pusch_hopping.hopping_offset = params_db->get_param(params::PUSCH_HOPPING_OFFSET); pusch_hopping.current_tx_nb = pusch_grant.get_current_tx_nb(); - srslte_ue_ul_set_pusch_cfg(&ue_ul, &dmrs_cfg, &pusch_hopping); + srslte_pucch_cfg_t pucch_cfg; + bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t)); + pucch_cfg.beta_pucch = (float) params_db->get_param(params::PUCCH_BETA)/10; + pucch_cfg.delta_pucch_shift = params_db->get_param(params::PUCCH_DELTA_SHIFT); + pucch_cfg.group_hopping_en = dmrs_cfg.group_hopping_en; + pucch_cfg.N_cs = params_db->get_param(params::PUCCH_CYCLIC_SHIFT); + pucch_cfg.n_rb_2 = params_db->get_param(params::PUCCH_N_RB_2); + + srslte_pucch_sched_t pucch_sched; + bzero(&pucch_sched, sizeof(srslte_pucch_sched_t)); + pucch_sched.n_cce = last_n_cce; + pucch_sched.n_pucch_1[0] = params_db->get_param(params::PUCCH_N_PUCCH_1_0); + pucch_sched.n_pucch_1[1] = params_db->get_param(params::PUCCH_N_PUCCH_1_1); + pucch_sched.n_pucch_1[2] = params_db->get_param(params::PUCCH_N_PUCCH_1_2); + pucch_sched.n_pucch_1[3] = params_db->get_param(params::PUCCH_N_PUCCH_1_3); + pucch_sched.N_pucch_1 = params_db->get_param(params::PUCCH_N_PUCCH_1); + pucch_sched.n_pucch_2 = params_db->get_param(params::PUCCH_N_PUCCH_2); + pucch_sched.n_pucch_sr = params_db->get_param(params::PUCCH_N_PUCCH_SR); + + srslte_ue_ul_set_cfg(&ue_ul, &dmrs_cfg, &pusch_hopping, &pucch_cfg, &pucch_sched); - int n = srslte_ue_ul_pusch_uci_encode_rnti(&ue_ul, (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr(), - payload, uci_data, - tti%10, pusch_grant.get_rnti(), - signal_buffer); + uci_data.I_offset_ack = params_db->get_param(params::UCI_I_OFFSET_ACK); + uci_data.I_offset_cqi = params_db->get_param(params::UCI_I_OFFSET_CQI); + uci_data.I_offset_ri = params_db->get_param(params::UCI_I_OFFSET_RI); + + int n = 0; + // Transmit on PUSCH if UL grant available, otherwise in PUCCH + if (payload) { + n = srslte_ue_ul_pusch_uci_encode_rnti(&ue_ul, (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr(), + payload, uci_data, + tti%10, pusch_grant.get_rnti(), + signal_buffer); + } else { + n = srslte_ue_ul_pucch_encode(&ue_ul, uci_data, tti&10, signal_buffer); + } + // Reset UCI data + bzero(&uci_data, sizeof(srslte_uci_data_t)); + uci_pending = false; + release(); if (n < 0) { - fprintf(stderr, "Error in UL buffer: Error encoding PUSCH\n"); + fprintf(stderr, "Error in UL buffer: Error encoding %s\n", signal_buffer?"PUSCH":"PUCCH"); return false; + } else { + return true; } - release(); - return true; } else { fprintf(stderr, "Error in UL buffer: buffer not released\n"); return false; } } -bool ul_buffer::generate_pucch(srslte_uci_data_t uci_data) -{ - fprintf(stderr, "Not implemented\n"); - return false; -} - bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time) { // send packet through usrp @@ -136,8 +184,6 @@ bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo radio_handler->tx(signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), tx_time); - //srslte_vec_save_file("pusch", signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb)*sizeof(cf_t)); - ready(); } diff --git a/srslte/lib/ue_itf/test/ue_itf_test_prach.cc b/srslte/lib/ue_itf/test/ue_itf_test_prach.cc index 851bb32d3..297a2e189 100644 --- a/srslte/lib/ue_itf/test/ue_itf_test_prach.cc +++ b/srslte/lib/ue_itf/test/ue_itf_test_prach.cc @@ -193,7 +193,7 @@ srslte::ue::phy phy; uint8_t payload[102400]; const uint8_t conn_request_msg[] = {0x20, 0x06, 0x1F, 0x5C, 0x2C, 0x04, 0xB2, 0xAC, 0xF6, 0x00, 0x00, 0x00}; -enum mac_state {RA, RAR, CONNSETUP} state = RA; +enum mac_state {RA, RAR, CONNREQUEST, CONNSETUP} state = RA; uint32_t conreq_tti = 0; uint32_t preamble_idx = 7; @@ -215,7 +215,13 @@ void config_phy() { phy.set_param(srslte::ue::params::PUSCH_RS_SEQUENCE_HOPPING_EN, 0); phy.set_param(srslte::ue::params::PUSCH_RS_CYCLIC_SHIFT, 0); phy.set_param(srslte::ue::params::PUSCH_HOPPING_OFFSET, 0); - + + phy.set_param(srslte::ue::params::PUCCH_BETA, 10); + phy.set_param(srslte::ue::params::PUCCH_DELTA_SHIFT, 1); + phy.set_param(srslte::ue::params::PUCCH_CYCLIC_SHIFT, 0); + phy.set_param(srslte::ue::params::PUCCH_N_PUCCH_1, 0); + phy.set_param(srslte::ue::params::PUCCH_N_RB_2, 2); + } uint32_t interval(uint32_t x1, uint32_t x2) { @@ -245,7 +251,8 @@ void run_tti(uint32_t tti) { fprintf(stderr, "Error sending PRACH\n"); exit(-1); } - } else if (state == RAR) { + } + if (state == RAR) { srslte::ue::sched_grant rar_grant(srslte::ue::sched_grant::DOWNLINK, 2); int ra_tti = phy.get_prach_transmitted_tti(); if (ra_tti > 0) { @@ -258,11 +265,11 @@ void run_tti(uint32_t tti) { if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_RARNTI, &rar_grant)) { // Decode packet - if (dl_buffer->decode_pdsch(rar_grant, payload)) { - INFO("RAR received tti: %d\n", tti); + if (dl_buffer->decode_data(rar_grant, payload)) { rar_unpack(payload, &rar_msg); - - INFO("Received RAR for preamble %d\n", rar_msg.RAPID); + if (!prog_args.continous) { + printf("Received RAR for preamble %d\n", rar_msg.RAPID); + } if (rar_msg.RAPID == preamble_idx) { INFO("Received RAR at TTI: %d\n", tti); @@ -293,7 +300,7 @@ void run_tti(uint32_t tti) { // Save transmission time conreq_tti = ul_buffer->tti; - state = CONNSETUP; + state = CONNREQUEST; } else { fprintf(stderr, "Error getting UL buffer for TTI %d\n", tti); state = RA; @@ -306,9 +313,8 @@ void run_tti(uint32_t tti) { state = RA; } } - } else { - srslte::ue::sched_grant conn_setup_grant(srslte::ue::sched_grant::DOWNLINK, rar_msg.temp_c_rnti); - + } + if (state == CONNREQUEST) { uint32_t interval_conreq = interval(tti, conreq_tti); if (interval_conreq == 4) { @@ -316,7 +322,7 @@ void run_tti(uint32_t tti) { phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant); // Decode PHICH from Connection Request - if (!dl_buffer->decode_phich(connreq_grant)) { + if (!dl_buffer->decode_ack(connreq_grant)) { // Pack Msg3 bits srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs()); @@ -333,40 +339,55 @@ void run_tti(uint32_t tti) { connreq_grant.set_current_tx_nb(nof_rtx_connsetup); connreq_grant.set_rv(rv_value[nof_rtx_connsetup%4]); INFO("Generating PUSCH for TTI: %d\n", ul_buffer->tti); - ul_buffer->generate_pusch(connreq_grant, payload); + ul_buffer->generate_data(connreq_grant, payload); // Save transmission time conreq_tti = ul_buffer->tti; - state = CONNSETUP; } } else { fprintf(stderr, "Error getting UL buffer for TTI %d\n", tti); state = RA; } } else { - // Get DL grant for tmp_rnti - if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_TEMPORAL, &conn_setup_grant)) - { - // Decode packet - if (dl_buffer->decode_pdsch(conn_setup_grant, payload)) { - nof_rx_connsetup++; - state = RA; - nof_rtx_connsetup=0; - if (!prog_args.continous) { - printf("Connection Setup received (%d/%d)\n", nof_rx_connsetup, nof_tx_ra); - } - } else { - INFO("Error decoding PDSCH for Connection Request at TTI=%d\n", tti); - state = RA; - } - } else { - INFO("DCI for Connection Request not found on PDCCH at TTI=%d\n", tti); - state = RA; - } + state = CONNSETUP; } } } - + if (state == CONNSETUP) { + srslte::ue::sched_grant conn_setup_grant(srslte::ue::sched_grant::DOWNLINK, rar_msg.temp_c_rnti); + bool connsetup_recv = false; + // Get DL grant for tmp_rnti + if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_TEMPORAL, &conn_setup_grant)) + { + // Decode packet + if (dl_buffer->decode_data(conn_setup_grant, payload)) { + nof_rx_connsetup++; + state = RA; + nof_rtx_connsetup=0; + if (!prog_args.continous) { + printf("Connection Setup received (%d/%d)\n", nof_rx_connsetup, nof_tx_ra); + } + connsetup_recv = true; + } else { + INFO("Error decoding PDSCH for Connection Request at TTI=%d\n", tti); + } + + // send ACK + INFO("Sending ack %d on TTI: %d\n", connsetup_recv, tti+4); + srslte::ue::ul_buffer *ul_buffer = phy.get_ul_buffer(tti+4); + ul_buffer->generate_ack(connsetup_recv, conn_setup_grant); + if (!prog_args.continous) { + while(ul_buffer->uci_ready()) { + sleep(1); + } + } + state = RA; + + } else { + INFO("DCI for Connection Request not found on PDCCH at TTI=%d\n", tti); + state = RA; + } + } if (srslte_verbose == SRSLTE_VERBOSE_NONE && prog_args.continous) { printf("RECV RAR %2.1f \%% RECV ConnSetup %2.1f \%% (%5u/%5u) \r", (float) 100*nof_rx_rar/nof_tx_ra, @@ -421,6 +442,9 @@ int main(int argc, char *argv[]) printf("Could not start RX\n"); exit(-1); } + for (int i=0;i<100;i++) { + ttisync.wait(); + } /* go to idle and process each tti */ while(1) { uint32_t tti = ttisync.wait(); diff --git a/srslte/lib/ue_itf/test/ue_itf_test_sib1.cc b/srslte/lib/ue_itf/test/ue_itf_test_sib1.cc index 74ac09836..ab041893a 100644 --- a/srslte/lib/ue_itf/test/ue_itf_test_sib1.cc +++ b/srslte/lib/ue_itf/test/ue_itf_test_sib1.cc @@ -108,7 +108,7 @@ void run_tti(uint32_t tti) { grant.set_rv(((uint32_t) ceilf((float)3*((phy.tti_to_SFN(tti)/2)%4)/2))%4); // Decode packet - if (!buffer->decode_pdsch(grant, payload)) { + if (!buffer->decode_data(grant, payload)) { total_errors++; } }