From b5eedf07aff9d2a22ce4eae79655881eb6a359c8 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 9 May 2016 12:38:39 +0200 Subject: [PATCH] Added enb_ul --- srslte/examples/pdsch_ue.c | 2 +- srslte/include/srslte/enb/enb_ul.h | 44 +++-- srslte/include/srslte/phch/prach.h | 23 ++- srslte/include/srslte/phch/pusch.h | 28 +++- srslte/lib/enb/enb_dl.c | 10 -- srslte/lib/enb/enb_ul.c | 222 ++++++++++++++++++++++++++ srslte/lib/phch/prach.c | 35 ++-- srslte/lib/phch/pusch.c | 126 ++++++++++++--- srslte/lib/phch/test/prach_test.c | 20 +-- srslte/lib/phch/test/pusch_test_mex.c | 14 +- 10 files changed, 445 insertions(+), 79 deletions(-) create mode 100644 srslte/lib/enb/enb_ul.c diff --git a/srslte/examples/pdsch_ue.c b/srslte/examples/pdsch_ue.c index 19b47b2ef..2dcd9cb27 100644 --- a/srslte/examples/pdsch_ue.c +++ b/srslte/examples/pdsch_ue.c @@ -495,7 +495,7 @@ int main(int argc, char **argv) { decode_pdsch = true; } else { /* We are looking for SIB1 Blocks, search only in appropiate places */ - if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) { + if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%8)==0)) { decode_pdsch = true; } else { decode_pdsch = false; diff --git a/srslte/include/srslte/enb/enb_ul.h b/srslte/include/srslte/enb/enb_ul.h index caf89cd4a..3104c9f2d 100644 --- a/srslte/include/srslte/enb/enb_ul.h +++ b/srslte/include/srslte/enb/enb_ul.h @@ -42,7 +42,7 @@ #include "srslte/common/phy_common.h" #include "srslte/dft/ofdm.h" -#include "srslte/ch_estimation/refsignal_ul.h" +#include "srslte/ch_estimation/chest_ul.h" #include "srslte/phch/prach.h" #include "srslte/phch/pusch.h" #include "srslte/phch/pusch_cfg.h" @@ -56,14 +56,17 @@ typedef struct SRSLTE_API { srslte_cell_t cell; - cf_t *sf_symbols[SRSLTE_MAX_PORTS]; + cf_t *sf_symbols; + cf_t *ce; + + srslte_ofdm_t fft; + srslte_chest_ul_t chest; - srslte_ofdm_t fft; srslte_pusch_t pusch; + srslte_pucch_t pucch; srslte_prach_t prach; - srslte_refsignal_ul_t ul_refs; - srslte_pusch_cfg_t pusch_cfg; + srslte_pusch_cfg_t pusch_cfg; srslte_softbuffer_rx_t softbuffer; } srslte_enb_ul_t; @@ -72,31 +75,34 @@ typedef struct { srslte_ra_ul_dci_t grant; uint32_t rnti_idx; uint32_t rv_idx; + uint32_t current_tx_nb; uint8_t *data; } srslte_enb_ul_pusch_t; /* This function shall be called just after the initial synchronization */ SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell, + srslte_prach_cfg_t* prach_cfg, uint32_t nof_rntis); SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q); -SRSLTE_API void srslte_enb_ul_set_cfi(srslte_enb_ul_t *q, - uint32_t cfi); - -SRSLTE_API void srslte_enb_ul_rx_signal(srslte_enb_ul_t *q, - cf_t *signal_buffer); - SRSLTE_API int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q, uint32_t idx, uint16_t rnti); +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_pusch(srslte_enb_ul_t *q, - srslte_ra_ul_dci_t *grant, - uint32_t rnti_idx, - uint32_t rv_idx, - uint8_t *data, + srslte_ra_ul_grant_t *grant, + uint32_t rnti_idx, + uint32_t rv_idx, + uint32_t current_tx_nb, + uint8_t *data, uint32_t sf_idx); SRSLTE_API int srslte_enb_ul_get_pusch_multi(srslte_enb_ul_t *q, @@ -104,8 +110,12 @@ SRSLTE_API int srslte_enb_ul_get_pusch_multi(srslte_enb_ul_t *q, uint32_t nof_pusch, uint32_t sf_idx); -SRSLTE_API int srslte_enb_ul_get_prach(srslte_enb_ul_t *q, - uint32_t sf_idx); +SRSLTE_API int srslte_enb_ul_detect_prach(srslte_enb_ul_t *q, + uint32_t tti, + uint32_t freq_offset, + cf_t *signal, + uint32_t *indices, + uint32_t *offsets); #endif diff --git a/srslte/include/srslte/phch/prach.h b/srslte/include/srslte/phch/prach.h index 86fb32561..d52b9714d 100644 --- a/srslte/include/srslte/phch/prach.h +++ b/srslte/include/srslte/phch/prach.h @@ -41,7 +41,7 @@ #include #include "srslte/config.h" #include "srslte/dft/dft.h" - +#include "srslte/common/phy_common.h" /** Generation and detection of RACH signals for uplink. @@ -52,6 +52,7 @@ typedef struct SRSLTE_API { // Parameters from higher layers (extracted from SIB2) + uint32_t config_idx; uint32_t f; // preamble format uint32_t rsi; // rootSequenceIndex bool hs; // highSpeedFlag @@ -105,24 +106,36 @@ typedef enum SRSLTE_API { SRSLTE_PRACH_SFN_ANY, } srslte_prach_sfn_t; +typedef struct { + uint32_t config_idx; + uint32_t root_seq_idx; + uint32_t zero_corr_zone; + bool hs_flag; +} srslte_prach_cfg_t; + + SRSLTE_API uint32_t srslte_prach_get_preamble_format(uint32_t config_idx); SRSLTE_API srslte_prach_sfn_t srslte_prach_get_sfn(uint32_t config_idx); -SRSLTE_API bool srslte_prach_send_tti(uint32_t config_idx, - uint32_t current_tti, - int allowed_subframe); +SRSLTE_API bool srslte_prach_tti_opportunity(srslte_prach_t *p, + uint32_t current_tti, + int allowed_subframe); SRSLTE_API void srslte_prach_sf_config(uint32_t config_idx, srslte_prach_sf_config_t *sf_config); SRSLTE_API int srslte_prach_init(srslte_prach_t *p, uint32_t N_ifft_ul, - uint32_t preamble_format, + uint32_t config_idx, uint32_t root_seq_index, bool high_speed_flag, uint32_t zero_corr_zone_config); +SRSLTE_API int srslte_prach_init_cfg(srslte_prach_t* p, + srslte_prach_cfg_t* cfg, + uint32_t nof_prb); + SRSLTE_API int srslte_prach_gen(srslte_prach_t *p, uint32_t seq_index, uint32_t freq_offset, diff --git a/srslte/include/srslte/phch/pusch.h b/srslte/include/srslte/phch/pusch.h index 7a59bfaf2..d8a5f3f53 100644 --- a/srslte/include/srslte/phch/pusch.h +++ b/srslte/include/srslte/phch/pusch.h @@ -87,7 +87,12 @@ typedef struct SRSLTE_API { srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; srslte_sequence_t seq_type2_fo; - srslte_sch_t dl_sch; + // This is to generate the scrambling seq for multiple CRNTIs + uint32_t nof_crnti; + srslte_sequence_t *seq_multi[SRSLTE_NSUBFRAMES_X_FRAME]; + uint16_t *rnti_multi; + + srslte_sch_t ul_sch; bool shortened; }srslte_pusch_t; @@ -111,6 +116,17 @@ SRSLTE_API int srslte_pusch_cfg(srslte_pusch_t *q, SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q, uint16_t rnti); +SRSLTE_API int srslte_pusch_init_rnti_multi(srslte_pusch_t *q, + uint32_t nof_rntis); + +SRSLTE_API int srslte_pusch_set_rnti_multi(srslte_pusch_t *q, + uint32_t idx, + uint16_t rnti); + +SRSLTE_API uint16_t srslte_pusch_get_rnti_multi(srslte_pusch_t *q, + uint32_t idx); + + SRSLTE_API int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, @@ -156,6 +172,16 @@ SRSLTE_API int srslte_pusch_uci_decode(srslte_pusch_t *q, uint8_t *data, srslte_uci_data_t *uci_data); +SRSLTE_API int srslte_pusch_uci_decode_rnti_idx(srslte_pusch_t *q, + srslte_pusch_cfg_t *cfg, + srslte_softbuffer_rx_t *softbuffer, + cf_t *sf_symbols, + cf_t *ce, + float noise_estimate, + uint32_t rnti_idx, + uint8_t *data, + srslte_uci_data_t *uci_data); + SRSLTE_API float srslte_pusch_average_noi(srslte_pusch_t *q); SRSLTE_API uint32_t srslte_pusch_last_noi(srslte_pusch_t *q); diff --git a/srslte/lib/enb/enb_dl.c b/srslte/lib/enb/enb_dl.c index d6b0d3012..6c228a19c 100644 --- a/srslte/lib/enb/enb_dl.c +++ b/srslte/lib/enb/enb_dl.c @@ -37,16 +37,6 @@ #define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) #define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp) -#define MAX_CANDIDATES 64 - -/* -static srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // SRSLTE_DCI_FORMAT1B should go here also -const static uint32_t nof_ue_formats = 2; - -static srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FORMAT1C}; -const static uint32_t nof_common_formats = 2; -*/ - int srslte_enb_dl_init(srslte_enb_dl_t *q, srslte_cell_t cell, uint32_t nof_rnti) { int ret = SRSLTE_ERROR_INVALID_INPUTS; diff --git a/srslte/lib/enb/enb_ul.c b/srslte/lib/enb/enb_ul.c new file mode 100644 index 000000000..5b8148835 --- /dev/null +++ b/srslte/lib/enb/enb_ul.c @@ -0,0 +1,222 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "srslte/enb/enb_ul.h" + +#include +#include +#include + + +#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb) +#define CURRENT_SFLEN SRSLTE_SF_LEN(CURRENT_FFTSIZE) + +#define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) +#define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp) + +#define MAX_CANDIDATES 64 + +int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell, + srslte_prach_cfg_t *prach_cfg, uint32_t nof_rnti) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + srslte_cell_isvalid(&cell)) + { + ret = SRSLTE_ERROR; + + bzero(q, sizeof(srslte_enb_ul_t)); + + q->cell = cell; + + if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) { + fprintf(stderr, "Error initiating FFT\n"); + goto clean_exit; + } + srslte_ofdm_set_normalize(&q->fft, true); + srslte_ofdm_set_freq_shift(&q->fft, 0.5); + + if (srslte_pucch_init(&q->pucch, q->cell)) { + fprintf(stderr, "Error creating PUCCH object\n"); + goto clean_exit; + } + + if (srslte_pusch_init(&q->pusch, q->cell)) { + fprintf(stderr, "Error creating PUSCH object\n"); + goto clean_exit; + } + + if (srslte_pusch_init_rnti_multi(&q->pusch, nof_rnti)) { + fprintf(stderr, "Error initiating multiple RNTIs in PUSCH\n"); + goto clean_exit; + } + + if (srslte_prach_init_cfg(&q->prach, prach_cfg, q->cell.nof_prb)) { + fprintf(stderr, "Error initiating PRACH\n"); + goto clean_exit; + } + + if (srslte_softbuffer_rx_init(&q->softbuffer, q->cell.nof_prb)) { + fprintf(stderr, "Error initiating soft buffer\n"); + goto clean_exit; + } + + if (srslte_chest_ul_init(&q->chest, cell)) { + fprintf(stderr, "Error initiating channel estimator\n"); + goto clean_exit; + } + + q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); + if (!q->sf_symbols) { + perror("malloc"); + goto clean_exit; + } + + q->ce = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); + if (!q->ce) { + perror("malloc"); + goto clean_exit; + } + + ret = SRSLTE_SUCCESS; + + } else { + fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", + cell.id, cell.nof_ports, cell.nof_prb); + } + +clean_exit: + if (ret == SRSLTE_ERROR) { + srslte_enb_ul_free(q); + } + return ret; +} + +void srslte_enb_ul_free(srslte_enb_ul_t *q) +{ + if (q) { + srslte_prach_free(&q->prach); + srslte_ofdm_rx_free(&q->fft); + srslte_pucch_free(&q->pucch); + srslte_pusch_free(&q->pusch); + srslte_softbuffer_rx_free(&q->softbuffer); + srslte_chest_ul_free(&q->chest); + if (q->sf_symbols) { + free(q->sf_symbols); + } + if (q->ce) { + free(q->ce); + } + bzero(q, sizeof(srslte_enb_ul_t)); + } +} + +int srslte_enb_ul_add_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_rem_rnti(srslte_enb_ul_t *q, uint32_t idx) +{ + return srslte_pusch_set_rnti_multi(&q->pusch, idx, 0); +} + +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_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, + uint32_t rnti_idx, uint32_t rv_idx, uint32_t current_tx_nb, + uint8_t *data, uint32_t sf_idx) +{ + + if (srslte_pusch_cfg(&q->pusch, &q->pusch_cfg, grant, NULL, NULL, NULL, sf_idx, rv_idx, current_tx_nb)) { + fprintf(stderr, "Error configuring PDSCH\n"); + return SRSLTE_ERROR; + } + + uint32_t cyclic_shift_for_dmrs = 0; + + srslte_chest_ul_estimate(&q->chest, q->sf_symbols, q->ce, grant->L_prb, sf_idx, cyclic_shift_for_dmrs, grant->n_prb); + + float noise_power = srslte_chest_ul_get_noise_estimate(&q->chest); + + srslte_uci_data_t uci_data; + bzero(&uci_data, sizeof(srslte_uci_data_t)); + return srslte_pusch_uci_decode_rnti_idx(&q->pusch, &q->pusch_cfg, + &q->softbuffer, q->sf_symbols, + q->ce, noise_power, + rnti_idx, data, + &uci_data); +} + +int srslte_enb_ul_get_pusch_multi(srslte_enb_ul_t *q, srslte_enb_ul_pusch_t *grants, + uint32_t nof_pusch, uint32_t tti) +{ + uint32_t n_rb_ho = 0; + for (int i=0;icell.nof_prb, n_rb_ho, &phy_grant, tti%8); + if (srslte_enb_ul_get_pusch(q, &phy_grant, grants[i].rnti_idx, grants[i].rv_idx, + grants[i].current_tx_nb, grants[i].data, tti%10) < 0) + { + fprintf(stderr, "Error getting PUSCH\n"); + return SRSLTE_ERROR; + } + } + return SRSLTE_SUCCESS; +} + +int srslte_enb_ul_detect_prach(srslte_enb_ul_t *q, uint32_t tti, + uint32_t freq_offset, cf_t *signal, + uint32_t *indices, uint32_t *offsets) +{ + uint32_t nof_detected_prach = 0; + // consider the number of subframes the transmission must be anticipated + if (srslte_prach_tti_opportunity(&q->prach, tti, -1)) + { + if (srslte_prach_detect_offset(&q->prach, + freq_offset, + &signal[q->prach.N_cp], + SRSLTE_SF_LEN_PRB(q->cell.nof_prb), + indices, + offsets, + &nof_detected_prach)) + { + fprintf(stderr, "Error detecting PRACH\n"); + return SRSLTE_ERROR; + } + } + return (int) nof_detected_prach; +} + + + + + diff --git a/srslte/lib/phch/prach.c b/srslte/lib/phch/prach.c index fdf3a461a..91b1286d4 100644 --- a/srslte/lib/phch/prach.c +++ b/srslte/lib/phch/prach.c @@ -189,7 +189,9 @@ srslte_prach_sfn_t srslte_prach_get_sfn(uint32_t config_idx) { /* Returns true if current_tti is a valid opportunity for PRACH transmission and the is an allowed subframe, * or allowed_subframe == -1 */ -bool srslte_prach_send_tti(uint32_t config_idx, uint32_t current_tti, int allowed_subframe) { +bool srslte_prach_tti_opportunity(srslte_prach_t *p, uint32_t current_tti, int allowed_subframe) +{ + uint32_t config_idx = p->config_idx; // Get SFN and sf_idx from the PRACH configuration index srslte_prach_sfn_t prach_sfn = srslte_prach_get_sfn(config_idx); @@ -319,9 +321,19 @@ int srslte_prach_gen_seqs(srslte_prach_t *p) return 0; } +int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t nof_prb) +{ + return srslte_prach_init(p, + srslte_symbol_sz(nof_prb), + cfg->config_idx, + cfg->root_seq_idx, + cfg->hs_flag, + cfg->zero_corr_zone); +} + int srslte_prach_init(srslte_prach_t *p, uint32_t N_ifft_ul, - uint32_t preamble_format, + uint32_t config_idx, uint32_t root_seq_index, bool high_speed_flag, uint32_t zero_corr_zone_config) @@ -329,11 +341,12 @@ int srslte_prach_init(srslte_prach_t *p, int ret = SRSLTE_ERROR; if(p != NULL && N_ifft_ul < 2049 && - preamble_format < 4 && // Currently supporting formats 0-3 + config_idx < 16 && root_seq_index < MAX_ROOTS && zero_corr_zone_config < 16) { - + uint32_t preamble_format = srslte_prach_get_preamble_format(config_idx); + p->config_idx = config_idx; p->f = preamble_format; p->rsi = root_seq_index; p->hs = high_speed_flag; @@ -353,7 +366,7 @@ int srslte_prach_init(srslte_prach_t *p, p->N_cs = prach_Ncs_unrestricted[p->zczc]; } } - + // Set up containers p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*p->N_zc); p->corr_spec = srslte_vec_malloc(sizeof(cf_t)*p->N_zc); @@ -453,7 +466,9 @@ int srslte_prach_gen(srslte_prach_t *p, uint32_t K = DELTA_F/DELTA_F_RA; uint32_t begin = PHI + (K*k_0) + (K/2); - DEBUG("N_zc: %d, N_cp: %d, N_seq: %d, N_ifft_prach=%d begin: %d\n", p->N_zc, p->N_cp, p->N_seq, p->N_ifft_prach, begin); + DEBUG("N_zc: %d, N_cp: %d, N_seq: %d, N_ifft_prach=%d begin: %d\n", + p->N_zc, p->N_cp, p->N_seq, p->N_ifft_prach, begin); + // Map dft-precoded sequence to ifft bins memset(p->ifft_in, 0, begin*sizeof(cf_t)); memcpy(&p->ifft_in[begin], p->dft_seqs[seq_index], p->N_zc * sizeof(cf_t)); @@ -503,6 +518,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p, sig_len > 0 && indices != NULL) { + if(sig_len < p->N_ifft_prach){ fprintf(stderr, "srslte_prach_detect: Signal is not of length %d", p->N_ifft_prach); return SRSLTE_ERROR_INVALID_INPUTS; @@ -520,7 +536,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p, uint32_t begin = PHI + (K*k_0) + (K/2); memcpy(p->prach_bins, &p->signal_fft[begin], p->N_zc*sizeof(cf_t)); - + for(int i=0;iN_roots;i++){ cf_t *root_spec = p->dft_seqs[p->root_seqs_idx[i]]; @@ -539,8 +555,9 @@ int srslte_prach_detect_offset(srslte_prach_t *p, winsize = p->N_zc; } uint32_t n_wins = p->N_zc/winsize; - + float max_peak = 0; + for(int j=0;jN_zc-(j*p->N_cs))%p->N_zc; uint32_t end = start+winsize; @@ -549,7 +566,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p, } start += p->deadzone; p->peak_values[j] = 0; - for(int k=start;kcorr[k] > p->peak_values[j]) { p->peak_values[j] = p->corr[k]; p->peak_offsets[j] = k-start; diff --git a/srslte/lib/phch/pusch.c b/srslte/lib/phch/pusch.c index 322fe4475..341f7127c 100644 --- a/srslte/lib/phch/pusch.c +++ b/srslte/lib/phch/pusch.c @@ -215,7 +215,7 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) { goto clean; } - srslte_sch_init(&q->dl_sch); + srslte_sch_init(&q->ul_sch); if (srslte_dft_precoding_init(&q->dft_precoding, cell.nof_prb)) { fprintf(stderr, "Error initiating DFT transform precoding\n"); @@ -288,7 +288,7 @@ void srslte_pusch_free(srslte_pusch_t *q) { for (i = 0; i < 4; i++) { srslte_modem_table_free(&q->mod[i]); } - srslte_sch_free(&q->dl_sch); + srslte_sch_free(&q->ul_sch); bzero(q, sizeof(srslte_pusch_t)); @@ -398,6 +398,61 @@ int srslte_pusch_set_rnti(srslte_pusch_t *q, uint16_t rnti) { } +/* Initializes the memory to support pre-calculation of multiple scrambling sequences */ +int srslte_pusch_init_rnti_multi(srslte_pusch_t *q, uint32_t nof_rntis) +{ + for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { + q->seq_multi[i] = malloc(sizeof(srslte_sequence_t)*nof_rntis); + if (!q->seq_multi[i]) { + perror("malloc"); + return SRSLTE_ERROR; + } + } + + q->rnti_multi = srslte_vec_malloc(sizeof(uint16_t)*nof_rntis); + if (!q->rnti_multi) { + perror("malloc"); + return SRSLTE_ERROR; + } + bzero(q->rnti_multi, sizeof(uint16_t)*nof_rntis); + + q->nof_crnti = nof_rntis; + + return SRSLTE_SUCCESS; +} + +int srslte_pusch_set_rnti_multi(srslte_pusch_t *q, uint32_t idx, uint16_t rnti) +{ + if (idx < q->nof_crnti) { + if (q->rnti_multi[idx]) { + for (uint32_t i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { + srslte_sequence_free(&q->seq_multi[i][idx]); + } + q->rnti_multi[idx] = 0; + } + q->rnti_multi[idx] = rnti; + q->rnti_is_set = true; + for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { + if (srslte_sequence_pusch(&q->seq_multi[i][idx], rnti, 2 * i, q->cell.id, + q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { + return SRSLTE_ERROR; + } + } + return SRSLTE_SUCCESS; + } else { + return SRSLTE_ERROR_INVALID_INPUTS; + } +} + +uint16_t srslte_pusch_get_rnti_multi(srslte_pusch_t *q, uint32_t idx) +{ + if (idx < q->nof_crnti) { + return q->rnti_multi[idx]; + } else { + return SRSLTE_ERROR_INVALID_INPUTS; + } +} + int srslte_pusch_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, uint8_t *data, uint16_t rnti, cf_t *sf_symbols) @@ -455,7 +510,7 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs cfg->grant.mcs.tbs, cfg->nbits.nof_re, cfg->nbits.nof_symb, cfg->nbits.nof_bits, cfg->rv); bzero(q->q, cfg->nbits.nof_bits); - if (srslte_ulsch_uci_encode(&q->dl_sch, cfg, softbuffer, data, uci_data, q->g, q->q)) { + if (srslte_ulsch_uci_encode(&q->ul_sch, cfg, softbuffer, data, uci_data, q->g, q->q)) { fprintf(stderr, "Error encoding TB\n"); return SRSLTE_ERROR; } @@ -473,12 +528,12 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs // Correct UCI placeholder/repetition bits uint8_t *d = q->q; - for (int i = 0; i < q->dl_sch.nof_ri_ack_bits; i++) { - if (q->dl_sch.ack_ri_bits[i].type == UCI_BIT_PLACEHOLDER) { - d[q->dl_sch.ack_ri_bits[i].position/8] |= (1<<(7-q->dl_sch.ack_ri_bits[i].position%8)); - } else if (q->dl_sch.ack_ri_bits[i].type == UCI_BIT_REPETITION) { - if (q->dl_sch.ack_ri_bits[i].position > 1) { - uint32_t p=q->dl_sch.ack_ri_bits[i].position; + for (int i = 0; i < q->ul_sch.nof_ri_ack_bits; i++) { + if (q->ul_sch.ack_ri_bits[i].type == UCI_BIT_PLACEHOLDER) { + d[q->ul_sch.ack_ri_bits[i].position/8] |= (1<<(7-q->ul_sch.ack_ri_bits[i].position%8)); + } else if (q->ul_sch.ack_ri_bits[i].type == UCI_BIT_REPETITION) { + if (q->ul_sch.ack_ri_bits[i].position > 1) { + uint32_t p=q->ul_sch.ack_ri_bits[i].position; uint8_t bit = d[(p-1)/8] & (1<<(7-(p-1)%8)); if (bit) { d[p/8] |= 1<<(7-p%8); @@ -514,14 +569,12 @@ int srslte_pusch_decode(srslte_pusch_t *q, return srslte_pusch_uci_decode(q, cfg, softbuffer, sf_symbols, ce, noise_estimate, data, &uci_data); } - -/** Decodes the PUSCH from the received symbols - */ -int srslte_pusch_uci_decode(srslte_pusch_t *q, - srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, - cf_t *sf_symbols, - cf_t *ce, float noise_estimate, - uint8_t *data, srslte_uci_data_t *uci_data) +int srslte_pusch_uci_decode_seq(srslte_pusch_t *q, + srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, + srslte_sequence_t *seq, + cf_t *sf_symbols, + cf_t *ce, float noise_estimate, + uint8_t *data, srslte_uci_data_t *uci_data) { uint32_t n; @@ -561,15 +614,15 @@ int srslte_pusch_uci_decode(srslte_pusch_t *q, srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re); // Decode RI/HARQ bits before descrambling - if (srslte_ulsch_uci_decode_ri_ack(&q->dl_sch, cfg, softbuffer, q->q, q->seq[cfg->sf_idx].c, uci_data)) { + if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, q->seq[cfg->sf_idx].c, uci_data)) { fprintf(stderr, "Error decoding RI/HARQ bits\n"); return SRSLTE_ERROR; } // Descrambling - srslte_scrambling_s_offset(&q->seq[cfg->sf_idx], q->q, 0, cfg->nbits.nof_bits); + srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits); - return srslte_ulsch_uci_decode(&q->dl_sch, cfg, softbuffer, q->q, q->g, data, uci_data); + return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data); } else { fprintf(stderr, "Must call srslte_pusch_set_rnti() before calling srslte_pusch_decode()\n"); return SRSLTE_ERROR; @@ -578,4 +631,37 @@ int srslte_pusch_uci_decode(srslte_pusch_t *q, return SRSLTE_ERROR_INVALID_INPUTS; } } + +/** Decodes the PUSCH from the received symbols + */ +int srslte_pusch_uci_decode(srslte_pusch_t *q, + srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, + cf_t *sf_symbols, + cf_t *ce, float noise_estimate, + uint8_t *data, srslte_uci_data_t *uci_data) +{ + return srslte_pusch_uci_decode_seq(q, cfg, softbuffer, &q->seq[cfg->sf_idx], sf_symbols, ce, noise_estimate, data, uci_data); +} + +/** Decodes the PUSCH from the received symbols for a given RNTI index + */ +int srslte_pusch_uci_decode_rnti_idx(srslte_pusch_t *q, + srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, + cf_t *sf_symbols, + cf_t *ce, float noise_estimate, + uint32_t rnti_idx, + uint8_t *data, srslte_uci_data_t *uci_data) +{ + if (rnti_idx < q->nof_crnti) { + if (q->rnti_multi[rnti_idx]) { + return srslte_pusch_uci_decode_seq(q, cfg, softbuffer, &q->seq_multi[cfg->sf_idx][rnti_idx], sf_symbols, ce, noise_estimate, data, uci_data); + } else { + fprintf(stderr, "Error RNTI idx %d not set\n", rnti_idx); + return SRSLTE_ERROR; + } + } else { + return SRSLTE_ERROR_INVALID_INPUTS; + } +} + diff --git a/srslte/lib/phch/test/prach_test.c b/srslte/lib/phch/test/prach_test.c index ee7c914fc..088f815c0 100644 --- a/srslte/lib/phch/test/prach_test.c +++ b/srslte/lib/phch/test/prach_test.c @@ -40,13 +40,13 @@ uint32_t N_ifft_ul = 1536; -uint32_t preamble_format = 0; +uint32_t config_idx = 3; uint32_t root_seq_idx = 0; -uint32_t zero_corr_zone = 1; +uint32_t zero_corr_zone = 15; void usage(char *prog) { printf("Usage: %s\n", prog); - printf("\t-N Uplink IFFT size [Default 128]\n"); + printf("\t-N Uplink IFFT size [Default %d]\n", N_ifft_ul); printf("\t-f Preamble format [Default 0]\n"); printf("\t-r Root sequence index [Default 0]\n"); printf("\t-z Zero correlation zone config [Default 1]\n"); @@ -60,7 +60,7 @@ void parse_args(int argc, char **argv) { N_ifft_ul = atoi(argv[optind]); break; case 'f': - preamble_format = atoi(argv[optind]); + config_idx = atoi(argv[optind]); break; case 'r': root_seq_idx = atoi(argv[optind]); @@ -87,7 +87,7 @@ int main(int argc, char **argv) { srslte_prach_init(p, N_ifft_ul, - preamble_format, + config_idx, root_seq_idx, high_speed_flag, zero_corr_zone); @@ -108,11 +108,13 @@ int main(int argc, char **argv) { preamble); uint32_t prach_len = p->N_seq; - if(preamble_format == 2 || preamble_format == 3) - prach_len /= 2; - - srslte_prach_detect(p, 0, &preamble[p->N_cp], prach_len, indices, &n_indices); + struct timeval t[3]; + gettimeofday(&t[1], NULL); + srslte_prach_detect(p, frequency_offset, &preamble[p->N_cp], prach_len, indices, &n_indices); + gettimeofday(&t[2], NULL); + get_time_interval(t); + printf("texec=%d us\n", t[0].tv_usec); if(n_indices != 1 || indices[0] != seq_index) return -1; } diff --git a/srslte/lib/phch/test/pusch_test_mex.c b/srslte/lib/phch/test/pusch_test_mex.c index 92589e5e5..6178a1f3a 100644 --- a/srslte/lib/phch/test/pusch_test_mex.c +++ b/srslte/lib/phch/test/pusch_test_mex.c @@ -50,7 +50,7 @@ int rv_seq[4] = {0, 2, 3, 1}; /* the gateway function */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - srslte_ofdm_t ofdm_tx; + srslte_ofdm_t ofdm_rx; srslte_pusch_t pusch; srslte_chest_ul_t chest; cf_t *input_fft; @@ -88,12 +88,12 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) return; } - if (srslte_ofdm_rx_init(&ofdm_tx, cell.cp, cell.nof_prb)) { + if (srslte_ofdm_rx_init(&ofdm_rx, cell.cp, cell.nof_prb)) { fprintf(stderr, "Error initializing FFT\n"); return; } - srslte_ofdm_set_normalize(&ofdm_tx, true); - srslte_ofdm_set_freq_shift(&ofdm_tx, 0.5); + srslte_ofdm_set_normalize(&ofdm_rx, true); + srslte_ofdm_set_freq_shift(&ofdm_rx, 0.5); if (srslte_pusch_init(&pusch, cell)) { mexErrMsgTxt("Error initiating PDSCH\n"); @@ -218,7 +218,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) if (!data_bytes) { return; } - srslte_sch_set_max_noi(&pusch.dl_sch, max_iterations); + srslte_sch_set_max_noi(&pusch.ul_sch, max_iterations); input_fft = NULL; int r=-1; @@ -244,7 +244,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) mexPrintf("Input is after fft\n"); } else { input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); - srslte_ofdm_rx_sf(&ofdm_tx, input_signal, input_fft); + srslte_ofdm_rx_sf(&ofdm_rx, input_signal, input_fft); mexPrintf("Input is before fft\n"); free(input_signal); } @@ -294,7 +294,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) srslte_softbuffer_rx_free(&softbuffer); srslte_chest_ul_free(&chest); srslte_pusch_free(&pusch); - srslte_ofdm_rx_free(&ofdm_tx); + srslte_ofdm_rx_free(&ofdm_rx); free(ce); free(data_bytes);