diff --git a/srslte/examples/pdsch_enodeb.c b/srslte/examples/pdsch_enodeb.c index 011164bd8..456b2af95 100644 --- a/srslte/examples/pdsch_enodeb.c +++ b/srslte/examples/pdsch_enodeb.c @@ -603,8 +603,8 @@ int main(int argc, char **argv) { if (send_data) { /* Encode PDCCH */ - srslte_dci_msg_pack_pdsch(&ra_dl, &dci_msg, SRSLTE_DCI_FORMAT1, cell.nof_prb, false); INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L); + srslte_dci_msg_pack_pdsch(&ra_dl, &dci_msg, SRSLTE_DCI_FORMAT1, cell.nof_prb, false); if (srslte_pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], UE_CRNTI, sf_symbols, sf_idx, cfi)) { fprintf(stderr, "Error encoding DCI message\n"); exit(-1); diff --git a/srslte/include/srslte/enb/enb_dl.h b/srslte/include/srslte/enb/enb_dl.h new file mode 100644 index 000000000..f82032907 --- /dev/null +++ b/srslte/include/srslte/enb/enb_dl.h @@ -0,0 +1,175 @@ +/** + * + * \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/. + * + */ + +/****************************************************************************** + * File: enb_dl.h + * + * Description: ENB downlink object. + * + * This module is a frontend to all the downlink data and control + * channel processing modules for the ENB transmitter side. + * + * Reference: + *****************************************************************************/ + +#ifndef ENBDL_H +#define ENBDL_H + +#include + +#include "srslte/common/phy_common.h" +#include "srslte/dft/ofdm.h" +#include "srslte/sync/pss.h" +#include "srslte/sync/sss.h" +#include "srslte/ch_estimation/refsignal_dl.h" +#include "srslte/phch/dci.h" +#include "srslte/phch/pbch.h" +#include "srslte/phch/pcfich.h" +#include "srslte/phch/pdcch.h" +#include "srslte/phch/pdsch.h" +#include "srslte/phch/pdsch_cfg.h" +#include "srslte/phch/phich.h" +#include "srslte/phch/ra.h" +#include "srslte/phch/regs.h" + +#include "srslte/utils/vector.h" +#include "srslte/utils/debug.h" + +#include "srslte/config.h" + +typedef struct SRSLTE_API { + srslte_cell_t cell; + + cf_t *sf_symbols[SRSLTE_MAX_PORTS]; + cf_t *slot1_symbols[SRSLTE_MAX_PORTS]; + + srslte_ofdm_t ifft; + srslte_pbch_t pbch; + srslte_pcfich_t pcfich; + srslte_regs_t regs; + srslte_pdcch_t pdcch; + srslte_pdsch_t pdsch; + srslte_phich_t phich; + + srslte_refsignal_cs_t csr_signal; + srslte_pdsch_cfg_t pdsch_cfg; + srslte_softbuffer_tx_t softbuffer; + srslte_ra_dl_dci_t dl_dci; + + srslte_dci_format_t dci_format; + uint32_t cfi; + + cf_t pss_signal[SRSLTE_PSS_LEN]; + float sss_signal0[SRSLTE_SSS_LEN]; + float sss_signal5[SRSLTE_SSS_LEN]; + uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; + +} srslte_enb_dl_t; + +typedef struct { + srslte_ra_dl_dci_t grant; + srslte_dci_format_t format; + srslte_dci_location_t location; + uint32_t rnti_idx; + uint32_t rv_idx; + uint8_t *data; +} srslte_enb_dl_pdsch_t; + + +typedef struct { + srslte_ra_ul_dci_t grant; + srslte_dci_location_t location; + uint32_t rnti_idx; + uint32_t rv_idx; +} srslte_enb_dl_pusch_grant_t; + + +/* This function shall be called just after the initial synchronization */ +SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q, + srslte_cell_t cell, + uint32_t nof_rntis); + +SRSLTE_API void srslte_enb_dl_free(srslte_enb_dl_t *q); + +SRSLTE_API void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q, + uint32_t cfi); + +SRSLTE_API void srslte_enb_dl_clear_sf(srslte_enb_dl_t *q); + +SRSLTE_API void srslte_enb_dl_put_sync(srslte_enb_dl_t *q, + uint32_t sf_idx); + +SRSLTE_API void srslte_enb_dl_put_refs(srslte_enb_dl_t *q, + uint32_t sf_idx); + +SRSLTE_API void srslte_enb_dl_put_mib(srslte_enb_dl_t *q, + uint32_t tti); + +SRSLTE_API void srslte_enb_dl_put_pcfich(srslte_enb_dl_t *q, + uint32_t sf_idx); + +SRSLTE_API void srslte_enb_dl_put_base(srslte_enb_dl_t *q, + uint32_t tti); + +SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, + cf_t *signal_buffer); + +SRSLTE_API int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, + uint32_t idx, + uint16_t rnti); + +SRSLTE_API int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, + srslte_ra_dl_grant_t *grant, + uint32_t rnti_idx, + uint32_t rv_idx, + uint32_t sf_idx, + uint8_t *data); + +SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q, + srslte_ra_dl_dci_t *grant, + srslte_dci_format_t format, + srslte_dci_location_t location, + uint32_t rnti_idx, + uint32_t sf_idx); + +SRSLTE_API int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, + srslte_ra_ul_dci_t *grant, + srslte_dci_location_t location, + uint32_t rnti_idx, + uint32_t sf_idx); + +SRSLTE_API int srslte_enb_dl_put_pdsch_multi(srslte_enb_dl_t *q, + srslte_enb_dl_pdsch_t *pdsch, + uint32_t nof_pdsch, + uint32_t sf_idx); + +SRSLTE_API int srslte_enb_dl_put_pusch_multi(srslte_enb_dl_t *q, + srslte_enb_dl_pusch_grant_t *pusch, + uint32_t nof_pusch, + uint32_t sf_idx); + + +#endif diff --git a/srslte/include/srslte/enb/enb_ul.h b/srslte/include/srslte/enb/enb_ul.h new file mode 100644 index 000000000..caf89cd4a --- /dev/null +++ b/srslte/include/srslte/enb/enb_ul.h @@ -0,0 +1,111 @@ +/** + * + * \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/. + * + */ + +/****************************************************************************** + * File: enb_ul.h + * + * Description: ENB uplink object. + * + * This module is a frontend to all the uplink data and control + * channel processing modules for the ENB receiver side. + * + * Reference: + *****************************************************************************/ + +#ifndef ENBUL_H +#define ENBUL_H + +#include + +#include "srslte/common/phy_common.h" +#include "srslte/dft/ofdm.h" +#include "srslte/ch_estimation/refsignal_ul.h" +#include "srslte/phch/prach.h" +#include "srslte/phch/pusch.h" +#include "srslte/phch/pusch_cfg.h" +#include "srslte/phch/ra.h" + +#include "srslte/utils/vector.h" +#include "srslte/utils/debug.h" + +#include "srslte/config.h" + +typedef struct SRSLTE_API { + srslte_cell_t cell; + + cf_t *sf_symbols[SRSLTE_MAX_PORTS]; + + srslte_ofdm_t fft; + srslte_pusch_t pusch; + srslte_prach_t prach; + + srslte_refsignal_ul_t ul_refs; + srslte_pusch_cfg_t pusch_cfg; + srslte_softbuffer_rx_t softbuffer; + +} srslte_enb_ul_t; + +typedef struct { + srslte_ra_ul_dci_t grant; + uint32_t rnti_idx; + uint32_t rv_idx; + 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, + 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_get_pusch(srslte_enb_ul_t *q, + srslte_ra_ul_dci_t *grant, + uint32_t rnti_idx, + uint32_t rv_idx, + uint8_t *data, + uint32_t sf_idx); + +SRSLTE_API int srslte_enb_ul_get_pusch_multi(srslte_enb_ul_t *q, + srslte_enb_ul_pusch_t *grants, + 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); + + +#endif diff --git a/srslte/include/srslte/phch/pdsch.h b/srslte/include/srslte/phch/pdsch.h index cce235558..b65260eac 100644 --- a/srslte/include/srslte/phch/pdsch.h +++ b/srslte/include/srslte/phch/pdsch.h @@ -68,6 +68,11 @@ typedef struct SRSLTE_API { srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; + // 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 dl_sch; } srslte_pdsch_t; @@ -80,6 +85,16 @@ SRSLTE_API void srslte_pdsch_free(srslte_pdsch_t *q); SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti); +SRSLTE_API int srslte_pdsch_init_rnti_multi(srslte_pdsch_t *q, + uint32_t nof_rntis); + +SRSLTE_API int srslte_pdsch_set_rnti_multi(srslte_pdsch_t *q, + uint32_t idx, + uint16_t rnti); + +SRSLTE_API uint16_t srslte_pdsch_get_rnti_multi(srslte_pdsch_t *q, + uint32_t idx); + SRSLTE_API int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, @@ -93,6 +108,13 @@ SRSLTE_API int srslte_pdsch_encode(srslte_pdsch_t *q, uint8_t *data, cf_t *sf_symbols[SRSLTE_MAX_PORTS]); +SRSLTE_API int srslte_pdsch_encode_rnti_idx(srslte_pdsch_t *q, + srslte_pdsch_cfg_t *cfg, + srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, + uint32_t rnti_idx, + cf_t *sf_symbols[SRSLTE_MAX_PORTS]); + SRSLTE_API int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, diff --git a/srslte/include/srslte/phch/ra.h b/srslte/include/srslte/phch/ra.h index a65cf8442..cbc4d5701 100644 --- a/srslte/include/srslte/phch/ra.h +++ b/srslte/include/srslte/phch/ra.h @@ -178,6 +178,7 @@ typedef union { srslte_ra_dl_grant_t dl; } srslte_phy_grant_t; + #define SRSLTE_PHY_GRANT_LEN sizeof(srslte_phy_grant_t) diff --git a/srslte/include/srslte/srslte.h b/srslte/include/srslte/srslte.h index df26e9c20..719b5d945 100644 --- a/srslte/include/srslte/srslte.h +++ b/srslte/include/srslte/srslte.h @@ -109,6 +109,9 @@ #include "srslte/ue/ue_dl.h" #include "srslte/ue/ue_ul.h" +#include "srslte/enb/enb_dl.h" +#include "srslte/enb/enb_ul.h" + #include "srslte/scrambling/scrambling.h" #include "srslte/sync/pss.h" diff --git a/srslte/lib/CMakeLists.txt b/srslte/lib/CMakeLists.txt index 4e0990563..7ca618ea5 100644 --- a/srslte/lib/CMakeLists.txt +++ b/srslte/lib/CMakeLists.txt @@ -34,6 +34,7 @@ add_subdirectory(modem) add_subdirectory(resampling) add_subdirectory(scrambling) add_subdirectory(ue) +add_subdirectory(enb) add_library(srslte SHARED version.c $ @@ -51,6 +52,7 @@ add_library(srslte SHARED version.c $ $ $ + $ $ ) @@ -72,6 +74,7 @@ if(NOT DisableMEX) $ $ $ + $ $ ) endif(NOT DisableMEX) diff --git a/srslte/lib/enb/CMakeLists.txt b/srslte/lib/enb/CMakeLists.txt new file mode 100644 index 000000000..abd38a7d0 --- /dev/null +++ b/srslte/lib/enb/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright 2013-2015 Software Radio Systems Limited +# +# 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/. +# + +file(GLOB SOURCES "*.c") +add_library(srslte_enb OBJECT ${SOURCES}) +SRSLTE_SET_PIC(srslte_enb) diff --git a/srslte/lib/enb/enb_dl.c b/srslte/lib/enb/enb_dl.c new file mode 100644 index 000000000..6706592ec --- /dev/null +++ b/srslte/lib/enb/enb_dl.c @@ -0,0 +1,317 @@ +/** + * + * \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_dl.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 + +/* +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; + + if (q != NULL && + srslte_cell_isvalid(&cell)) + { + ret = SRSLTE_ERROR; + + bzero(q, sizeof(srslte_enb_dl_t)); + + q->cell = cell; + q->cfi = 3; + + if (srslte_ofdm_tx_init(&q->ifft, q->cell.cp, q->cell.nof_prb)) { + fprintf(stderr, "Error initiating FFT\n"); + goto clean_exit; + } + + srslte_ofdm_set_normalize(&q->ifft, true); + + if (srslte_regs_init(&q->regs, q->cell)) { + fprintf(stderr, "Error initiating REGs\n"); + goto clean_exit; + } + if (srslte_pbch_init(&q->pbch, q->cell)) { + fprintf(stderr, "Error creating PBCH object\n"); + goto clean_exit; + } + if (srslte_pcfich_init(&q->pcfich, &q->regs, q->cell)) { + fprintf(stderr, "Error creating PCFICH object\n"); + goto clean_exit; + } + if (srslte_phich_init(&q->phich, &q->regs, q->cell)) { + fprintf(stderr, "Error creating PHICH object\n"); + goto clean_exit; + } + + if (srslte_pdcch_init(&q->pdcch, &q->regs, q->cell)) { + fprintf(stderr, "Error creating PDCCH object\n"); + goto clean_exit; + } + + if (srslte_pdsch_init(&q->pdsch, q->cell)) { + fprintf(stderr, "Error creating PDSCH object\n"); + goto clean_exit; + } + + if (srslte_pdsch_init_rnti_multi(&q->pdsch, nof_rnti)) { + fprintf(stderr, "Error initiating multiple RNTIs in PDSCH\n"); + goto clean_exit; + } + + if (srslte_softbuffer_tx_init(&q->softbuffer, q->cell.nof_prb)) { + fprintf(stderr, "Error initiating soft buffer\n"); + goto clean_exit; + } + + if (srslte_refsignal_cs_init(&q->csr_signal, q->cell)) { + fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); + goto clean_exit; + } + + for (int i=0;icell.nof_ports;i++) { + q->sf_symbols[i] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); + if (!q->sf_symbols[i]) { + perror("malloc"); + goto clean_exit; + } + q->slot1_symbols[i] = &q->sf_symbols[i][CURRENT_SLOTLEN_RE]; + } + + /* Generate PSS/SSS signals */ + srslte_pss_generate(q->pss_signal, cell.id%3); + srslte_sss_generate(q->sss_signal0, q->sss_signal5, cell.id); + + 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_dl_free(q); + } + return ret; +} + +void srslte_enb_dl_free(srslte_enb_dl_t *q) +{ + if (q) { + srslte_ofdm_tx_free(&q->ifft); + srslte_regs_free(&q->regs); + srslte_pcfich_free(&q->pcfich); + srslte_phich_free(&q->phich); + srslte_pdcch_free(&q->pdcch); + srslte_pdsch_free(&q->pdsch); + + srslte_refsignal_cs_free(&q->csr_signal); + srslte_softbuffer_tx_free(&q->softbuffer); + + for (int i=0;isf_symbols[i]) { + free(q->sf_symbols[i]); + } + } + bzero(q, sizeof(srslte_enb_dl_t)); + } +} + +void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q, uint32_t cfi) +{ + q->cfi = cfi; +} + +void srslte_enb_dl_clear_sf(srslte_enb_dl_t *q) +{ + for (int i=0;icell.nof_ports;i++) { + bzero(q->sf_symbols[i], CURRENT_SFLEN_RE * sizeof(cf_t)); + } +} + +void srslte_enb_dl_put_sync(srslte_enb_dl_t *q, uint32_t sf_idx) +{ + if (sf_idx == 0 || sf_idx == 5) { + srslte_pss_put_slot(q->pss_signal, q->sf_symbols[0], q->cell.nof_prb, q->cell.cp); + srslte_sss_put_slot(sf_idx ? q->sss_signal5 : q->sss_signal0, q->sf_symbols[0], + q->cell.nof_prb, SRSLTE_CP_NORM); + } +} + +void srslte_enb_dl_put_refs(srslte_enb_dl_t *q, uint32_t sf_idx) +{ + srslte_refsignal_cs_put_sf(q->cell, 0, q->csr_signal.pilots[0][sf_idx], q->sf_symbols[0]); +} + +void srslte_enb_dl_put_mib(srslte_enb_dl_t *q, uint32_t tti) +{ + if ((tti%10) == 0) { + srslte_pbch_mib_pack(&q->cell, tti/10, q->bch_payload); + srslte_pbch_encode(&q->pbch, q->bch_payload, q->slot1_symbols); + } +} + +void srslte_enb_dl_put_pcfich(srslte_enb_dl_t *q, uint32_t sf_idx) +{ + srslte_pcfich_encode(&q->pcfich, q->cfi, q->sf_symbols, sf_idx); + +} + +void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti) +{ + uint32_t sf_idx = tti%10; + + srslte_enb_dl_put_sync(q, sf_idx); + srslte_enb_dl_put_refs(q, sf_idx); + srslte_enb_dl_put_mib(q, tti); + srslte_enb_dl_put_pcfich(q, sf_idx); + +} + +void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, cf_t *signal_buffer) +{ + srslte_ofdm_tx_sf(&q->ifft, q->sf_symbols[0], signal_buffer); + + // TODO: PAPR control + srslte_vec_sc_prod_cfc(signal_buffer, 0.5, signal_buffer, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); +} + +int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint32_t idx, uint16_t rnti) +{ + return srslte_pdsch_set_rnti_multi(&q->pdsch, idx, rnti); +} + +int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q, srslte_ra_dl_dci_t *grant, + srslte_dci_format_t format, srslte_dci_location_t location, + uint32_t rnti_idx, uint32_t sf_idx) +{ + srslte_dci_msg_t dci_msg; + + uint16_t rnti = srslte_pdsch_get_rnti_multi(&q->pdsch, rnti_idx); + + bool rnti_is_user = true; + if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || rnti == SRSLTE_MRNTI) { + rnti_is_user = false; + } + + srslte_dci_msg_pack_pdsch(grant, &dci_msg, format, q->cell.nof_prb, rnti_is_user); + if (srslte_pdcch_encode(&q->pdcch, &dci_msg, location, rnti, q->sf_symbols, sf_idx, q->cfi)) { + fprintf(stderr, "Error encoding DCI message\n"); + return SRSLTE_ERROR; + } + + return SRSLTE_SUCCESS; +} + +int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant, + srslte_dci_location_t location, + uint32_t rnti_idx, uint32_t sf_idx) +{ + srslte_dci_msg_t dci_msg; + + uint16_t rnti = srslte_pdsch_get_rnti_multi(&q->pdsch, rnti_idx); + + srslte_dci_msg_pack_pusch(grant, &dci_msg, q->cell.nof_prb); + if (srslte_pdcch_encode(&q->pdcch, &dci_msg, location, rnti, q->sf_symbols, sf_idx, q->cfi)) { + fprintf(stderr, "Error encoding DCI message\n"); + return SRSLTE_ERROR; + } + + return SRSLTE_SUCCESS; +} + +int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, + uint32_t rnti_idx, uint32_t rv_idx, uint32_t sf_idx, + uint8_t *data) +{ + /* Configure pdsch_cfg parameters */ + if (srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx)) { + fprintf(stderr, "Error configuring PDSCH\n"); + return SRSLTE_ERROR; + } + + /* Encode PDSCH */ + if (srslte_pdsch_encode_rnti_idx(&q->pdsch, &q->pdsch_cfg, &q->softbuffer, data, rnti_idx, q->sf_symbols)) { + fprintf(stderr, "Error encoding PDSCH\n"); + return SRSLTE_ERROR; + } + return SRSLTE_SUCCESS; +} + +int srslte_enb_dl_put_pdsch_multi(srslte_enb_dl_t *q, srslte_enb_dl_pdsch_t *grants, uint32_t nof_pdsch, uint32_t sf_idx) +{ + for (int i=0;ipdsch, grants[i].rnti_idx); + + bool rnti_is_user = true; + if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || rnti == SRSLTE_MRNTI) { + rnti_is_user = false; + } + srslte_ra_dl_grant_t phy_grant; + srslte_ra_dl_dci_to_grant(&grants[i].grant, q->cell.nof_prb, rnti_is_user, &phy_grant); + if (srslte_enb_dl_put_pdsch(q, &phy_grant, grants[i].rnti_idx, grants[i].rv_idx, sf_idx, grants[i].data)) { + fprintf(stderr, "Error putting PDCCH %d\n",i); + return SRSLTE_ERROR; + } + } + return SRSLTE_SUCCESS; +} + + +int srslte_enb_dl_put_pusch_multi(srslte_enb_dl_t *q, srslte_enb_dl_pusch_grant_t *grants, uint32_t nof_pusch, uint32_t sf_idx) +{ + for (int i=0;icell = cell; q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp); + q->nof_crnti = 0; INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports, q->cell.nof_prb, q->max_re); @@ -286,6 +287,19 @@ void srslte_pdsch_free(srslte_pdsch_t *q) { for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { srslte_sequence_free(&q->seq[i]); } + + for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { + for (int n=0;nnof_crnti;n++) { + srslte_sequence_free(&q->seq_multi[i][n]); + } + if (q->seq_multi[i]) { + free(q->seq_multi[i]); + } + } + + if (q->rnti_multi) { + free(q->rnti_multi); + } for (i = 0; i < 4; i++) { srslte_modem_table_free(&q->mod[i]); @@ -334,6 +348,54 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) { return SRSLTE_SUCCESS; } +/* Initializes the memory to support pre-calculation of multiple scrambling sequences */ +int srslte_pdsch_init_rnti_multi(srslte_pdsch_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; + } + + q->nof_crnti = nof_rntis; + + return SRSLTE_SUCCESS; +} + +int srslte_pdsch_set_rnti_multi(srslte_pdsch_t *q, uint32_t idx, uint16_t rnti) +{ + if (idx < q->nof_crnti) { + q->rnti_multi[idx] = rnti; + q->rnti_is_set = true; + for (uint32_t i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { + if (srslte_sequence_pdsch(&q->seq[i], rnti, 0, 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_pdsch_get_rnti_multi(srslte_pdsch_t *q, uint32_t idx) +{ + if (idx < q->nof_crnti) { + return q->rnti_multi[idx]; + } else { + return SRSLTE_ERROR_INVALID_INPUTS; + } +} + int srslte_pdsch_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate, @@ -472,12 +534,11 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, } } -/** Converts the PDSCH data bits to symbols mapped to the slot ready for transmission - */ -int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, +int srslte_pdsch_encode_seq(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, uint16_t rnti, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) + uint8_t *data, srslte_sequence_t *seq, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) { + int i; /* Set pointers for layermapping & precoding */ cf_t *x[SRSLTE_MAX_LAYERS]; @@ -520,16 +581,7 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, return SRSLTE_ERROR; } - if (rnti != q->rnti) { - srslte_sequence_t seq; - if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { - return SRSLTE_ERROR; - } - srslte_scrambling_bytes(&seq, (uint8_t*) q->e, cfg->nbits.nof_bits); - srslte_sequence_free(&seq); - } else { - srslte_scrambling_bytes(&q->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits.nof_bits); - } + srslte_scrambling_bytes(seq, (uint8_t*) q->e, cfg->nbits.nof_bits); srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits); @@ -551,6 +603,37 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, return ret; } +int srslte_pdsch_encode_rnti_idx(srslte_pdsch_t *q, + srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, uint32_t rnti_idx, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) +{ + if (rnti_idx < q->nof_crnti) { + return srslte_pdsch_encode_seq(q, cfg, softbuffer, data, &q->seq_multi[cfg->sf_idx][rnti_idx], sf_symbols); + } else { + return SRSLTE_ERROR_INVALID_INPUTS; + } +} + +/** Converts the PDSCH data bits to symbols mapped to the slot ready for transmission + */ +int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, + srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, uint16_t rnti, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) +{ + if (rnti != q->rnti) { + srslte_sequence_t seq; + if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { + return SRSLTE_ERROR; + } + int r = srslte_pdsch_encode_seq(q, cfg, softbuffer, data, &seq, sf_symbols); + srslte_sequence_free(&seq); + return r; + } else { + return srslte_pdsch_encode_seq(q, cfg, softbuffer, data, &q->seq[cfg->sf_idx], sf_symbols); + } +} + + float srslte_pdsch_average_noi(srslte_pdsch_t *q) { return q->dl_sch.average_nof_iterations; diff --git a/srslte/lib/ue/ue_dl.c b/srslte/lib/ue/ue_dl.c index ec8ed2447..cbc28d09a 100644 --- a/srslte/lib/ue/ue_dl.c +++ b/srslte/lib/ue/ue_dl.c @@ -39,10 +39,10 @@ #define MAX_CANDIDATES 64 -srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // SRSLTE_DCI_FORMAT1B should go here also +static srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // SRSLTE_DCI_FORMAT1B should go here also const uint32_t nof_ue_formats = 2; -srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FORMAT1C}; +static srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FORMAT1C}; const uint32_t nof_common_formats = 2;