diff --git a/cuhd/lib/cuhd_imp.cpp b/cuhd/lib/cuhd_imp.cpp index 3ff2000d4..ed82c0aae 100644 --- a/cuhd/lib/cuhd_imp.cpp +++ b/cuhd/lib/cuhd_imp.cpp @@ -35,7 +35,7 @@ #include "cuhd_handler.hpp" #include "srslte/cuhd/cuhd.h" -#define METADATA_VERBOSE +//#define METADATA_VERBOSE //#define HIDE_MESSAGES diff --git a/matlab/tests/dlsch_test.m b/matlab/tests/dlsch_test.m index 1af1e1b1f..43d170297 100644 --- a/matlab/tests/dlsch_test.m +++ b/matlab/tests/dlsch_test.m @@ -1,7 +1,7 @@ enbConfig=struct('NCellID',1,'CyclicPrefix','Normal','CellRefP',1); pdschConfig=struct('Modulation','QPSK','RV',0,'TxScheme','Port0'); -addpath('../../debug/lte/phy/lib/phch/test') +addpath('../../debug/srslte/lib/phch/test') TBs=1:111:15000; e_bits=10000; diff --git a/matlab/tests/pdsch_bler.m b/matlab/tests/pdsch_bler.m index a5b83266b..9ea8490d8 100644 --- a/matlab/tests/pdsch_bler.m +++ b/matlab/tests/pdsch_bler.m @@ -10,7 +10,7 @@ Npackets = 1; SNR_values = linspace(15,20,4); %% Choose RMC -[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.9',[1;0;0;1]); +[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.4',[1;0;0;1]); waveform = sum(waveform,2); if ~isempty(recordedSignal) @@ -51,7 +51,7 @@ cec.InterpType = 'linear'; % 2D interpolation type cec.InterpWindow = 'Centered'; % Interpolation window type cec.InterpWinSize = 1; % Interpolation window size -addpath('../../debug/lte/phy/lib/phch/test') +addpath('../../debug/srslte/lib/phch/test') decoded = zeros(size(SNR_values)); decoded_srslte = zeros(size(SNR_values)); diff --git a/matlab/tests/pusch_test.m b/matlab/tests/pusch_test.m index c743e19e9..5cee60fe0 100644 --- a/matlab/tests/pusch_test.m +++ b/matlab/tests/pusch_test.m @@ -1,20 +1,14 @@ clear -ueConfig=struct('NCellID',1,'NULRB',6,'NSubframe',8,'RNTI',68,'CyclicPrefixUL','Normal','NTxAnts',1); +ueConfig=struct('NCellID',1,'NULRB',6,'NSubframe',1,'RNTI',18,'CyclicPrefixUL','Normal','NTxAnts',1); puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',[1:4]','Modulation','QPSK','RV',0,'Shortened',0); -addpath('../../debug/lte/phy/lib/phch/test') +addpath('../../debug/srslte/lib/phch/test') -% TBs=0:13:211; -% cqilen=[0, 8, 17]; -% mods={'QPSK','16QAM','64QAM'}; -% rvs=0; -% betas=0:3:11; - -TBs=88; -cqilen=0; -mods={'QPSK'}; -rvs=0; -betas=0; + TBs=0:13:211; + cqilen=[0, 8, 17]; + mods={'QPSK','16QAM','64QAM'}; + rvs=0; + betas=[2.0 2.5 6.25]; for i=1:length(TBs) for m=1:length(mods) @@ -28,9 +22,9 @@ for i=1:length(TBs) puschConfig.Modulation = mods{m}; puschConfig.RV = rvs(r); - puschConfig.BetaCQI = 2+betas(bcqi); - puschConfig.BetaRI = 2+betas(bri); - puschConfig.BetaACK = 2+betas(back); + puschConfig.BetaCQI = betas(bcqi); + puschConfig.BetaRI = betas(bri); + puschConfig.BetaACK = betas(back); if (betas(bri)>0) ri_bit=randi(2,1,1)-1; diff --git a/matlab/tests/ulsch_test.m b/matlab/tests/ulsch_test.m index 53c0d8d25..0fc370292 100644 --- a/matlab/tests/ulsch_test.m +++ b/matlab/tests/ulsch_test.m @@ -2,13 +2,13 @@ clear ueConfig=struct('NCellID',1,'CyclicPrefixUL','Normal','NTxAnts',1); puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',0,'Modulation','16QAM','RV',0,'Shortened',0); -addpath('../../debug/lte/phy/lib/phch/test') +addpath('../../debug/srslte/lib/phch/test') TBs=0:13:222; - cqilen=0;%[0, 8, 17]; + cqilen=[0, 8, 17]; mods={'QPSK','16QAM','64QAM'}; - rvs=0;%[0, 3]; - betas=0:3:11; + rvs=[0, 3]; + betas=[2.0 2.5 6.25]; for i=1:length(TBs) @@ -23,9 +23,9 @@ for i=1:length(TBs) puschConfig.Modulation = mods{m}; puschConfig.RV = rvs(r); - puschConfig.BetaCQI = 2+betas(bcqi); - puschConfig.BetaRI = 2+betas(bri); - puschConfig.BetaACK = 2+betas(back); + puschConfig.BetaCQI = betas(bcqi); + puschConfig.BetaRI = betas(bri); + puschConfig.BetaACK = betas(back); if (betas(bri)>0) ri_bit=randi(2,1,1)-1; diff --git a/srslte/CMakeLists.txt b/srslte/CMakeLists.txt index 23a512ef6..0deb408ab 100644 --- a/srslte/CMakeLists.txt +++ b/srslte/CMakeLists.txt @@ -46,4 +46,4 @@ ADD_CUSTOM_TARGET (add_srslte_headers SOURCES ${HEADERS_ALL}) ######################################################################## ADD_SUBDIRECTORY(lib) ADD_SUBDIRECTORY(examples) -add_subdirectory(tutorial_examples) +#add_subdirectory(tutorial_examples) diff --git a/srslte/examples/pdsch_enodeb.c b/srslte/examples/pdsch_enodeb.c index a2196102e..92658284c 100644 --- a/srslte/examples/pdsch_enodeb.c +++ b/srslte/examples/pdsch_enodeb.c @@ -74,9 +74,10 @@ srslte_pbch_t pbch; srslte_pcfich_t pcfich; srslte_pdcch_t pdcch; srslte_pdsch_t pdsch; -srslte_harq_t harq_process; +srslte_pdsch_cfg_t pdsch_cfg; +srslte_softbuffer_tx_t softbuffer; srslte_regs_t regs; -srslte_ra_pdsch_t ra_dl; +srslte_ra_dl_dci_t ra_dl; cf_t *sf_buffer = NULL, *output_buffer = NULL; @@ -253,15 +254,15 @@ void base_init() { srslte_pdsch_set_rnti(&pdsch, 1234); - if (srslte_harq_init(&harq_process, cell)) { - fprintf(stderr, "Error initiating HARQ process\n"); + if (srslte_softbuffer_tx_init(&softbuffer, cell)) { + fprintf(stderr, "Error initiating soft buffer\n"); exit(-1); } } void base_free() { - srslte_harq_free(&harq_process); + srslte_softbuffer_tx_free(&softbuffer); srslte_pdsch_free(&pdsch); srslte_pdcch_free(&pdcch); srslte_regs_free(®s); @@ -315,21 +316,25 @@ uint32_t prbset_to_bitmask() { int update_radl() { - bzero(&ra_dl, sizeof(srslte_ra_pdsch_t)); + bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t)); ra_dl.harq_process = 0; ra_dl.mcs_idx = mcs_idx; ra_dl.ndi = 0; ra_dl.rv_idx = 0; ra_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0; ra_dl.type0_alloc.rbg_bitmask = prbset_to_bitmask(); - - srslte_ra_dl_alloc(&ra_dl.prb_alloc, &ra_dl, cell.nof_prb); - srslte_ra_dl_alloc_re(&ra_dl.prb_alloc, cell.nof_prb, 1, cell.nof_prb<10?(cfi+1):cfi, SRSLTE_CP_NORM); - srslte_ra_mcs_from_idx_dl(mcs_idx, ra_dl.prb_alloc.slot[0].nof_prb, &ra_dl.mcs); srslte_ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb); + srslte_ra_dl_grant_t dummy_grant; + srslte_ra_dl_dci_to_grant(&ra_dl, &dummy_grant, cell, 1, cfi, true); + srslte_ra_dl_grant_fprint(stdout, &dummy_grant); printf("Type new MCS index and press Enter: "); fflush(stdout); + if (dummy_grant.mcs.tbs > dummy_grant.nof_bits) { + fprintf(stderr, "Invalid code rate %d/%d=%.2f\n", dummy_grant.mcs.tbs, dummy_grant.nof_bits, (float) dummy_grant.mcs.tbs / dummy_grant.nof_bits); + return -1; + } + return 0; } @@ -403,7 +408,7 @@ void *net_thread_fnc(void *arg) { do { n = srslte_netsource_read(&net_source, &data_unpacked[rpm], DATA_BUFF_SZ-rpm); if (n > 0) { - int nbytes = 1+(ra_dl.mcs.tbs-1)/8; + int nbytes = 1+(pdsch_cfg.grant.mcs.tbs-1)/8; rpm += n; INFO("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes); wpm = 0; @@ -537,13 +542,6 @@ int main(int argc, char **argv) { fprintf(stderr, "Error updating parameters from control port\n"); } - srslte_harq_reset(&harq_process); - if (srslte_harq_setup_dl(&harq_process, ra_dl.mcs, ra_dl.rv_idx, sf_idx, &ra_dl.prb_alloc)) { - fprintf(stderr, "Error configuring HARQ process\n"); - return -1; - } - - /* Transmit PDCCH + PDSCH only when there is data to send */ if (sf_idx != 0 && sf_idx != 5) { if (net_port > 0) { @@ -552,8 +550,8 @@ int main(int argc, char **argv) { INFO("Transmitting packet\n",0); } } else { - INFO("SF: %d, Generating %d random bits\n", sf_idx, ra_dl.mcs.tbs); - for (i=0;i 0 && net_packet_ready) { if (null_file_sink) { - srslte_bit_unpack_vector(data, data_tmp, ra_dl.mcs.tbs); - if (srslte_netsink_write(&net_sink, data_tmp, 1+(ra_dl.mcs.tbs-1)/8) < 0) { + srslte_bit_unpack_vector(data, data_tmp, pdsch_cfg.grant.mcs.tbs); + if (srslte_netsink_write(&net_sink, data_tmp, 1+(pdsch_cfg.grant.mcs.tbs-1)/8) < 0) { fprintf(stderr, "Error sending data through UDP socket\n"); } } @@ -598,7 +602,7 @@ int main(int argc, char **argv) { } else { #ifndef DISABLE_UHD // FIXME - float norm_factor = (float) cell.nof_prb/15/sqrtf(ra_dl.prb_alloc.slot[0].nof_prb); + float norm_factor = (float) cell.nof_prb/15/sqrtf(pdsch_cfg.grant.nof_prb); srslte_vec_sc_prod_cfc(output_buffer, uhd_amp*norm_factor, output_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb)); cuhd_send(uhd, output_buffer, sf_n_samples, true); #endif diff --git a/srslte/examples/pdsch_ue.c b/srslte/examples/pdsch_ue.c index 1b8a82bec..4205afc89 100644 --- a/srslte/examples/pdsch_ue.c +++ b/srslte/examples/pdsch_ue.c @@ -566,7 +566,7 @@ void *plot_thread_run(void *arg) { while(1) { sem_wait(&plot_sem); - uint32_t nof_symbols = ue_dl.harq_process[0].dl_alloc.re_sf[plot_sf_idx]; + uint32_t nof_symbols = ue_dl.pdsch_cfg.grant.nof_re; for (i = 0; i < nof_re; i++) { tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i])); if (isinf(tmp_plot[i])) { diff --git a/srslte/examples/prach_ue.c b/srslte/examples/prach_ue.c index be70891a3..0114fe6d5 100644 --- a/srslte/examples/prach_ue.c +++ b/srslte/examples/prach_ue.c @@ -295,7 +295,8 @@ int main(int argc, char **argv) { uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; uint32_t sfn_offset; rar_msg_t rar_msg; - srslte_ra_pusch_t ra_pusch; + srslte_ra_ul_dci_t ra_pusch; + srslte_ra_ul_grant_t ra_grant; uint32_t rar_window_start = 0, rar_trials = 0, rar_window_stop = 0; srslte_timestamp_t uhd_time; srslte_timestamp_t next_tx_time; @@ -489,15 +490,16 @@ int main(int argc, char **argv) { rar_unpack(data_rx, &rar_msg); rar_msg_fprint(stdout, &rar_msg); - - srslte_dci_rar_to_ra_ul(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, cell.nof_prb, &ra_pusch); + srslte_dci_rar_grant_t rar_grant; + rar_grant.hopping_flag = rar_msg.hopping_flag; + rar_grant.rba = rar_msg.rba; + rar_grant.trunc_mcs = rar_msg.mcs; + srslte_dci_rar_to_ul_grant(&rar_grant, cell, 0, 0, &ra_pusch, &ra_grant); srslte_ra_pusch_fprint(stdout, &ra_pusch, cell.nof_prb); - srslte_ra_ul_alloc(&ra_pusch.prb_alloc, &ra_pusch, 0, cell.nof_prb); - srslte_ue_sync_get_last_timestamp(&ue_sync, &uhd_time); - srslte_bit_pack_vector((uint8_t*) conn_request_msg, data, ra_pusch.mcs.tbs); + srslte_bit_pack_vector((uint8_t*) conn_request_msg, data, ra_grant.mcs.tbs); uint32_t n_ta = srslte_N_ta_new_rar(rar_msg.timing_adv_cmd); printf("ta: %d, n_ta: %d\n", rar_msg.timing_adv_cmd, n_ta); @@ -515,7 +517,7 @@ int main(int argc, char **argv) { printf("Setting CFO: %f (%f)\n", cfo, cfo*15000); srslte_ue_ul_set_cfo(&ue_ul, cfo); - n = srslte_ue_ul_pusch_encode_rnti(&ue_ul, &ra_pusch, data, ul_sf_idx, rar_msg.temp_c_rnti, ul_signal); + n = srslte_ue_ul_pusch_encode_rnti(&ue_ul, &ra_grant, data, ul_sf_idx, 0, rar_msg.temp_c_rnti, ul_signal); if (n < 0) { fprintf(stderr, "Error encoding PUSCH\n"); exit(-1); diff --git a/srslte/include/srslte/common/phy_common.h b/srslte/include/srslte/common/phy_common.h index 36b24316a..e3f7b765b 100644 --- a/srslte/include/srslte/common/phy_common.h +++ b/srslte/include/srslte/common/phy_common.h @@ -126,8 +126,6 @@ typedef enum {SRSLTE_CP_NORM, SRSLTE_CP_EXT} srslte_cp_t; #define SRSLTE_NOF_LTE_BANDS 29 -#define SRSLTE_NOF_TC_CB_SIZES 188 - typedef enum SRSLTE_API { SRSLTE_PHICH_NORM = 0, SRSLTE_PHICH_EXT @@ -221,18 +219,12 @@ SRSLTE_API uint32_t srslte_N_ta_new_rar(uint32_t ta); SRSLTE_API uint32_t srslte_N_ta_new(uint32_t N_ta_old, uint32_t ta); -SRSLTE_API int srslte_cb_size(uint32_t index); - -SRSLTE_API bool srslte_cb_size_isvalid(uint32_t size); - SRSLTE_API char *srslte_cp_string(srslte_cp_t cp); SRSLTE_API char *srslte_mod_string(srslte_mod_t mod); SRSLTE_API uint32_t srslte_mod_bits_x_symbol(srslte_mod_t mod); -SRSLTE_API int srslte_find_cb_index(uint32_t long_cb); - SRSLTE_API float srslte_band_fd(uint32_t earfcn); SRSLTE_API int srslte_band_get_fd_band(uint32_t band, diff --git a/srslte/include/srslte/fec/cbsegm.h b/srslte/include/srslte/fec/cbsegm.h new file mode 100644 index 000000000..ad0628618 --- /dev/null +++ b/srslte/include/srslte/fec/cbsegm.h @@ -0,0 +1,58 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \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 Lesser 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 Lesser General Public License for more details. + * + * A copy of the GNU Lesser 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 +#include + +#include "srslte/config.h" + +#ifndef CBSEGM_H +#define CBSEGM_H + +#define SRSLTE_NOF_TC_CB_SIZES 188 + + + typedef struct SRSLTE_API { + uint32_t F; + uint32_t C; + uint32_t K1; + uint32_t K2; + uint32_t C1; + uint32_t C2; + uint32_t tbs; +} srslte_cbsegm_t; + +SRSLTE_API int srslte_cbsegm(srslte_cbsegm_t *s, + uint32_t tbs); + +SRSLTE_API int srslte_cbsegm_cbsize(uint32_t index); + +SRSLTE_API bool srslte_cbsegm_cbsize_isvalid(uint32_t size); + +SRSLTE_API int srslte_cbsegm_cbindex(uint32_t long_cb); + +#endif diff --git a/srslte/include/srslte/fec/tc_interl.h b/srslte/include/srslte/fec/tc_interl.h index adca1be8b..4f851bc25 100644 --- a/srslte/include/srslte/fec/tc_interl.h +++ b/srslte/include/srslte/fec/tc_interl.h @@ -37,6 +37,7 @@ #define _TC_INTERL_H #include "srslte/config.h" +#include typedef struct SRSLTE_API { uint32_t *forward; diff --git a/srslte/include/srslte/fec/turbodecoder.h b/srslte/include/srslte/fec/turbodecoder.h index 90fb0b4ff..8fd76e090 100644 --- a/srslte/include/srslte/fec/turbodecoder.h +++ b/srslte/include/srslte/fec/turbodecoder.h @@ -46,8 +46,8 @@ #define SRSLTE_TCOD_RATE 3 #define SRSLTE_TCOD_TOTALTAIL 12 -#define MAX_LONG_CB 6144 -#define MAX_LONG_CODED (SRSLTE_TCOD_RATE*MAX_LONG_CB+SRSLTE_TCOD_TOTALTAIL) +#define SRSLTE_TCOD_MAX_LEN_CB 6144 +#define SRSLTE_TCOD_MAX_LEN_CODED (SRSLTE_TCOD_RATE*SRSLTE_TCOD_MAX_LEN_CB+SRSLTE_TCOD_TOTALTAIL) typedef float srslte_llr_t; diff --git a/srslte/include/srslte/phch/dci.h b/srslte/include/srslte/phch/dci.h index 1196d90ff..fb651e0a1 100644 --- a/srslte/include/srslte/phch/dci.h +++ b/srslte/include/srslte/phch/dci.h @@ -28,7 +28,9 @@ /****************************************************************************** * File: dci.h * - * Description: Downlink control information (DCI) + * Description: Downlink control information (DCI). + * Packing/Unpacking functions to convert between bit streams + * and packed DCI UL/DL grants defined in ra.h * * Reference: 3GPP TS 36.212 version 10.0.0 Release 10 Sec. 5.3.3 *****************************************************************************/ @@ -79,25 +81,36 @@ typedef struct SRSLTE_API { uint32_t nof_bits; } srslte_dci_msg_t; +typedef struct SRSLTE_API { + uint32_t rba; + uint32_t trunc_mcs; + bool hopping_flag; +} srslte_dci_rar_grant_t; + /* Converts a received PDSCH DL scheduling DCI message * to ra structures ready to be passed to the harq setup function */ -SRSLTE_API int srslte_dci_msg_to_ra_dl(srslte_dci_msg_t *msg, - uint16_t msg_rnti, - srslte_cell_t cell, - uint32_t cfi, - srslte_ra_pdsch_t *ra_dl); - -SRSLTE_API int srslte_dci_msg_to_ra_ul(srslte_dci_msg_t *msg, - uint32_t nof_prb, - uint32_t n_rb_ho, - srslte_ra_pusch_t *ra_ul); - -SRSLTE_API int srslte_dci_rar_to_ra_ul(uint32_t rba, - uint32_t trunc_mcs, - bool hopping_flag, - uint32_t nof_prb, - srslte_ra_pusch_t *ra); +SRSLTE_API int srslte_dci_msg_to_dl_grant(srslte_dci_msg_t *msg, + uint16_t msg_rnti, + srslte_cell_t cell, + uint32_t cfi, + uint32_t sf_idx, + srslte_ra_dl_dci_t *dl_dci, + srslte_ra_dl_grant_t *grant); + +SRSLTE_API int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg, + srslte_cell_t cell, + uint32_t N_srs, + uint32_t n_rb_ho, + srslte_ra_ul_dci_t *ul_dci, + srslte_ra_ul_grant_t *grant); + +SRSLTE_API int srslte_dci_rar_to_ul_grant(srslte_dci_rar_grant_t *rar, + srslte_cell_t cell, + uint32_t N_srs, + uint32_t n_rb_ho, + srslte_ra_ul_dci_t *ul_dci, + srslte_ra_ul_grant_t *grant); SRSLTE_API srslte_dci_format_t srslte_dci_format_from_string(char *str); @@ -118,23 +131,23 @@ SRSLTE_API void srslte_dci_msg_type_fprint(FILE *f, srslte_dci_msg_type_t type); // For srslte_dci_msg_type_t = SRSLTE_DCI_MSG_TYPE_PUSCH_SCHED -SRSLTE_API int srslte_dci_msg_pack_pusch(srslte_ra_pusch_t *data, +SRSLTE_API int srslte_dci_msg_pack_pusch(srslte_ra_ul_dci_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb); SRSLTE_API int srslte_dci_msg_unpack_pusch(srslte_dci_msg_t *msg, - srslte_ra_pusch_t *data, + srslte_ra_ul_dci_t *data, uint32_t nof_prb); // For srslte_dci_msg_type_t = SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED -SRSLTE_API int srslte_dci_msg_pack_pdsch(srslte_ra_pdsch_t *data, +SRSLTE_API int srslte_dci_msg_pack_pdsch(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, srslte_dci_format_t format, uint32_t nof_prb, bool crc_is_crnti); SRSLTE_API int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg, - srslte_ra_pdsch_t *data, + srslte_ra_dl_dci_t *data, uint32_t nof_prb, bool crc_is_crnti); diff --git a/srslte/include/srslte/phch/harq.h b/srslte/include/srslte/phch/harq.h deleted file mode 100644 index 5d1c19cbc..000000000 --- a/srslte/include/srslte/phch/harq.h +++ /dev/null @@ -1,98 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2014 The srsLTE Developers. See the - * COPYRIGHT file at the top-level directory of this distribution. - * - * \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 Lesser 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 Lesser General Public License for more details. - * - * A copy of the GNU Lesser 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: harq.h - * - * Description: Hybrid Automatic Repeat Request (HARQ) - * - * Reference: - *****************************************************************************/ - -#ifndef HARQ_ -#define HARQ_ - -#include "srslte/config.h" -#include "srslte/common/phy_common.h" -#include "srslte/phch/ra.h" - - - typedef struct SRSLTE_API { - uint32_t F; - uint32_t C; - uint32_t K1; - uint32_t K2; - uint32_t C1; - uint32_t C2; -} srslte_harq_cbsegm_t; - -typedef struct SRSLTE_API { - srslte_ra_mcs_t mcs; - uint32_t rv; - uint32_t sf_idx; - srslte_ra_dl_alloc_t dl_alloc; - srslte_ra_ul_alloc_t ul_alloc; - srslte_cell_t cell; - - uint32_t nof_re; // Number of RE per subframe - uint32_t nof_bits; // Number of bits per subframe - uint32_t nof_symb; // Number of symbols per subframe - uint32_t nof_prb; // Number of allocated PRB per subframe. - - uint32_t max_cb; - uint32_t w_buff_size; - float **pdsch_w_buff_f; - uint8_t **pdsch_w_buff_c; - - srslte_harq_cbsegm_t cb_segm; - -} srslte_harq_t; - -SRSLTE_API int srslte_harq_init(srslte_harq_t * q, - srslte_cell_t cell); - -SRSLTE_API int srslte_harq_setup_dl(srslte_harq_t *p, - srslte_ra_mcs_t mcs, - uint32_t rv, - uint32_t sf_idx, - srslte_ra_dl_alloc_t *prb_alloc); - -SRSLTE_API int srslte_harq_setup_ul(srslte_harq_t *p, - srslte_ra_mcs_t mcs, - uint32_t rv, - uint32_t sf_idx, - srslte_ra_ul_alloc_t *prb_alloc); - -SRSLTE_API void srslte_harq_reset(srslte_harq_t *p); - -SRSLTE_API void srslte_harq_free(srslte_harq_t *p); - -SRSLTE_API int srslte_harq_codeblock_segmentation(srslte_harq_cbsegm_t *s, - uint32_t tbs); - - -#endif diff --git a/srslte/include/srslte/phch/pdsch.h b/srslte/include/srslte/phch/pdsch.h index 32b99a261..e97878550 100644 --- a/srslte/include/srslte/phch/pdsch.h +++ b/srslte/include/srslte/phch/pdsch.h @@ -46,12 +46,11 @@ #include "srslte/phch/dci.h" #include "srslte/phch/regs.h" #include "srslte/phch/sch.h" -#include "srslte/phch/harq.h" +#include "srslte/phch/pdsch_cfg.h" #define SRSLTE_PDSCH_MAX_TDEC_ITERS 5 - /* PDSCH object */ typedef struct SRSLTE_API { srslte_cell_t cell; @@ -87,25 +86,29 @@ SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti); SRSLTE_API int srslte_pdsch_encode(srslte_pdsch_t *q, - srslte_harq_t *harq_process, + srslte_pdsch_cfg_t *cfg, + srslte_softbuffer_tx_t *softbuffer, uint8_t *data, cf_t *sf_symbols[SRSLTE_MAX_PORTS]); SRSLTE_API int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, - srslte_harq_t *harq_process, + srslte_pdsch_cfg_t *cfg, + srslte_softbuffer_tx_t *softbuffer, uint8_t *data, uint16_t rnti, cf_t *sf_symbols[SRSLTE_MAX_PORTS]); SRSLTE_API int srslte_pdsch_decode(srslte_pdsch_t *q, - srslte_harq_t *harq_process, + srslte_pdsch_cfg_t *cfg, + srslte_softbuffer_rx_t *softbuffer, cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate, uint8_t *data); SRSLTE_API int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, - srslte_harq_t *harq_process, + srslte_pdsch_cfg_t *cfg, + srslte_softbuffer_rx_t *softbuffer, cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate, diff --git a/srslte/include/srslte/phch/pdsch_cfg.h b/srslte/include/srslte/phch/pdsch_cfg.h new file mode 100644 index 000000000..488cfb66e --- /dev/null +++ b/srslte/include/srslte/phch/pdsch_cfg.h @@ -0,0 +1,51 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \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 Lesser 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 Lesser General Public License for more details. + * + * A copy of the GNU Lesser 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: pdsch_cfg.h + * + * Description: Physical downlink shared channel configuration + * + * Reference: 3GPP TS 36.211 version 10.0.0 Release 10 Sec. 6.4 + *****************************************************************************/ + +#ifndef PDSCHCFG_ +#define PDSCHCFG_ + +#include "srslte/phch/ra.h" +#include "srslte/phch/softbuffer.h" +#include "srslte/fec/cbsegm.h" + +typedef struct SRSLTE_API { + srslte_cbsegm_t cb_segm; + srslte_ra_dl_grant_t grant; + uint32_t rv; + uint32_t sf_idx; +} srslte_pdsch_cfg_t; + +#endif + diff --git a/srslte/include/srslte/phch/pusch.h b/srslte/include/srslte/phch/pusch.h index 94a81c607..565d4428a 100644 --- a/srslte/include/srslte/phch/pusch.h +++ b/srslte/include/srslte/phch/pusch.h @@ -45,7 +45,7 @@ #include "srslte/scrambling/scrambling.h" #include "srslte/phch/regs.h" #include "srslte/phch/sch.h" -#include "srslte/phch/harq.h" +#include "srslte/phch/pusch_cfg.h" #include "srslte/dft/dft_precoding.h" #define SRSLTE_PUSCH_MAX_TDEC_ITERS 5 @@ -110,31 +110,36 @@ SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q, uint16_t rnti); SRSLTE_API int srslte_pusch_encode(srslte_pusch_t *q, - srslte_harq_t *harq_process, + srslte_pusch_cfg_t *cfg, + srslte_softbuffer_tx_t *softbuffer, uint8_t *data, cf_t *sf_symbols); SRSLTE_API int srslte_pusch_encode_rnti(srslte_pusch_t *q, - srslte_harq_t *harq_process, + srslte_pusch_cfg_t *cfg, + srslte_softbuffer_tx_t *softbuffer, uint8_t *data, uint16_t rnti, cf_t *sf_symbols); SRSLTE_API int srslte_pusch_uci_encode(srslte_pusch_t *q, - srslte_harq_t *harq_process, + srslte_pusch_cfg_t *cfg, + srslte_softbuffer_tx_t *softbuffer, uint8_t *data, srslte_uci_data_t uci_data, cf_t *sf_symbols); SRSLTE_API int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, - srslte_harq_t *harq, + srslte_pusch_cfg_t *cfg, + srslte_softbuffer_tx_t *softbuffer, uint8_t *data, srslte_uci_data_t uci_data, uint16_t rnti, cf_t *sf_symbols); SRSLTE_API int srslte_pusch_decode(srslte_pusch_t *q, - srslte_harq_t *harq_process, + srslte_pusch_cfg_t *cfg, + srslte_softbuffer_rx_t *softbuffer, cf_t *sf_symbols, cf_t *ce, float noise_estimate, diff --git a/srslte/include/srslte/phch/pusch_cfg.h b/srslte/include/srslte/phch/pusch_cfg.h new file mode 100644 index 000000000..ad60cd335 --- /dev/null +++ b/srslte/include/srslte/phch/pusch_cfg.h @@ -0,0 +1,52 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \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 Lesser 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 Lesser General Public License for more details. + * + * A copy of the GNU Lesser 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: pdsch_cfg.h + * + * Description: Physical downlink shared channel configuration + * + * Reference: 3GPP TS 36.211 version 10.0.0 Release 10 Sec. 6.4 + *****************************************************************************/ + +#ifndef PUSCHCFG_ +#define PUSCHCFG_ + +#include "srslte/phch/ra.h" +#include "srslte/phch/softbuffer.h" +#include "srslte/fec/cbsegm.h" + +typedef struct SRSLTE_API { + srslte_cbsegm_t cb_segm; + srslte_ra_ul_grant_t grant; + uint32_t rv; + uint32_t sf_idx; + srslte_cp_t cp; +} srslte_pusch_cfg_t; + +#endif + diff --git a/srslte/include/srslte/phch/ra.h b/srslte/include/srslte/phch/ra.h index 223f51fc8..a00a93408 100644 --- a/srslte/include/srslte/phch/ra.h +++ b/srslte/include/srslte/phch/ra.h @@ -29,6 +29,7 @@ * File: ra.h * * Description: Structures and utility functions for DL/UL resource allocation. + * Convert an UL/DL unpacket DCI message to a resource allocation * * Reference: 3GPP TS 36.213 version 10.0.1 Release 10 *****************************************************************************/ @@ -42,6 +43,10 @@ #include "srslte/config.h" #include "srslte/common/phy_common.h" +/************************************************** + * Common structures used for Resource Allocation + **************************************************/ + typedef struct SRSLTE_API { srslte_mod_t mod; int tbs; @@ -78,39 +83,72 @@ typedef struct SRSLTE_API { } mode; } srslte_ra_type2_t; -typedef struct SRSLTE_API { - bool prb_idx[SRSLTE_MAX_PRB]; - uint32_t nof_prb; -} srslte_ra_prb_slot_t; -typedef struct SRSLTE_API { - srslte_ra_prb_slot_t slot[2]; - uint32_t lstart; - uint32_t re_sf[SRSLTE_NSUBFRAMES_X_FRAME]; -} srslte_ra_dl_alloc_t; + + + + +/************************************************** + * Structures used for Downlink Resource Allocation + **************************************************/ typedef struct SRSLTE_API { - uint32_t n_prb[2]; - uint32_t n_prb_tilde[2]; - uint32_t L_prb; - uint32_t freq_hopping; -} srslte_ra_ul_alloc_t; + bool prb_idx[2][SRSLTE_MAX_PRB]; + uint32_t lstart; + uint32_t nof_re; + uint32_t nof_bits; + uint32_t nof_symb; + uint32_t nof_prb; + uint32_t Qm; + srslte_ra_mcs_t mcs; +} srslte_ra_dl_grant_t; +/** Unpacked DCI message for DL grant */ typedef struct SRSLTE_API { + + enum { + SRSLTE_RA_DCI_FORMAT1, + SRSLTE_RA_DCI_FORMAT1A, + SRSLTE_RA_DCI_FORMAT1C, + } dci_format; + srslte_ra_type_t alloc_type; union { srslte_ra_type0_t type0_alloc; srslte_ra_type1_t type1_alloc; srslte_ra_type2_t type2_alloc; }; - srslte_ra_dl_alloc_t prb_alloc; + uint32_t mcs_idx; - srslte_ra_mcs_t mcs; uint32_t harq_process; uint32_t rv_idx; bool ndi; -} srslte_ra_pdsch_t; +} srslte_ra_dl_dci_t; + + + + + +/************************************************** + * Structures used for Uplink Resource Allocation + **************************************************/ +typedef struct SRSLTE_API { + uint32_t n_prb[2]; + uint32_t n_prb_tilde[2]; + uint32_t L_prb; + uint32_t freq_hopping; + uint32_t lstart; + uint32_t nof_re; + uint32_t nof_bits; + uint32_t nof_symb; + uint32_t M_sc; + uint32_t M_sc_init; + uint32_t Qm; + srslte_ra_mcs_t mcs; +} srslte_ra_ul_grant_t; + +/** Unpacked DCI Format0 message */ typedef struct SRSLTE_API { /* 36.213 Table 8.4-2: SRSLTE_RA_PUSCH_HOP_HALF is 0 for < 10 Mhz and 10 for > 10 Mhz. * SRSLTE_RA_PUSCH_HOP_QUART is 00 for > 10 Mhz and SRSLTE_RA_PUSCH_HOP_QUART_NEG is 01 for > 10 Mhz. @@ -123,57 +161,49 @@ typedef struct SRSLTE_API { SRSLTE_RA_PUSCH_HOP_TYPE2 = 3 } freq_hop_fl; - srslte_ra_ul_alloc_t prb_alloc; - + srslte_ra_ul_grant_t prb_alloc; + srslte_ra_type2_t type2_alloc; uint32_t mcs_idx; - srslte_ra_mcs_t mcs; - uint32_t rv_idx; // If set to non-zero, a retransmission is requested with the same modulation - // than before (SRSLTE_DCI_FORMAT0 message, see also 8.6.1 in 36.2313). - + uint32_t rv_idx; uint32_t n_dmrs; bool ndi; bool cqi_request; -} srslte_ra_pusch_t; +} srslte_ra_ul_dci_t; -SRSLTE_API void srslte_ra_prb_fprint(FILE *f, - srslte_ra_prb_slot_t *prb, - uint32_t nof_prb); -SRSLTE_API int srslte_ra_dl_alloc(srslte_ra_dl_alloc_t *prb, - srslte_ra_pdsch_t *ra, - uint32_t nof_prb); -SRSLTE_API int srslte_ra_ul_alloc(srslte_ra_ul_alloc_t *prb, - srslte_ra_pusch_t *ra, - uint32_t n_rb_ho, - uint32_t nof_prb); +/************************************************** + * Functions + **************************************************/ -SRSLTE_API void srslte_ra_dl_alloc_re(srslte_ra_dl_alloc_t *prb_dist, - uint32_t nof_prb, - uint32_t nof_ports, - uint32_t nof_ctrl_symbols, - srslte_cp_t cp); -SRSLTE_API uint32_t srslte_ra_nprb_dl(srslte_ra_pdsch_t *ra, - uint32_t nof_prb); +SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t* dci, + srslte_ra_dl_grant_t* grant, + srslte_cell_t cell, + uint32_t sf_idx, + uint32_t cfi, + bool crc_is_crnti); -SRSLTE_API uint32_t srslte_ra_nprb_ul(srslte_ra_pusch_t *ra, - uint32_t nof_prb); +SRSLTE_API void srslte_dl_dci_to_grant_nof_re(srslte_ra_dl_grant_t *grant, + srslte_cell_t cell, + uint32_t sf_idx, + uint32_t nof_ctrl_symbols); -SRSLTE_API int srslte_ra_mcs_from_idx_dl(uint32_t mcs_idx, - uint32_t nof_prb, - srslte_ra_mcs_t *mcs); +SRSLTE_API int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, + srslte_ra_ul_grant_t *grant, + srslte_cell_t cell, + uint32_t n_rb_ho, + uint32_t N_srs); -SRSLTE_API int srslte_ra_mcs_from_idx_ul(uint32_t mcs_idx, - uint32_t nof_prb, - srslte_ra_mcs_t *mcs); - -SRSLTE_API int srslte_ra_tbs_from_idx_format1c(uint32_t tbs_idx); +SRSLTE_API int srslte_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, + srslte_ra_ul_grant_t *grant, + uint32_t n_rb_ho, + uint32_t nof_prb); SRSLTE_API int srslte_ra_tbs_from_idx(uint32_t tbs_idx, - uint32_t n_prb); + uint32_t n_prb); SRSLTE_API int srslte_ra_tbs_to_table_idx(uint32_t tbs, uint32_t n_prb); @@ -201,11 +231,20 @@ SRSLTE_API uint32_t srslte_ra_type2_ngap(uint32_t nof_prb, SRSLTE_API uint32_t srslte_ra_type1_N_rb(uint32_t nof_prb); SRSLTE_API void srslte_ra_pdsch_fprint(FILE *f, - srslte_ra_pdsch_t *ra, + srslte_ra_dl_dci_t *ra, uint32_t nof_prb); +SRSLTE_API void srslte_ra_dl_grant_fprint(FILE *f, + srslte_ra_dl_grant_t *grant); + +SRSLTE_API void srslte_ra_prb_fprint(FILE *f, + srslte_ra_dl_grant_t *grant); + SRSLTE_API void srslte_ra_pusch_fprint(FILE *f, - srslte_ra_pusch_t *ra, + srslte_ra_ul_dci_t *ra, uint32_t nof_prb); +SRSLTE_API void srslte_ra_ul_grant_fprint(FILE *f, + srslte_ra_ul_grant_t *grant); + #endif /* RB_ALLOC_H_ */ diff --git a/srslte/include/srslte/phch/sch.h b/srslte/include/srslte/phch/sch.h index 3e4806bb0..d89a482da 100644 --- a/srslte/include/srslte/phch/sch.h +++ b/srslte/include/srslte/phch/sch.h @@ -42,7 +42,8 @@ #include "srslte/fec/turbocoder.h" #include "srslte/fec/turbodecoder.h" #include "srslte/fec/crc.h" -#include "srslte/phch/harq.h" +#include "srslte/phch/pdsch_cfg.h" +#include "srslte/phch/pusch_cfg.h" #include "srslte/phch/uci.h" #define SRSLTE_PDSCH_MAX_TDEC_ITERS 5 @@ -58,7 +59,7 @@ /* DL-SCH AND UL-SCH common functions */ typedef struct SRSLTE_API { - + uint32_t nof_iterations; float average_nof_iterations; @@ -86,31 +87,42 @@ SRSLTE_API float srslte_sch_average_noi(srslte_sch_t *q); SRSLTE_API uint32_t srslte_sch_last_noi(srslte_sch_t *q); SRSLTE_API int srslte_dlsch_encode(srslte_sch_t *q, - srslte_harq_t *harq_process, - uint8_t *data, - uint8_t *e_bits); + srslte_pdsch_cfg_t *cfg, + srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, + uint8_t *e_bits); SRSLTE_API int srslte_dlsch_decode(srslte_sch_t *q, - srslte_harq_t *harq_process, - float *e_bits, - uint8_t *data); + srslte_pdsch_cfg_t *cfg, + srslte_softbuffer_rx_t *softbuffer, + float *e_bits, + uint8_t *data); SRSLTE_API int srslte_ulsch_encode(srslte_sch_t *q, - srslte_harq_t *harq_process, - uint8_t *data, - uint8_t *g_bits, - uint8_t *q_bits); + srslte_pusch_cfg_t *cfg, + srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, + uint8_t *g_bits, + uint8_t *q_bits); SRSLTE_API int srslte_ulsch_uci_encode(srslte_sch_t *q, - srslte_harq_t *harq_process, - uint8_t *data, - srslte_uci_data_t uci_data, - uint8_t *g_bits, - uint8_t *q_bits); + srslte_pusch_cfg_t *cfg, + srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, + srslte_uci_data_t uci_data, + uint8_t *g_bits, + uint8_t *q_bits); SRSLTE_API int srslte_ulsch_decode(srslte_sch_t *q, - srslte_harq_t *harq_process, - float *e_bits, - uint8_t *data); + srslte_pusch_cfg_t *cfg, + srslte_softbuffer_rx_t *softbuffer, + float *e_bits, + uint8_t *data); + +SRSLTE_API uint32_t srslte_sch_find_Ioffset_ack(float beta); + +SRSLTE_API uint32_t srslte_sch_find_Ioffset_cqi(float beta); + +SRSLTE_API uint32_t srslte_sch_find_Ioffset_ri(float beta); #endif diff --git a/srslte/include/srslte/phch/softbuffer.h b/srslte/include/srslte/phch/softbuffer.h new file mode 100644 index 000000000..a7e5077d9 --- /dev/null +++ b/srslte/include/srslte/phch/softbuffer.h @@ -0,0 +1,71 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \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 Lesser 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 Lesser General Public License for more details. + * + * A copy of the GNU Lesser 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: softbuffer.h + * + * Description: Buffer for RX and TX soft bits. This should be provided by MAC. + * Provided here basically for the examples. + * + * Reference: + *****************************************************************************/ + +#ifndef SOFTBUFFER_ +#define SOFTBUFFER_ + +#include "srslte/config.h" +#include "srslte/common/phy_common.h" + +typedef struct SRSLTE_API { + uint32_t max_cb; + uint32_t buff_size; + float **buffer_f; +} srslte_softbuffer_rx_t; + +typedef struct SRSLTE_API { + uint32_t max_cb; + uint32_t buff_size; + uint8_t **buffer_b; +} srslte_softbuffer_tx_t; + +SRSLTE_API int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t * q, + srslte_cell_t cell); + +SRSLTE_API void srslte_softbuffer_rx_reset(srslte_softbuffer_rx_t *p); + +SRSLTE_API void srslte_softbuffer_rx_free(srslte_softbuffer_rx_t *p); + +SRSLTE_API int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t * q, + srslte_cell_t cell); + +SRSLTE_API void srslte_softbuffer_tx_reset(srslte_softbuffer_tx_t *p); + +SRSLTE_API void srslte_softbuffer_tx_free(srslte_softbuffer_tx_t *p); + + + +#endif diff --git a/srslte/include/srslte/phch/uci.h b/srslte/include/srslte/phch/uci.h index 0df2c7768..69e068151 100644 --- a/srslte/include/srslte/phch/uci.h +++ b/srslte/include/srslte/phch/uci.h @@ -38,14 +38,13 @@ #include "srslte/config.h" #include "srslte/common/phy_common.h" -#include "srslte/phch/harq.h" +#include "srslte/phch/pusch_cfg.h" #include "srslte/fec/crc.h" #define SRSLTE_UCI_MAX_CQI_LEN_PUSCH 512 #define SRSLTE_UCI_MAX_CQI_LEN_PUCCH 13 #define SRSLTE_UCI_CQI_CODED_PUCCH_B 20 - typedef struct SRSLTE_API { srslte_crc_t crc; uint8_t tmp_cqi[SRSLTE_UCI_MAX_CQI_LEN_PUSCH]; @@ -72,28 +71,28 @@ SRSLTE_API int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t *q); SRSLTE_API void srslte_uci_cqi_free(srslte_uci_cqi_pusch_t *q); SRSLTE_API int srslte_uci_encode_cqi_pusch(srslte_uci_cqi_pusch_t *q, + srslte_pusch_cfg_t *cfg, uint8_t *cqi_data, uint32_t cqi_len, float beta, uint32_t Q_prime_ri, - srslte_harq_t *harq_process, uint8_t *q_bits); SRSLTE_API int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]); -SRSLTE_API int srslte_uci_encode_ack(uint8_t data, - uint32_t O_cqi, +SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, + uint8_t data, + uint32_t O_cqi, float beta, - srslte_harq_t *harq_process, uint32_t H_prime_total, uint8_t *q_bits); -SRSLTE_API int srslte_uci_encode_ri(uint8_t data, - uint32_t O_cqi, +SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg, + uint8_t data, + uint32_t O_cqi, float beta, - srslte_harq_t *harq_process, uint32_t H_prime_total, uint8_t *q_bits); diff --git a/srslte/include/srslte/srslte.h b/srslte/include/srslte/srslte.h index bd7bec9ca..e6d71e22e 100644 --- a/srslte/include/srslte/srslte.h +++ b/srslte/include/srslte/srslte.h @@ -64,6 +64,7 @@ #include "srslte/fec/tc_interl.h" #include "srslte/fec/turbocoder.h" #include "srslte/fec/turbodecoder.h" +#include "srslte/fec/cbsegm.h" #include "srslte/fec/rm_conv.h" #include "srslte/fec/rm_turbo.h" @@ -87,7 +88,7 @@ #include "srslte/phch/cqi.h" #include "srslte/phch/dci.h" -#include "srslte/phch/harq.h" +#include "srslte/phch/softbuffer.h" #include "srslte/phch/pbch.h" #include "srslte/phch/pcfich.h" #include "srslte/phch/pdcch.h" diff --git a/srslte/include/srslte/ue/ue_dl.h b/srslte/include/srslte/ue/ue_dl.h index 4e04ea519..ac67a5004 100644 --- a/srslte/include/srslte/ue/ue_dl.h +++ b/srslte/include/srslte/ue/ue_dl.h @@ -49,6 +49,7 @@ #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" @@ -58,19 +59,17 @@ #include "srslte/config.h" -#define SRSLTE_UE_UL_NOF_HARQ_PROCESSES 8 - typedef struct SRSLTE_API { srslte_pcfich_t pcfich; srslte_pdcch_t pdcch; srslte_pdsch_t pdsch; srslte_phich_t phich; - srslte_harq_t harq_process[SRSLTE_UE_UL_NOF_HARQ_PROCESSES]; srslte_regs_t regs; srslte_ofdm_t fft; srslte_chest_dl_t chest; - srslte_ra_pdsch_t ra_dl; + srslte_pdsch_cfg_t pdsch_cfg; + srslte_softbuffer_rx_t softbuffer; srslte_cell_t cell; diff --git a/srslte/include/srslte/ue/ue_phy.h b/srslte/include/srslte/ue/ue_phy.h index 26d513f2b..6ad32a2bf 100644 --- a/srslte/include/srslte/ue/ue_phy.h +++ b/srslte/include/srslte/ue/ue_phy.h @@ -82,8 +82,8 @@ public: uint32_t get_harq_process(); private: union { - srslte_ra_pusch_t ul_grant; - srslte_ra_pdsch_t dl_grant; + srslte_ra_ul_dci_t ul_grant; + srslte_ra_dl_dci_t dl_grant; }; direction_t dir; }; diff --git a/srslte/include/srslte/ue/ue_ul.h b/srslte/include/srslte/ue/ue_ul.h index f5e29e60f..4d984dd48 100644 --- a/srslte/include/srslte/ue/ue_ul.h +++ b/srslte/include/srslte/ue/ue_ul.h @@ -63,8 +63,10 @@ typedef struct SRSLTE_API { float current_cfo; + srslte_pusch_cfg_t pusch_cfg; srslte_refsignal_ul_t dmrs; - srslte_harq_t harq_process[SRSLTE_UE_UL_NOF_HARQ_PROCESSES]; + srslte_softbuffer_tx_t softbuffer; + srslte_pusch_t pusch; srslte_pucch_t pucch; @@ -103,33 +105,44 @@ SRSLTE_API int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, cf_t *output_signal); SRSLTE_API int srslte_ue_ul_pusch_encode(srslte_ue_ul_t *q, - srslte_ra_pusch_t *ra_ul, + srslte_ra_ul_grant_t *grant, uint8_t *data, uint32_t sf_idx, + uint32_t rv, cf_t *output_signal); SRSLTE_API int srslte_ue_ul_pusch_encode_rnti(srslte_ue_ul_t *q, - srslte_ra_pusch_t *ra_ul, + srslte_ra_ul_grant_t *grant, uint8_t *data, uint32_t sf_idx, + uint32_t rv, uint16_t rnti, cf_t *output_signal); SRSLTE_API int srslte_ue_ul_pusch_uci_encode(srslte_ue_ul_t *q, - srslte_ra_pusch_t *ra_ul, + srslte_ra_ul_grant_t *grant, uint8_t *data, srslte_uci_data_t uci_data, uint32_t sf_idx, + uint32_t rv, cf_t *output_signal); SRSLTE_API int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, - srslte_ra_pusch_t *ra_ul, + srslte_ra_ul_grant_t *grant, uint8_t *data, srslte_uci_data_t uci_data, uint32_t sf_idx, + uint32_t rv, uint16_t rnti, cf_t *output_signal); +SRSLTE_API int srslte_ue_ul_pusch_encode_cfg(srslte_ue_ul_t *q, + srslte_pusch_cfg_t *cfg, + uint8_t *data, + srslte_uci_data_t uci_data, + uint16_t rnti, + cf_t *output_signal); + SRSLTE_API void srslte_ue_ul_reset(srslte_ue_ul_t *q); SRSLTE_API void srslte_ue_ul_set_rnti(srslte_ue_ul_t *q, diff --git a/srslte/include/srslte/ue_itf/dl_buffer.h b/srslte/include/srslte/ue_itf/dl_buffer.h index f4231fb96..addbb2437 100644 --- a/srslte/include/srslte/ue_itf/dl_buffer.h +++ b/srslte/include/srslte/ue_itf/dl_buffer.h @@ -27,7 +27,8 @@ #include "srslte/srslte.h" #include "srslte/ue_itf/queue.h" -#include "srslte/ue_itf/sched_grant.h" +#include "srslte/ue_itf/ul_sched_grant.h" +#include "srslte/ue_itf/dl_sched_grant.h" #include "srslte/ue_itf/phy_params.h" #ifndef UEDLBUFFER_H @@ -64,10 +65,11 @@ namespace ue { bool init_cell(srslte_cell_t cell, phy_params *params_db); void free_cell(); 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_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 + bool get_ul_grant(pdcch_ul_search_t mode, ul_sched_grant *grant); + bool get_dl_grant(pdcch_dl_search_t mode, dl_sched_grant *grant); + bool decode_ack(ul_sched_grant *pusch_grant); + bool decode_data(dl_sched_grant *pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/NOK + private: phy_params *params_db; srslte_cell_t cell; diff --git a/srslte/include/srslte/ue_itf/dl_sched_grant.h b/srslte/include/srslte/ue_itf/dl_sched_grant.h new file mode 100644 index 000000000..2048f8d21 --- /dev/null +++ b/srslte/include/srslte/ue_itf/dl_sched_grant.h @@ -0,0 +1,94 @@ + /** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \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 Lesser 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 Lesser General Public License for more details. + * + * A copy of the GNU Lesser 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 + +#include "srslte/srslte.h" +#include "srslte/ue_itf/sched_grant.h" + +#ifndef UEDLSCHEDGRANT_H +#define UEDLSCHEDGRANT_H + +namespace srslte { +namespace ue { + + /* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */ + class SRSLTE_API dl_sched_grant : public sched_grant { + public: + + dl_sched_grant(uint16_t rnti) : sched_grant(rnti) {} + + uint32_t get_rv() { + return dl_dci.rv_idx; + } + void set_rv(uint32_t rv) { + dl_dci.rv_idx = rv; + } + bool get_ndi() { + return dl_dci.ndi; + } + void set_ndi(bool value) { + dl_dci.ndi = value; + } + uint32_t get_harq_process() { + return dl_dci.harq_process; + } + void get_dl_grant(srslte_ra_dl_grant_t *ul_grant) { + memcpy(ul_grant, &grant, sizeof(srslte_ra_dl_grant_t)); + } + bool is_sps_release() { + return false; + } + uint32_t get_tbs() { + return grant.mcs.tbs; + } + uint32_t get_ncce() { + return ncce; + } + bool create_from_dci(srslte_dci_msg_t *msg, srslte_cell_t cell, uint32_t cfi, uint32_t sf_idx, uint32_t ncce_) { + ncce = ncce_; + if (srslte_dci_msg_to_dl_grant(msg, rnti, cell, cfi, sf_idx, &dl_dci, &grant)) { + return false; + } else { + return true; + } + } + void get_pdsch_cfg(uint32_t sf_idx, srslte_pdsch_cfg_t *cfg) { + srslte_cbsegm(&cfg->cb_segm, grant.mcs.tbs); + memcpy(&cfg->grant, &grant, sizeof(srslte_ra_dl_grant_t)); + cfg->sf_idx = sf_idx; + cfg->rv = dl_dci.rv_idx; + } + private: + srslte_ra_dl_grant_t grant; + srslte_ra_dl_dci_t dl_dci; + uint32_t ncce; + }; + +} +} + +#endif diff --git a/srslte/include/srslte/ue_itf/phy.h b/srslte/include/srslte/ue_itf/phy.h index 84fe4a32d..125431d0e 100644 --- a/srslte/include/srslte/ue_itf/phy.h +++ b/srslte/include/srslte/ue_itf/phy.h @@ -59,7 +59,11 @@ typedef _Complex float cf_t; class SRSLTE_API phy { public: - + phy() { + started = false; + is_sfn_synched = false; + cell_is_set = false; + } bool init(radio *radio_handler, tti_sync *ttisync); void stop(); @@ -87,7 +91,7 @@ public: void set_timeadv(uint32_t ta_cmd); // Generate Msg3 UL grant from RAR - void rar_ul_grant(uint32_t rba, uint32_t trunc_mcs, bool hopping_flag, sched_grant *grant); + void rar_ul_grant(srslte_dci_rar_grant_t *rar, ul_sched_grant *grant); // Get status bool status_is_idle(); @@ -114,8 +118,8 @@ private: srslte_cell_t cell; bool cell_is_set; - bool is_sfn_synched = false; - bool started = false; + bool is_sfn_synched; + bool started; srslte_ue_sync_t ue_sync; srslte_ue_mib_t ue_mib; diff --git a/srslte/include/srslte/ue_itf/prach.h b/srslte/include/srslte/ue_itf/prach.h index 895de037b..50e7227cb 100644 --- a/srslte/include/srslte/ue_itf/prach.h +++ b/srslte/include/srslte/ue_itf/prach.h @@ -38,6 +38,11 @@ namespace ue { class SRSLTE_API prach { public: + prach() { + params_db = NULL; + initiated = false; + signal_buffer = NULL; + } bool init_cell(srslte_cell_t cell, phy_params *params_db); void free_cell(); bool prepare_to_send(uint32_t preamble_idx); @@ -51,7 +56,7 @@ namespace ue { bool initiated = false; uint32_t len; cf_t *buffer[64]; - srslte_prach_t prach; + srslte_prach_t prach_obj; uint32_t transmitted_tti; srslte_cell_t cell; cf_t *signal_buffer; diff --git a/srslte/include/srslte/ue_itf/sched_grant.h b/srslte/include/srslte/ue_itf/sched_grant.h index 6c4e8fa94..deaf5ba4b 100644 --- a/srslte/include/srslte/ue_itf/sched_grant.h +++ b/srslte/include/srslte/ue_itf/sched_grant.h @@ -37,34 +37,20 @@ namespace ue { /* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */ class SRSLTE_API sched_grant { public: - - typedef enum {DOWNLINK=0, UPLINK=1} direction_t; - sched_grant(direction_t direction, uint16_t rnti); - uint16_t get_rnti(); - uint32_t get_rv(); - void set_rv(uint32_t rv); - bool get_ndi(); - void set_ndi(bool value); - bool get_cqi_request(); - int get_harq_process(); - bool is_uplink(); - bool is_downlink(); - void* get_grant_ptr(); - bool is_sps_release(); - 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); + sched_grant(uint16_t rnti_) { + rnti = rnti_; + } + uint16_t get_rnti() { + return rnti; + } + virtual uint32_t get_rv() = 0; + virtual void set_rv(uint32_t rv) = 0; + virtual bool get_ndi() = 0; + virtual void set_ndi(bool value) = 0; + virtual bool is_sps_release() = 0; + virtual uint32_t get_tbs() = 0; protected: - union { - srslte_ra_pusch_t ul_grant; - srslte_ra_pdsch_t dl_grant; - }; - 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 17d8c2672..1ad7ee3ce 100644 --- a/srslte/include/srslte/ue_itf/ul_buffer.h +++ b/srslte/include/srslte/ue_itf/ul_buffer.h @@ -28,7 +28,8 @@ #include "srslte/srslte.h" #include "srslte/common/radio.h" #include "srslte/ue_itf/queue.h" -#include "srslte/ue_itf/sched_grant.h" +#include "srslte/ue_itf/ul_sched_grant.h" +#include "srslte/ue_itf/dl_sched_grant.h" #include "srslte/ue_itf/phy_params.h" #ifndef UEULBUFFER_H @@ -48,26 +49,27 @@ namespace ue { void free_cell(); void set_tti(uint32_t tti); void set_current_tx_nb(uint32_t current_tx_nb); - bool generate_ack(bool ack, sched_grant last_dl_grant); + bool generate_ack(bool ack, dl_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 generate_data(ul_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 private: - phy_params *params_db; - srslte_cell_t cell; - srslte_ue_ul_t ue_ul; - 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; + phy_params *params_db; + srslte_cell_t cell; + srslte_ue_ul_t ue_ul; + srslte_pusch_cfg_t pusch_cfg; + 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/include/srslte/ue_itf/ul_sched_grant.h b/srslte/include/srslte/ue_itf/ul_sched_grant.h new file mode 100644 index 000000000..7fa907761 --- /dev/null +++ b/srslte/include/srslte/ue_itf/ul_sched_grant.h @@ -0,0 +1,117 @@ + /** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \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 Lesser 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 Lesser General Public License for more details. + * + * A copy of the GNU Lesser 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 + +#include "srslte/srslte.h" +#include "srslte/ue_itf/sched_grant.h" + +#ifndef UEULSCHEDGRANT_H +#define UEULSCHEDGRANT_H + +namespace srslte { +namespace ue { + + /* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */ + class SRSLTE_API ul_sched_grant : public sched_grant { + public: + + ul_sched_grant(uint16_t rnti) : sched_grant(rnti) {} + + uint32_t get_rv() { + return ul_dci.rv_idx; + } + void set_rv(uint32_t rv) { + ul_dci.rv_idx = rv; + } + bool get_ndi() { + return ul_dci.ndi; + } + void set_ndi(bool value) { + ul_dci.ndi = value; + } + bool get_cqi_request() { + return ul_dci.cqi_request; + } + void get_ul_grant(srslte_ra_ul_grant_t *ul_grant) { + memcpy(ul_grant, &grant, sizeof(srslte_ra_ul_grant_t)); + } + bool is_sps_release() { + return false; + } + uint32_t get_tbs() { + return grant.mcs.tbs; + } + uint32_t get_current_tx_nb() { + return current_tx_nb; + } + void set_current_tx_nb(uint32_t current_tx_nb) { + current_tx_nb = current_tx_nb; + } + uint32_t get_I_lowest() { + return grant.n_prb[0]; + } + uint32_t get_n_dmrs() { + return ul_dci.n_dmrs; + } + bool create_from_dci(srslte_dci_msg_t *msg, srslte_cell_t cell, uint32_t N_srs, uint32_t n_rb_ho) { + if (srslte_dci_msg_to_ul_grant(msg, cell, N_srs, n_rb_ho, &ul_dci, &grant)) { + return false; + } else { + if (SRSLTE_VERBOSE_ISINFO()) { + srslte_ra_pusch_fprint(stdout, &ul_dci, cell.nof_prb); + } + return true; + } + } + bool create_from_rar(srslte_dci_rar_grant_t *rar, srslte_cell_t cell, uint32_t N_srs, uint32_t n_rb_ho) { + if (srslte_dci_rar_to_ul_grant(rar, cell, N_srs, n_rb_ho, &ul_dci, &grant)) { + return false; + } else { + if (SRSLTE_VERBOSE_ISINFO()) { + srslte_ra_pusch_fprint(stdout, &ul_dci, cell.nof_prb); + } + return true; + } + } + void to_pusch_cfg(uint32_t sf_idx, srslte_cp_t cp, srslte_pusch_cfg_t *cfg) { + srslte_cbsegm(&cfg->cb_segm, grant.mcs.tbs); + cfg->cp = cp; + memcpy(&cfg->grant, &grant, sizeof(srslte_ra_ul_grant_t)); + cfg->rv = ul_dci.rv_idx; + cfg->sf_idx = sf_idx; + } + private: + srslte_ra_ul_grant_t grant; + srslte_ra_ul_dci_t ul_dci; + uint32_t current_tx_nb; + uint16_t rnti; + }; + +} +} + +#endif diff --git a/srslte/lib/ch_estimation/test/chest_test_dl.c b/srslte/lib/ch_estimation/test/chest_test_dl.c index b59d9d10f..31817dc03 100644 --- a/srslte/lib/ch_estimation/test/chest_test_dl.c +++ b/srslte/lib/ch_estimation/test/chest_test_dl.c @@ -85,7 +85,7 @@ int main(int argc, char **argv) { srslte_chest_dl_t est; srslte_precoding_t cheq; cf_t *input = NULL, *ce = NULL, *h = NULL, *output = NULL; - int i, j, n_port, sf_idx, cid, num_re; + int i, j, n_port=0, sf_idx=0, cid=0, num_re; int ret = -1; int max_cid; FILE *fmatlab = NULL; diff --git a/srslte/lib/common/src/phy_common.c b/srslte/lib/common/src/phy_common.c index f612453c4..57f75367d 100644 --- a/srslte/lib/common/src/phy_common.c +++ b/srslte/lib/common/src/phy_common.c @@ -35,21 +35,6 @@ #include "srslte/common/phy_common.h" #include "srslte/common/sequence.h" -const uint32_t tc_cb_sizes[SRSLTE_NOF_TC_CB_SIZES] = { 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, - 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, - 240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, 336, 344, - 352, 360, 368, 376, 384, 392, 400, 408, 416, 424, 432, 440, 448, 456, - 464, 472, 480, 488, 496, 504, 512, 528, 544, 560, 576, 592, 608, 624, - 640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816, 832, 848, - 864, 880, 896, 912, 928, 944, 960, 976, 992, 1008, 1024, 1056, 1088, - 1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1440, 1472, - 1504, 1536, 1568, 1600, 1632, 1664, 1696, 1728, 1760, 1792, 1824, 1856, - 1888, 1920, 1952, 1984, 2016, 2048, 2112, 2176, 2240, 2304, 2368, 2432, - 2496, 2560, 2624, 2688, 2752, 2816, 2880, 2944, 3008, 3072, 3136, 3200, - 3264, 3328, 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, 3904, 3968, - 4032, 4096, 4160, 4224, 4288, 4352, 4416, 4480, 4544, 4608, 4672, 4736, - 4800, 4864, 4928, 4992, 5056, 5120, 5184, 5248, 5312, 5376, 5440, 5504, - 5568, 5632, 5696, 5760, 5824, 5888, 5952, 6016, 6080, 6144 }; /* Returns true if the structure pointed by cell has valid parameters */ @@ -135,27 +120,6 @@ bool srslte_N_id_1_isvalid(uint32_t N_id_1) { } } - -/* - * Returns Turbo coder interleaver size for Table 5.1.3-3 (36.212) index - */ -int srslte_cb_size(uint32_t index) { - if (index < SRSLTE_NOF_TC_CB_SIZES) { - return (int) tc_cb_sizes[index]; - } else { - return SRSLTE_ERROR; - } -} - -bool srslte_cb_size_isvalid(uint32_t size) { - for (int i=0;i=long_cb in Table 5.1.3-3 of 36.212 - */ -int srslte_find_cb_index(uint32_t long_cb) { - int j = 0; - while (j < SRSLTE_NOF_TC_CB_SIZES && tc_cb_sizes[j] < long_cb) { - j++; - } - - if (j == SRSLTE_NOF_TC_CB_SIZES) { - return SRSLTE_ERROR; - } else { - return j; - } -} int srslte_sampling_freq_hz(uint32_t nof_prb) { int n = srslte_symbol_sz(nof_prb); diff --git a/srslte/lib/fec/src/cbsegm.c b/srslte/lib/fec/src/cbsegm.c new file mode 100644 index 000000000..3e3a4d85b --- /dev/null +++ b/srslte/lib/fec/src/cbsegm.c @@ -0,0 +1,137 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \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 Lesser 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 Lesser General Public License for more details. + * + * A copy of the GNU Lesser 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 +#include + +#include "srslte/fec/turbodecoder.h" +#include "srslte/fec/cbsegm.h" +#include "srslte/utils/debug.h" + + +const uint32_t tc_cb_sizes[SRSLTE_NOF_TC_CB_SIZES] = { 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, + 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, + 240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, 336, 344, + 352, 360, 368, 376, 384, 392, 400, 408, 416, 424, 432, 440, 448, 456, + 464, 472, 480, 488, 496, 504, 512, 528, 544, 560, 576, 592, 608, 624, + 640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816, 832, 848, + 864, 880, 896, 912, 928, 944, 960, 976, 992, 1008, 1024, 1056, 1088, + 1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1440, 1472, + 1504, 1536, 1568, 1600, 1632, 1664, 1696, 1728, 1760, 1792, 1824, 1856, + 1888, 1920, 1952, 1984, 2016, 2048, 2112, 2176, 2240, 2304, 2368, 2432, + 2496, 2560, 2624, 2688, 2752, 2816, 2880, 2944, 3008, 3072, 3136, 3200, + 3264, 3328, 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, 3904, 3968, + 4032, 4096, 4160, 4224, 4288, 4352, 4416, 4480, 4544, 4608, 4672, 4736, + 4800, 4864, 4928, 4992, 5056, 5120, 5184, 5248, 5312, 5376, 5440, 5504, + 5568, 5632, 5696, 5760, 5824, 5888, 5952, 6016, 6080, 6144 }; + +/* Calculate Codeblock Segmentation as in Section 5.1.2 of 36.212 */ +int srslte_cbsegm(srslte_cbsegm_t *s, uint32_t tbs) { + uint32_t Bp, B, idx1; + int ret; + + if (tbs == 0) { + bzero(s, sizeof(srslte_cbsegm_t)); + ret = SRSLTE_SUCCESS; + } else { + B = tbs + 24; + s->tbs = tbs; + + /* Calculate CB sizes */ + if (B <= SRSLTE_TCOD_MAX_LEN_CB) { + s->C = 1; + Bp = B; + } else { + s->C = (uint32_t) ceilf((float) B / (SRSLTE_TCOD_MAX_LEN_CB - 24)); + Bp = B + 24 * s->C; + } + ret = srslte_cbsegm_cbindex((Bp-1) / s->C + 1); + if (ret != SRSLTE_ERROR) { + idx1 = (uint32_t) ret; + ret = srslte_cbsegm_cbsize(idx1); + if (ret != SRSLTE_ERROR) { + s->K1 = (uint32_t) ret; + if (idx1 > 0) { + ret = srslte_cbsegm_cbsize(idx1 - 1); + } + if (ret != SRSLTE_ERROR) { + if (s->C == 1) { + s->K2 = 0; + s->C2 = 0; + s->C1 = 1; + } else { + s->K2 = (uint32_t) ret; + s->C2 = (s->C * s->K1 - Bp) / (s->K1 - s->K2); + s->C1 = s->C - s->C2; + } + s->F = s->C1 * s->K1 + s->C2 * s->K2 - Bp; + INFO("CB Segmentation: TBS: %d, C=%d, C+=%d K+=%d, C-=%d, K-=%d, F=%d, Bp=%d\n", + tbs, s->C, s->C1, s->K1, s->C2, s->K2, s->F, Bp); + ret = SRSLTE_SUCCESS; + } + } + } + + } + return ret; +} + +/* + * Finds index of minimum K>=long_cb in Table 5.1.3-3 of 36.212 + */ +int srslte_cbsegm_cbindex(uint32_t long_cb) { + int j = 0; + while (j < SRSLTE_NOF_TC_CB_SIZES && tc_cb_sizes[j] < long_cb) { + j++; + } + + if (j == SRSLTE_NOF_TC_CB_SIZES) { + return SRSLTE_ERROR; + } else { + return j; + } +} + +/* + * Returns Turbo coder interleaver size for Table 5.1.3-3 (36.212) index + */ +int srslte_cbsegm_cbsize(uint32_t index) { + if (index < SRSLTE_NOF_TC_CB_SIZES) { + return (int) tc_cb_sizes[index]; + } else { + return SRSLTE_ERROR; + } +} + +bool srslte_cbsegm_cbsize_isvalid(uint32_t size) { + for (int i=0;i 0 && cfi < 4) { ret = SRSLTE_ERROR; srslte_dci_msg_type_t type; + if (srslte_dci_msg_get_type(msg, &type, cell.nof_prb, msg_rnti)) { fprintf(stderr, "Can't get DCI message type\n"); return ret; @@ -68,28 +70,25 @@ int srslte_dci_msg_to_ra_dl(srslte_dci_msg_t *msg, uint16_t msg_rnti, srslte_dci_msg_type_fprint(stdout, type); } if (type.type == SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED) { - bzero(ra_dl, sizeof(srslte_ra_pdsch_t)); + bzero(dl_dci, sizeof(srslte_ra_dl_dci_t)); + bzero(grant, sizeof(srslte_ra_dl_grant_t)); bool crc_is_crnti = false; if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) { crc_is_crnti = true; } - if (srslte_dci_msg_unpack_pdsch(msg, ra_dl, cell.nof_prb, crc_is_crnti)) { + if (srslte_dci_msg_unpack_pdsch(msg, dl_dci, cell.nof_prb, crc_is_crnti)) { fprintf(stderr, "Can't unpack PDSCH message\n"); return ret; } + srslte_ra_dl_dci_to_grant(dl_dci, grant, cell, sf_idx, cfi, crc_is_crnti); + if (SRSLTE_VERBOSE_ISINFO()) { - srslte_ra_pdsch_fprint(stdout, ra_dl, cell.nof_prb); - } - - if (srslte_ra_dl_alloc(&ra_dl->prb_alloc, ra_dl, cell.nof_prb)) { - fprintf(stderr, "Error computing resource allocation\n"); - return ret; + srslte_ra_pdsch_fprint(stdout, dl_dci, cell.nof_prb); + srslte_ra_dl_grant_fprint(stdout, grant); } - - srslte_ra_dl_alloc_re(&ra_dl->prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp); - + ret = SRSLTE_SUCCESS; } else { if (SRSLTE_VERBOSE_ISINFO()) { @@ -103,58 +102,77 @@ int srslte_dci_msg_to_ra_dl(srslte_dci_msg_t *msg, uint16_t msg_rnti, /* Creates the UL PUSCH resource allocation grant from the random access respone message */ -int srslte_dci_rar_to_ra_ul(uint32_t rba, uint32_t trunc_mcs, bool hopping_flag, uint32_t nof_prb, srslte_ra_pusch_t *ra) { - bzero(ra, sizeof(srslte_ra_pusch_t)); - if (!hopping_flag) { - ra->freq_hop_fl = SRSLTE_RA_PUSCH_HOP_DISABLED; +int srslte_dci_rar_to_ul_grant(srslte_dci_rar_grant_t *rar, srslte_cell_t cell, + uint32_t N_srs, uint32_t n_rb_ho, + srslte_ra_ul_dci_t *ul_dci, + srslte_ra_ul_grant_t *grant) +{ + bzero(ul_dci, sizeof(srslte_ra_ul_dci_t)); + + if (!rar->hopping_flag) { + ul_dci->freq_hop_fl = SRSLTE_RA_PUSCH_HOP_DISABLED; } else { fprintf(stderr, "FIXME: Frequency hopping in RAR not implemented\n"); - ra->freq_hop_fl = 1; + ul_dci->freq_hop_fl = 1; } - uint32_t riv = rba; + uint32_t riv = rar->rba; // Truncate resource block assignment uint32_t b = 0; - if (nof_prb <= 44) { - b = (uint32_t) (ceilf(log2((float) nof_prb*(nof_prb+1)/2))); + if (cell.nof_prb <= 44) { + b = (uint32_t) (ceilf(log2((float) cell.nof_prb*(cell.nof_prb+1)/2))); riv = riv & ((1<<(b+1))-1); } - ra->type2_alloc.riv = riv; - ra->mcs_idx = trunc_mcs; + ul_dci->type2_alloc.riv = riv; + ul_dci->mcs_idx = rar->trunc_mcs; - srslte_ra_type2_from_riv(riv, &ra->type2_alloc.L_crb, &ra->type2_alloc.RB_start, - nof_prb, nof_prb); + srslte_ra_type2_from_riv(riv, &ul_dci->type2_alloc.L_crb, &ul_dci->type2_alloc.RB_start, + cell.nof_prb, cell.nof_prb); + + if (srslte_ra_ul_dci_to_grant(ul_dci, grant, cell, n_rb_ho, N_srs)) { + fprintf(stderr, "Error computing resource allocation\n"); + return SRSLTE_ERROR; + } - srslte_ra_mcs_from_idx_ul(ra->mcs_idx, srslte_ra_nprb_ul(ra, nof_prb), &ra->mcs); + if (SRSLTE_VERBOSE_ISINFO()) { + srslte_ra_pusch_fprint(stdout, ul_dci, cell.nof_prb); + srslte_ra_ul_grant_fprint(stdout, grant); + } return SRSLTE_SUCCESS; } /* Creates the UL PUSCH resource allocation grant from a DCI format 0 message */ -int srslte_dci_msg_to_ra_ul(srslte_dci_msg_t *msg, uint32_t nof_prb, uint32_t n_rb_ho, srslte_ra_pusch_t *ra_ul) +int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg, srslte_cell_t cell, + uint32_t N_srs, uint32_t n_rb_ho, + srslte_ra_ul_dci_t *ul_dci, + srslte_ra_ul_grant_t *grant) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (msg != NULL && - ra_ul != NULL) + srslte_cell_isvalid(&cell) && + grant != NULL) { ret = SRSLTE_ERROR; - bzero(ra_ul, sizeof(srslte_ra_pusch_t)); + bzero(ul_dci, sizeof(srslte_ra_ul_dci_t)); + bzero(grant, sizeof(srslte_ra_ul_dci_t)); - if (srslte_dci_msg_unpack_pusch(msg, ra_ul, nof_prb)) { + if (srslte_dci_msg_unpack_pusch(msg, ul_dci, cell.nof_prb)) { fprintf(stderr, "Can't unpack PDSCH message\n"); return ret; } - if (SRSLTE_VERBOSE_ISINFO()) { - srslte_ra_pusch_fprint(stdout, ra_ul, nof_prb); - } - - if (srslte_ra_ul_alloc(&ra_ul->prb_alloc, ra_ul, n_rb_ho, nof_prb)) { + if (srslte_ra_ul_dci_to_grant(ul_dci, grant, cell, n_rb_ho, N_srs)) { fprintf(stderr, "Error computing resource allocation\n"); return ret; } + if (SRSLTE_VERBOSE_ISINFO()) { + srslte_ra_pusch_fprint(stdout, ul_dci, cell.nof_prb); + srslte_ra_ul_grant_fprint(stdout, grant); + } + ret = SRSLTE_SUCCESS; } return ret; @@ -275,7 +293,7 @@ uint32_t srslte_dci_format_sizeof(srslte_dci_format_t format, uint32_t nof_prb) * * TODO: TPC and cyclic shift for DM RS not implemented */ -int dci_format0_pack(srslte_ra_pusch_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) { +int dci_format0_pack(srslte_ra_ul_dci_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) { /* pack bits */ uint8_t *y = msg->data; @@ -337,7 +355,7 @@ int dci_format0_pack(srslte_ra_pusch_t *data, srslte_dci_msg_t *msg, uint32_t no * * TODO: TPC and cyclic shift for DM RS not implemented */ -int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_pusch_t *data, uint32_t nof_prb) { +int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_ul_dci_t *data, uint32_t nof_prb) { /* pack bits */ uint8_t *y = msg->data; @@ -384,19 +402,6 @@ int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_pusch_t *data, uint32_t // CQI request data->cqi_request = *y++ ? true : false; - // 8.6.2 First paragraph - if (data->mcs_idx <= 28) { - srslte_ra_mcs_from_idx_ul(data->mcs_idx, srslte_ra_nprb_ul(data, nof_prb), &data->mcs); - } else if (data->mcs_idx == 29 && data->cqi_request && srslte_ra_nprb_ul(data, nof_prb) <= 4) { - // 8.6.1 and 8.6.2 36.213 second paragraph - data->mcs.mod = SRSLTE_MOD_QPSK; - data->mcs.tbs = 0; - } else if (data->mcs_idx >= 29) { - // Else leave TBS and use the previously used PUSCH modulation - data->mcs.tbs = 0; - data->rv_idx = data->mcs_idx - 28; - } - return SRSLTE_SUCCESS; } @@ -406,7 +411,7 @@ int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_pusch_t *data, uint32_t * TODO: TPC commands */ -int dci_format1_pack(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) { +int dci_format1_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) { /* pack bits */ uint8_t *y = msg->data; @@ -459,7 +464,7 @@ int dci_format1_pack(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, uint32_t no return SRSLTE_SUCCESS; } -int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t nof_prb) { +int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t nof_prb) { /* pack bits */ uint8_t *y = msg->data; @@ -496,10 +501,6 @@ int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t } /* unpack MCS according to 7.1.7 of 36.213 */ data->mcs_idx = srslte_bit_unpack(&y, 5); - if (srslte_ra_mcs_from_idx_dl(data->mcs_idx, srslte_ra_nprb_dl(data, nof_prb), &data->mcs)) { - fprintf(stderr, "Error getting MCS\n"); - return SRSLTE_ERROR; - } /* harq process number */ data->harq_process = srslte_bit_unpack(&y, 3); @@ -510,6 +511,9 @@ int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t data->rv_idx = srslte_bit_unpack(&y, 2); // TPC not implemented + + data->dci_format = SRSLTE_RA_DCI_FORMAT1; + return SRSLTE_SUCCESS; } @@ -518,7 +522,7 @@ int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t * * TODO: RA procedure initiated by PDCCH, TPC commands */ -int dci_format1As_pack(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb, +int dci_format1As_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb, bool crc_is_crnti) { /* pack bits */ @@ -604,7 +608,7 @@ int dci_format1As_pack(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, uint32_t /* Unpacks DCI format 1A for compact scheduling of PDSCH words according to 36.212 5.3.3.1.3 * */ -int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t nof_prb, +int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t nof_prb, bool crc_is_crnti) { /* pack bits */ @@ -667,14 +671,7 @@ int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_ data->type2_alloc.n_prb1a = *y++; // LSB indicates N_prb_1a for TBS } - uint32_t n_prb; - if (crc_is_crnti) { - n_prb = srslte_ra_nprb_dl(data, nof_prb); - } else { - n_prb = data->type2_alloc.n_prb1a == SRSLTE_RA_TYPE2_NPRB1A_2 ? 2 : 3; - } - data->mcs.tbs = srslte_ra_tbs_from_idx(data->mcs_idx, n_prb); - data->mcs.mod = SRSLTE_MOD_QPSK; + data->dci_format = SRSLTE_RA_DCI_FORMAT1A; return SRSLTE_SUCCESS; } @@ -682,7 +679,7 @@ int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_ /* Format 1C for compact scheduling of PDSCH words * */ -int dci_format1Cs_pack(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) { +int dci_format1Cs_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) { /* pack bits */ uint8_t *y = msg->data; @@ -732,7 +729,7 @@ int dci_format1Cs_pack(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, uint32_t return SRSLTE_SUCCESS; } -int dci_format1Cs_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t nof_prb) { +int dci_format1Cs_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t nof_prb) { uint32_t L_p, RB_p; /* pack bits */ @@ -759,15 +756,15 @@ int dci_format1Cs_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_ data->type2_alloc.riv = riv; data->mcs_idx = srslte_bit_unpack(&y, 5); - data->mcs.tbs = srslte_ra_tbs_from_idx_format1c(data->mcs_idx); - data->mcs.mod = SRSLTE_MOD_QPSK; - + + data->dci_format = SRSLTE_RA_DCI_FORMAT1C; + msg->nof_bits = (y - msg->data); return SRSLTE_SUCCESS; } -int srslte_dci_msg_pack_pdsch(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, srslte_dci_format_t format, +int srslte_dci_msg_pack_pdsch(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, srslte_dci_format_t format, uint32_t nof_prb, bool crc_is_crnti) { switch (format) { case SRSLTE_DCI_FORMAT1: @@ -783,7 +780,7 @@ int srslte_dci_msg_pack_pdsch(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, sr } } -int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t nof_prb, +int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t nof_prb, bool crc_is_crnti) { if (msg->nof_bits == srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, nof_prb)) { return dci_format1_unpack(msg, data, nof_prb); @@ -796,11 +793,11 @@ int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, } } -int srslte_dci_msg_pack_pusch(srslte_ra_pusch_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) { +int srslte_dci_msg_pack_pusch(srslte_ra_ul_dci_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) { return dci_format0_pack(data, msg, nof_prb); } -int srslte_dci_msg_unpack_pusch(srslte_dci_msg_t *msg, srslte_ra_pusch_t *data, uint32_t nof_prb) { +int srslte_dci_msg_unpack_pusch(srslte_dci_msg_t *msg, srslte_ra_ul_dci_t *data, uint32_t nof_prb) { return dci_format0_unpack(msg, data, nof_prb); } diff --git a/srslte/lib/phch/src/harq.c b/srslte/lib/phch/src/harq.c deleted file mode 100644 index 90b2fca4d..000000000 --- a/srslte/lib/phch/src/harq.c +++ /dev/null @@ -1,248 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2014 The srsLTE Developers. See the - * COPYRIGHT file at the top-level directory of this distribution. - * - * \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 Lesser 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 Lesser General Public License for more details. - * - * A copy of the GNU Lesser 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 -#include -#include -#include -#include -#include -#include -#include - -#include "srslte/common/phy_common.h" -#include "srslte/phch/ra.h" -#include "srslte/phch/harq.h" -#include "srslte/fec/turbodecoder.h" -#include "srslte/utils/vector.h" -#include "srslte/utils/debug.h" - - -#define MAX_PDSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12) - -/* Calculate Codeblock Segmentation as in Section 5.1.2 of 36.212 */ -int srslte_harq_codeblock_segmentation(srslte_harq_cbsegm_t *s, uint32_t tbs) { - uint32_t Bp, B, idx1; - int ret; - - if (tbs == 0) { - bzero(s, sizeof(srslte_harq_cbsegm_t)); - ret = SRSLTE_SUCCESS; - } else { - B = tbs + 24; - - /* Calculate CB sizes */ - if (B <= MAX_LONG_CB) { - s->C = 1; - Bp = B; - } else { - s->C = (uint32_t) ceilf((float) B / (MAX_LONG_CB - 24)); - Bp = B + 24 * s->C; - } - ret = srslte_find_cb_index((Bp-1) / s->C + 1); - if (ret != SRSLTE_ERROR) { - idx1 = (uint32_t) ret; - ret = srslte_cb_size(idx1); - if (ret != SRSLTE_ERROR) { - s->K1 = (uint32_t) ret; - if (idx1 > 0) { - ret = srslte_cb_size(idx1 - 1); - } - if (ret != SRSLTE_ERROR) { - if (s->C == 1) { - s->K2 = 0; - s->C2 = 0; - s->C1 = 1; - } else { - s->K2 = (uint32_t) ret; - s->C2 = (s->C * s->K1 - Bp) / (s->K1 - s->K2); - s->C1 = s->C - s->C2; - } - s->F = s->C1 * s->K1 + s->C2 * s->K2 - Bp; - INFO("CB Segmentation: TBS: %d, C=%d, C+=%d K+=%d, C-=%d, K-=%d, F=%d, Bp=%d\n", - tbs, s->C, s->C1, s->K1, s->C2, s->K2, s->F, Bp); - } - } - } - - } - return ret; -} - -int srslte_harq_init(srslte_harq_t *q, srslte_cell_t cell) { - int ret = SRSLTE_ERROR_INVALID_INPUTS; - - if (q != NULL) { - uint32_t i; - bzero(q, sizeof(srslte_harq_t)); - - memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); - - ret = srslte_ra_tbs_from_idx(26, cell.nof_prb); - if (ret != SRSLTE_ERROR) { - q->max_cb = (uint32_t) ret / (MAX_LONG_CB - 24) + 1; - - q->pdsch_w_buff_f = srslte_vec_malloc(sizeof(float*) * q->max_cb); - if (!q->pdsch_w_buff_f) { - perror("malloc"); - return SRSLTE_ERROR; - } - - q->pdsch_w_buff_c = srslte_vec_malloc(sizeof(uint8_t*) * q->max_cb); - if (!q->pdsch_w_buff_c) { - perror("malloc"); - return SRSLTE_ERROR; - } - - // FIXME: Use HARQ buffer limitation based on UE category - q->w_buff_size = cell.nof_prb * MAX_PDSCH_RE(cell.cp) * 6 * 10; - for (i=0;imax_cb;i++) { - q->pdsch_w_buff_f[i] = srslte_vec_malloc(sizeof(float) * q->w_buff_size); - if (!q->pdsch_w_buff_f[i]) { - perror("malloc"); - return SRSLTE_ERROR; - } - q->pdsch_w_buff_c[i] = srslte_vec_malloc(sizeof(uint8_t) * q->w_buff_size); - if (!q->pdsch_w_buff_c[i]) { - perror("malloc"); - return SRSLTE_ERROR; - } - bzero(q->pdsch_w_buff_c[i], sizeof(uint8_t) * q->w_buff_size); - } - ret = SRSLTE_SUCCESS; - } - } - return ret; -} - -void srslte_harq_free(srslte_harq_t *q) { - if (q) { - uint32_t i; - if (q->pdsch_w_buff_f) { - for (i=0;imax_cb;i++) { - if (q->pdsch_w_buff_f[i]) { - free(q->pdsch_w_buff_f[i]); - } - } - free(q->pdsch_w_buff_f); - } - if (q->pdsch_w_buff_c) { - for (i=0;imax_cb;i++) { - if (q->pdsch_w_buff_c[i]) { - free(q->pdsch_w_buff_c[i]); - } - } - free(q->pdsch_w_buff_c); - } - bzero(q, sizeof(srslte_harq_t)); - } -} - -void srslte_harq_reset(srslte_harq_t *q) { - int i; - if (q->pdsch_w_buff_f) { - for (i=0;imax_cb;i++) { - if (q->pdsch_w_buff_f[i]) { - bzero(q->pdsch_w_buff_f[i], sizeof(float) * q->w_buff_size); - } - } - } - if (q->pdsch_w_buff_c) { - for (i=0;imax_cb;i++) { - if (q->pdsch_w_buff_c[i]) { - bzero(q->pdsch_w_buff_c[i], sizeof(uint8_t) * q->w_buff_size); - } - } - } - bzero(&q->mcs, sizeof(srslte_ra_mcs_t)); - bzero(&q->cb_segm, sizeof(srslte_harq_cbsegm_t)); - bzero(&q->dl_alloc, sizeof(srslte_ra_dl_alloc_t)); -} - -static int harq_setup_common(srslte_harq_t *q, srslte_ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx) { - if (mcs.tbs != q->mcs.tbs) { - srslte_harq_codeblock_segmentation(&q->cb_segm, mcs.tbs); - if (q->cb_segm.C > q->max_cb) { - fprintf(stderr, "Codeblock segmentation returned more CBs (%d) than allocated (%d)\n", - q->cb_segm.C, q->max_cb); - return SRSLTE_ERROR; - } - } - - q->mcs = mcs; - q->sf_idx = sf_idx; - q->rv = rv; - return SRSLTE_SUCCESS; -} - -int srslte_harq_setup_dl(srslte_harq_t *q, srslte_ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, srslte_ra_dl_alloc_t *dl_alloc) { - int ret = SRSLTE_ERROR_INVALID_INPUTS; - - if (q != NULL && - rv < 4 && - sf_idx < 10) - { - ret = harq_setup_common(q, mcs, rv, sf_idx); - if (ret) { - return ret; - } - memcpy(&q->dl_alloc, dl_alloc, sizeof(srslte_ra_dl_alloc_t)); - - // Number of symbols, RE and bits per subframe for DL - q->nof_re = q->dl_alloc.re_sf[q->sf_idx]; - q->nof_symb = 2*SRSLTE_CP_NSYMB(q->cell.cp)-q->dl_alloc.lstart; - q->nof_bits = q->nof_re * srslte_mod_bits_x_symbol(q->mcs.mod); - q->nof_prb = q->dl_alloc.slot[0].nof_prb; - - ret = SRSLTE_SUCCESS; - } - return ret; -} - -int srslte_harq_setup_ul(srslte_harq_t *q, srslte_ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, srslte_ra_ul_alloc_t *ul_alloc) { - int ret = SRSLTE_ERROR_INVALID_INPUTS; - - if (q != NULL && - rv < 4 && - sf_idx < 10) - { - ret = harq_setup_common(q, mcs, rv, sf_idx); - if (ret) { - return ret; - } - memcpy(&q->ul_alloc, ul_alloc, sizeof(srslte_ra_ul_alloc_t)); - - // Number of symbols, RE and bits per subframe for UL - q->nof_symb = 2*(SRSLTE_CP_NSYMB(q->cell.cp)-1); - q->nof_re = q->nof_symb*q->ul_alloc.L_prb*SRSLTE_NRE; - q->nof_bits = q->nof_re * srslte_mod_bits_x_symbol(q->mcs.mod); - q->nof_prb = q->ul_alloc.L_prb; - - ret = SRSLTE_SUCCESS; - } - return ret; -} diff --git a/srslte/lib/phch/src/pdsch.c b/srslte/lib/phch/src/pdsch.c index 47a497205..871ec8911 100644 --- a/srslte/lib/phch/src/pdsch.c +++ b/srslte/lib/phch/src/pdsch.c @@ -36,6 +36,7 @@ #include "prb_dl.h" #include "srslte/phch/pdsch.h" +#include "srslte/phch/sch.h" #include "srslte/common/phy_common.h" #include "srslte/utils/bit.h" #include "srslte/utils/debug.h" @@ -58,7 +59,7 @@ extern int indices_ptr; #endif -int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_alloc_t *prb_alloc, +int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_grant_t *grant, uint32_t nsubframe, bool put) { uint32_t s, n, l, lp, lstart, lend, nof_refs; bool is_pbch, is_sss; @@ -66,7 +67,7 @@ int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_a uint32_t offset = 0; INFO("%s %d RE from %d PRB\n", put ? "Putting" : "Getting", - prb_alloc->re_sf[nsubframe], prb_alloc->slot[0].nof_prb); + grant->nof_re, grant->nof_prb); #ifdef DEBUG_IDX indices_ptr = 0; @@ -88,9 +89,9 @@ int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_a for (n = 0; n < q->cell.nof_prb; n++) { // If this PRB is assigned - if (prb_alloc->slot[s].prb_idx[n]) { + if (grant->prb_idx[s][n]) { if (s == 0) { - lstart = prb_alloc->lstart; + lstart = grant->lstart; } else { lstart = 0; } @@ -179,8 +180,8 @@ int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_a * 36.211 10.3 section 6.3.5 */ int srslte_pdsch_put(srslte_pdsch_t *q, cf_t *symbols, cf_t *sf_symbols, - srslte_ra_dl_alloc_t *prb_alloc, uint32_t subframe) { - return srslte_pdsch_cp(q, symbols, sf_symbols, prb_alloc, subframe, true); + srslte_ra_dl_grant_t *grant, uint32_t subframe) { + return srslte_pdsch_cp(q, symbols, sf_symbols, grant, subframe, true); } /** @@ -191,8 +192,8 @@ int srslte_pdsch_put(srslte_pdsch_t *q, cf_t *symbols, cf_t *sf_symbols, * 36.211 10.3 section 6.3.5 */ int srslte_pdsch_get(srslte_pdsch_t *q, cf_t *sf_symbols, cf_t *symbols, - srslte_ra_dl_alloc_t *prb_alloc, uint32_t subframe) { - return srslte_pdsch_cp(q, sf_symbols, symbols, prb_alloc, subframe, false); + srslte_ra_dl_grant_t *grant, uint32_t subframe) { + return srslte_pdsch_cp(q, sf_symbols, symbols, grant, subframe, false); } /** Initializes the PDCCH transmitter and receiver */ @@ -318,14 +319,18 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) { return SRSLTE_SUCCESS; } -int srslte_pdsch_decode(srslte_pdsch_t *q, srslte_harq_t *harq, cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate, uint8_t *data) { +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, + uint8_t *data) +{ if (q != NULL && sf_symbols != NULL && data != NULL && - harq != NULL) + cfg != NULL) { if (q->rnti_is_set) { - return srslte_pdsch_decode_rnti(q, harq, sf_symbols, ce, noise_estimate, q->rnti, data); + return srslte_pdsch_decode_rnti(q, cfg, softbuffer, sf_symbols, ce, noise_estimate, q->rnti, data); } else { fprintf(stderr, "Must call srslte_pdsch_set_rnti() before calling srslte_pdsch_decode()\n"); return SRSLTE_ERROR; @@ -337,22 +342,30 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, srslte_harq_t *harq, cf_t *sf_symbols /** Decodes the PDSCH from the received symbols */ -int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], - float noise_estimate, uint16_t rnti, uint8_t *data) +int srslte_pdsch_decode_rnti(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, + uint16_t rnti, uint8_t *data) { /* Set pointers for layermapping & precoding */ uint32_t i, n; cf_t *x[SRSLTE_MAX_LAYERS]; - if (q != NULL && - sf_symbols != NULL && - data != NULL && - harq != NULL) + if (q != NULL && + sf_symbols != NULL && + data != NULL && + cfg != NULL) { INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", - harq->sf_idx, rnti, srslte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv); + cfg->sf_idx, rnti, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->grant.nof_re, + cfg->grant.nof_bits, cfg->rv); + + if (cfg->grant.mcs.tbs > cfg->grant.nof_bits) { + fprintf(stderr, "Invalid code rate %d/%d=%.2f\n", cfg->grant.mcs.tbs, cfg->grant.nof_bits, (float) cfg->grant.mcs.tbs / cfg->grant.nof_bits); + return SRSLTE_ERROR_INVALID_INPUTS; + } /* number of layers equals number of ports */ for (i = 0; i < q->cell.nof_ports; i++) { @@ -361,17 +374,17 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, cf_t *sf_sy memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports)); /* extract symbols */ - n = srslte_pdsch_get(q, sf_symbols, q->symbols[0], &harq->dl_alloc, harq->sf_idx); - if (n != harq->nof_re) { - fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); + n = srslte_pdsch_get(q, sf_symbols, q->symbols[0], &cfg->grant, cfg->sf_idx); + if (n != cfg->grant.nof_re) { + fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->grant.nof_re, n); return SRSLTE_ERROR; } /* extract channel estimates */ for (i = 0; i < q->cell.nof_ports; i++) { - n = srslte_pdsch_get(q, ce[i], q->ce[i], &harq->dl_alloc, harq->sf_idx); - if (n != harq->nof_re) { - fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); + n = srslte_pdsch_get(q, ce[i], q->ce[i], &cfg->grant, cfg->sf_idx); + if (n != cfg->grant.nof_re) { + fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->grant.nof_re, n); return SRSLTE_ERROR; } } @@ -380,12 +393,12 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, cf_t *sf_sy if (q->cell.nof_ports == 1) { /* no need for layer demapping */ srslte_predecoding_single(&q->precoding, q->symbols[0], q->ce[0], q->d, - harq->nof_re, noise_estimate); + cfg->grant.nof_re, noise_estimate); } else { srslte_predecoding_diversity(&q->precoding, q->symbols[0], q->ce, x, q->cell.nof_ports, - harq->nof_re, noise_estimate); + cfg->grant.nof_re, noise_estimate); srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, - harq->nof_re / q->cell.nof_ports); + cfg->grant.nof_re / q->cell.nof_ports); } /* demodulate symbols @@ -393,36 +406,38 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, cf_t *sf_sy * thus we don't need tot set it in the LLRs normalization */ srslte_demod_soft_sigma_set(&q->demod, sqrt(0.5)); - srslte_demod_soft_table_set(&q->demod, &q->mod[harq->mcs.mod]); - srslte_demod_soft_demodulate(&q->demod, q->d, q->e, harq->nof_re); + srslte_demod_soft_table_set(&q->demod, &q->mod[cfg->grant.mcs.mod]); + srslte_demod_soft_demodulate(&q->demod, q->d, q->e, cfg->grant.nof_re); /* descramble */ if (rnti != q->rnti) { srslte_sequence_t seq; - if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * harq->sf_idx, q->cell.id, harq->nof_bits)) { + if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->grant.nof_bits)) { return SRSLTE_ERROR; } - srslte_scrambling_f_offset(&seq, q->e, 0, harq->nof_bits); + srslte_scrambling_f_offset(&seq, q->e, 0, cfg->grant.nof_bits); srslte_sequence_free(&seq); } else { - srslte_scrambling_f_offset(&q->seq[harq->sf_idx], q->e, 0, harq->nof_bits); + srslte_scrambling_f_offset(&q->seq[cfg->sf_idx], q->e, 0, cfg->grant.nof_bits); } - return srslte_dlsch_decode(&q->dl_sch, harq, q->e, data); + return srslte_dlsch_decode(&q->dl_sch, cfg, softbuffer, q->e, data); } else { return SRSLTE_ERROR_INVALID_INPUTS; } } -int srslte_pdsch_encode(srslte_pdsch_t *q, srslte_harq_t *harq, uint8_t *data, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) +int srslte_pdsch_encode(srslte_pdsch_t *q, + srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) { - if (q != NULL && - data != NULL && - harq != NULL) + if (q != NULL && + data != NULL && + cfg != NULL) { if (q->rnti_is_set) { - return srslte_pdsch_encode_rnti(q, harq, data, q->rnti, sf_symbols); + return srslte_pdsch_encode_rnti(q, cfg, softbuffer, data, q->rnti, sf_symbols); } else { fprintf(stderr, "Must call srslte_pdsch_set_rnti() to set the encoder/decoder RNTI\n"); return SRSLTE_ERROR; @@ -434,7 +449,9 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, srslte_harq_t *harq, uint8_t *data, c /** Converts the PDSCH data bits to symbols mapped to the slot ready for transmission */ -int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, uint8_t *data, uint16_t rnti, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) +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]) { int i; /* Set pointers for layermapping & precoding */ @@ -443,7 +460,7 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, uint8_t *da if (q != NULL && data != NULL && - harq != NULL) + cfg != NULL) { for (i=0;icell.nof_ports;i++) { @@ -452,24 +469,25 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, uint8_t *da } } - if (harq->mcs.tbs == 0) { + if (cfg->grant.mcs.tbs == 0) { return SRSLTE_ERROR_INVALID_INPUTS; } - if (harq->mcs.tbs > harq->nof_bits) { - fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->nof_bits); + if (cfg->grant.mcs.tbs > cfg->grant.nof_bits) { + fprintf(stderr, "Invalid code rate %d/%d=%.2f\n", cfg->grant.mcs.tbs, cfg->grant.nof_bits, (float) cfg->grant.mcs.tbs / cfg->grant.nof_bits); return SRSLTE_ERROR_INVALID_INPUTS; } - if (harq->nof_re > q->max_re) { + if (cfg->grant.nof_re > q->max_re) { fprintf(stderr, "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", - harq->nof_re, q->max_re, q->cell.nof_prb); + cfg->grant.nof_re, q->max_re, q->cell.nof_prb); return SRSLTE_ERROR_INVALID_INPUTS; } INFO("Encoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", - harq->sf_idx, srslte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv); + cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, + cfg->grant.nof_re, cfg->grant.nof_bits, cfg->rv); /* number of layers equals number of ports */ for (i = 0; i < q->cell.nof_ports; i++) { @@ -477,36 +495,36 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, uint8_t *da } memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports)); - if (srslte_dlsch_encode(&q->dl_sch, harq, data, q->e)) { + if (srslte_dlsch_encode(&q->dl_sch, cfg, softbuffer, data, q->e)) { fprintf(stderr, "Error encoding TB\n"); return SRSLTE_ERROR; } if (rnti != q->rnti) { srslte_sequence_t seq; - if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * harq->sf_idx, q->cell.id, harq->nof_bits)) { + if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->grant.nof_bits)) { return SRSLTE_ERROR; } - srslte_scrambling_b_offset(&seq, (uint8_t*) q->e, 0, harq->nof_bits); + srslte_scrambling_b_offset(&seq, (uint8_t*) q->e, 0, cfg->grant.nof_bits); srslte_sequence_free(&seq); } else { - srslte_scrambling_b_offset(&q->seq[harq->sf_idx], (uint8_t*) q->e, 0, harq->nof_bits); + srslte_scrambling_b_offset(&q->seq[cfg->sf_idx], (uint8_t*) q->e, 0, cfg->grant.nof_bits); } - srslte_mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->e, q->d, harq->nof_bits); + srslte_mod_modulate(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->grant.nof_bits); /* TODO: only diversity supported */ if (q->cell.nof_ports > 1) { - srslte_layermap_diversity(q->d, x, q->cell.nof_ports, harq->nof_re); + srslte_layermap_diversity(q->d, x, q->cell.nof_ports, cfg->grant.nof_re); srslte_precoding_diversity(&q->precoding, x, q->symbols, q->cell.nof_ports, - harq->nof_re / q->cell.nof_ports); + cfg->grant.nof_re / q->cell.nof_ports); } else { - memcpy(q->symbols[0], q->d, harq->nof_re * sizeof(cf_t)); + memcpy(q->symbols[0], q->d, cfg->grant.nof_re * sizeof(cf_t)); } /* mapping to resource elements */ for (i = 0; i < q->cell.nof_ports; i++) { - srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &harq->dl_alloc, harq->sf_idx); + srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &cfg->grant, cfg->sf_idx); } ret = SRSLTE_SUCCESS; } diff --git a/srslte/lib/phch/src/pusch.c b/srslte/lib/phch/src/pusch.c index 7ac183d39..cedf11d07 100644 --- a/srslte/lib/phch/src/pusch.c +++ b/srslte/lib/phch/src/pusch.c @@ -35,6 +35,7 @@ #include #include "srslte/phch/pusch.h" +#include "srslte/phch/pusch_cfg.h" #include "srslte/phch/uci.h" #include "srslte/common/phy_common.h" #include "srslte/utils/bit.h" @@ -83,7 +84,7 @@ static int f_m(srslte_pusch_t *q, srslte_pusch_hopping_cfg_t *hopping, uint32_t } } -int pusch_cp(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output, bool advance_input) +int pusch_cp(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant, uint32_t sf_idx, cf_t *input, cf_t *output, bool advance_input) { cf_t *in_ptr = input; cf_t *out_ptr = output; @@ -93,27 +94,27 @@ int pusch_cp(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output, if (SRSLTE_CP_ISEXT(q->cell.cp)) { L_ref = 2; } - INFO("PUSCH Freq hopping: %d\n", harq->ul_alloc.freq_hopping); + INFO("PUSCH Freq hopping: %d\n", grant->freq_hopping); for (uint32_t slot=0;slot<2;slot++) { - uint32_t n_prb_tilde = harq->ul_alloc.n_prb[slot]; - if (harq->ul_alloc.freq_hopping == 1) { + uint32_t n_prb_tilde = grant->n_prb[slot]; + if (grant->freq_hopping == 1) { if (hopping->hop_mode == SRSLTE_PUSCH_HOP_MODE_INTER_SF) { - n_prb_tilde = harq->ul_alloc.n_prb[hopping->current_tx_nb%2]; + n_prb_tilde = grant->n_prb[hopping->current_tx_nb%2]; } else { - n_prb_tilde = harq->ul_alloc.n_prb[slot]; + n_prb_tilde = grant->n_prb[slot]; } } - if (harq->ul_alloc.freq_hopping == 2) { + if (grant->freq_hopping == 2) { /* Freq hopping type 2 as defined in 5.3.4 of 36.211 */ - uint32_t n_vrb_tilde = harq->ul_alloc.n_prb[0]; + uint32_t n_vrb_tilde = grant->n_prb[0]; if (hopping->n_sb > 1) { n_vrb_tilde -= (hopping->hopping_offset-1)/2+1; } int i=0; if (hopping->hop_mode == SRSLTE_PUSCH_HOP_MODE_INTER_SF) { - i = harq->sf_idx; + i = sf_idx; } else { - i = 2*harq->sf_idx+slot; + i = 2*sf_idx+slot; } uint32_t n_rb_sb = q->cell.nof_prb; if (hopping->n_sb > 1) { @@ -129,8 +130,8 @@ int pusch_cp(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output, } } - harq->ul_alloc.n_prb_tilde[slot] = n_prb_tilde; - INFO("Allocating PUSCH %d PRB to index %d at slot %d\n",harq->ul_alloc.L_prb, n_prb_tilde,slot); + grant->n_prb_tilde[slot] = n_prb_tilde; + INFO("Allocating PUSCH %d PRB to index %d at slot %d\n",grant->L_prb, n_prb_tilde,slot); for (uint32_t l=0;lcell.cp);l++) { if (l != L_ref) { uint32_t idx = SRSLTE_RE_IDX(q->cell.nof_prb, l+slot*SRSLTE_CP_NSYMB(q->cell.cp), @@ -140,24 +141,24 @@ int pusch_cp(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output, } else { in_ptr = &input[idx]; } - memcpy(out_ptr, in_ptr, harq->ul_alloc.L_prb * SRSLTE_NRE * sizeof(cf_t)); + memcpy(out_ptr, in_ptr, grant->L_prb * SRSLTE_NRE * sizeof(cf_t)); if (advance_input) { - in_ptr += harq->ul_alloc.L_prb*SRSLTE_NRE; + in_ptr += grant->L_prb*SRSLTE_NRE; } else { - out_ptr += harq->ul_alloc.L_prb*SRSLTE_NRE; + out_ptr += grant->L_prb*SRSLTE_NRE; } } } } - return SRSLTE_NRE*harq->ul_alloc.L_prb; + return SRSLTE_NRE*grant->L_prb; } -int pusch_put(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output) { - return pusch_cp(q, harq, input, output, true); +int pusch_put(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant, uint32_t sf_idx, cf_t *input, cf_t *output) { + return pusch_cp(q, grant, sf_idx, input, output, true); } -int get(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output) { - return pusch_cp(q, harq, input, output, false); +int pusch_get(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant, uint32_t sf_idx, cf_t *input, cf_t *output) { + return pusch_cp(q, grant, sf_idx, input, output, false); } @@ -306,53 +307,57 @@ int srslte_pusch_set_rnti(srslte_pusch_t *q, uint16_t rnti) { /** Decodes the PUSCH from the received symbols */ -int srslte_pusch_decode(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *sf_symbols, cf_t *ce, float noise_estimate, uint8_t *data) +int srslte_pusch_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) { uint32_t n; - if (q != NULL && - sf_symbols != NULL && - data != NULL && - harq != NULL) + if (q != NULL && + sf_symbols != NULL && + data != NULL && + cfg != NULL) { if (q->rnti_is_set) { INFO("Decoding PUSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", - harq->sf_idx, srslte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv); + cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, + cfg->grant.nof_re, cfg->grant.nof_bits, cfg->rv); /* extract symbols */ - n = get(q, harq, sf_symbols, q->d); - if (n != harq->nof_re) { - fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); + n = pusch_get(q, &cfg->grant, cfg->sf_idx, sf_symbols, q->d); + if (n != cfg->grant.nof_re) { + fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->grant.nof_re, n); return SRSLTE_ERROR; } /* extract channel estimates */ - n = get(q, harq, ce, q->ce); - if (n != harq->nof_re) { - fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); + n = pusch_get(q, &cfg->grant, cfg->sf_idx, ce, q->ce); + if (n != cfg->grant.nof_re) { + fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->grant.nof_re, n); return SRSLTE_ERROR; } srslte_predecoding_single(&q->equalizer, q->d, q->ce, q->z, - harq->nof_re, noise_estimate); + cfg->grant.nof_re, noise_estimate); - srslte_dft_predecoding(&q->dft_precoding, q->z, q->d, - harq->ul_alloc.L_prb, harq->nof_symb); + srslte_dft_predecoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->grant.nof_symb); /* demodulate symbols * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, * thus we don't need tot set it in the LLRs normalization */ srslte_demod_soft_sigma_set(&q->demod, sqrt(0.5)); - srslte_demod_soft_table_set(&q->demod, &q->mod[harq->mcs.mod]); - srslte_demod_soft_demodulate(&q->demod, q->d, q->q, harq->nof_re); + srslte_demod_soft_table_set(&q->demod, &q->mod[cfg->grant.mcs.mod]); + srslte_demod_soft_demodulate(&q->demod, q->d, q->q, cfg->grant.nof_re); /* descramble */ - srslte_scrambling_f_offset(&q->seq[harq->sf_idx], q->q, 0, harq->nof_bits); + srslte_scrambling_f_offset(&q->seq[cfg->sf_idx], q->q, 0, cfg->grant.nof_bits); - return srslte_ulsch_decode(&q->dl_sch, harq, q->q, data); + return srslte_ulsch_decode(&q->dl_sch, cfg, softbuffer, q->q, data); } else { fprintf(stderr, "Must call srslte_pusch_set_rnti() before calling srslte_pusch_decode()\n"); return SRSLTE_ERROR; @@ -362,29 +367,34 @@ int srslte_pusch_decode(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *sf_symbols } } -int srslte_pusch_encode_rnti(srslte_pusch_t *q, srslte_harq_t *harq_process, uint8_t *data, uint16_t rnti, cf_t *sf_symbols) +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) { srslte_uci_data_t uci_data; bzero(&uci_data, sizeof(srslte_uci_data_t)); - return srslte_pusch_uci_encode_rnti(q, harq_process, data, uci_data, rnti, sf_symbols); + return srslte_pusch_uci_encode_rnti(q, cfg, softbuffer, data, uci_data, rnti, sf_symbols); } -int srslte_pusch_encode(srslte_pusch_t *q, srslte_harq_t *harq_process, uint8_t *data, cf_t *sf_symbols) +int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, cf_t *sf_symbols) { if (q->rnti_is_set) { srslte_uci_data_t uci_data; bzero(&uci_data, sizeof(srslte_uci_data_t)); - return srslte_pusch_uci_encode_rnti(q, harq_process, data, uci_data, q->rnti, sf_symbols); + return srslte_pusch_uci_encode_rnti(q, cfg, softbuffer, data, uci_data, q->rnti, sf_symbols); } else { fprintf(stderr, "Must call srslte_pusch_set_rnti() to set the encoder/decoder RNTI\n"); return SRSLTE_ERROR; } } -int srslte_pusch_uci_encode(srslte_pusch_t *q, srslte_harq_t *harq, uint8_t *data, srslte_uci_data_t uci_data, cf_t *sf_symbols) +int srslte_pusch_uci_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, srslte_uci_data_t uci_data, + cf_t *sf_symbols) { if (q->rnti_is_set) { - return srslte_pusch_uci_encode_rnti(q, harq, data, uci_data, q->rnti, sf_symbols); + return srslte_pusch_uci_encode_rnti(q, cfg, softbuffer, data, uci_data, q->rnti, sf_symbols); } else { fprintf(stderr, "Must call srslte_pusch_set_rnti() to set the encoder/decoder RNTI\n"); return SRSLTE_ERROR; @@ -393,52 +403,54 @@ int srslte_pusch_uci_encode(srslte_pusch_t *q, srslte_harq_t *harq, uint8_t *dat /** Converts the PUSCH data bits to symbols mapped to the slot ready for transmission */ -int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_harq_t *harq, uint8_t *data, srslte_uci_data_t uci_data, uint16_t rnti, cf_t *sf_symbols) +int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, srslte_uci_data_t uci_data, uint16_t rnti, + cf_t *sf_symbols) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && data != NULL && - harq != NULL) + cfg != NULL) { - if (harq->mcs.tbs > harq->nof_bits) { - fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->nof_bits); + if (cfg->grant.mcs.tbs > cfg->grant.nof_bits) { + fprintf(stderr, "Invalid code rate %.2f\n", (float) cfg->grant.mcs.tbs / cfg->grant.nof_bits); return SRSLTE_ERROR_INVALID_INPUTS; } - if (harq->nof_re > q->max_re) { + if (cfg->grant.nof_re > q->max_re) { fprintf(stderr, "Error too many RE per subframe (%d). PUSCH configured for %d RE (%d PRB)\n", - harq->nof_re, q->max_re, q->cell.nof_prb); + cfg->grant.nof_re, q->max_re, q->cell.nof_prb); return SRSLTE_ERROR_INVALID_INPUTS; } INFO("Encoding PUSCH SF: %d, Mod %s, RNTI: %d, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", - harq->sf_idx, srslte_mod_string(harq->mcs.mod), rnti, harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv); + cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), rnti, + cfg->grant.mcs.tbs, cfg->grant.nof_re, cfg->grant.nof_bits, cfg->rv); - bzero(q->q, harq->nof_bits); - if (srslte_ulsch_uci_encode(&q->dl_sch, harq, data, uci_data, q->g, q->q)) { + bzero(q->q, cfg->grant.nof_bits); + if (srslte_ulsch_uci_encode(&q->dl_sch, cfg, softbuffer, data, uci_data, q->g, q->q)) { fprintf(stderr, "Error encoding TB\n"); return SRSLTE_ERROR; } if (rnti != q->rnti) { srslte_sequence_t seq; - if (srslte_sequence_pusch(&seq, rnti, 2 * harq->sf_idx, q->cell.id, harq->nof_bits)) { + if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->grant.nof_bits)) { return SRSLTE_ERROR; } - srslte_scrambling_b_offset_pusch(&seq, (uint8_t*) q->q, 0, harq->nof_bits); + srslte_scrambling_b_offset_pusch(&seq, (uint8_t*) q->q, 0, cfg->grant.nof_bits); srslte_sequence_free(&seq); } else { - srslte_scrambling_b_offset_pusch(&q->seq[harq->sf_idx], (uint8_t*) q->q, 0, harq->nof_bits); + srslte_scrambling_b_offset_pusch(&q->seq[cfg->sf_idx], (uint8_t*) q->q, 0, cfg->grant.nof_bits); } - srslte_mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->q, q->d, harq->nof_bits); + srslte_mod_modulate(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->q, q->d, cfg->grant.nof_bits); - srslte_dft_precoding(&q->dft_precoding, q->d, q->z, - harq->ul_alloc.L_prb, harq->nof_symb); + srslte_dft_precoding(&q->dft_precoding, q->d, q->z, cfg->grant.L_prb, cfg->grant.nof_symb); /* mapping to resource elements */ - pusch_put(q, harq, q->z, sf_symbols); + pusch_put(q, &cfg->grant, cfg->sf_idx, q->z, sf_symbols); ret = SRSLTE_SUCCESS; } diff --git a/srslte/lib/phch/src/ra.c b/srslte/lib/phch/src/ra.c index f42a18b82..ffd4614a5 100644 --- a/srslte/lib/phch/src/ra.c +++ b/srslte/lib/phch/src/ra.c @@ -108,44 +108,30 @@ uint32_t ra_re_x_prb(uint32_t subframe, uint32_t slot, uint32_t prb_idx, uint32_ return re; } -void srslte_ra_prb_fprint(FILE *f, srslte_ra_prb_slot_t *prb, uint32_t nof_prb) { - int i; - if (prb->nof_prb > 0) { - for (i=0;iprb_idx[i]) { - fprintf(f, "%d, ", i); - } - } - fprintf(f, "\n"); - } - -} - -/** Compute PRB allocation for Uplink as defined in 8.1 and 8.4 of 36.213 */ -int srslte_ra_ul_alloc(srslte_ra_ul_alloc_t *prb_dist, srslte_ra_pusch_t *ra, uint32_t n_rb_ho, uint32_t nof_prb) { - - bzero(prb_dist, sizeof(srslte_ra_ul_alloc_t)); - prb_dist->L_prb = ra->type2_alloc.L_crb; - uint32_t n_prb_1 = ra->type2_alloc.RB_start; +int srslte_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, + uint32_t n_rb_ho, uint32_t nof_prb) { + bzero(grant, sizeof(srslte_ra_ul_grant_t)); + grant->L_prb = dci->type2_alloc.L_crb; + uint32_t n_prb_1 = dci->type2_alloc.RB_start; uint32_t n_rb_pusch = 0; if (n_rb_ho%2) { n_rb_ho++; } - - if (ra->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED || ra->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_TYPE2) { + + if (dci->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED || dci->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_TYPE2) { /* For no freq hopping or type2 freq hopping, n_prb is the same * n_prb_tilde is calculated during resource mapping */ for (uint32_t i=0;i<2;i++) { - prb_dist->n_prb[i] = n_prb_1; + grant->n_prb[i] = n_prb_1; } - if (ra->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED) { - prb_dist->freq_hopping = 0; + if (dci->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED) { + grant->freq_hopping = 0; } else { - prb_dist->freq_hopping = 2; + grant->freq_hopping = 2; } - INFO("prb1: %d, prb2: %d, L: %d\n", prb_dist->n_prb[0], prb_dist->n_prb[1], prb_dist->L_prb); + INFO("prb1: %d, prb2: %d, L: %d\n", grant->n_prb[0], grant->n_prb[1], grant->L_prb); } else { /* Type1 frequency hopping as defined in 8.4.1 of 36.213 * frequency offset between 1st and 2nd slot is fixed. @@ -153,108 +139,166 @@ int srslte_ra_ul_alloc(srslte_ra_ul_alloc_t *prb_dist, srslte_ra_pusch_t *ra, ui n_rb_pusch = nof_prb - n_rb_ho - (nof_prb%2); // starting prb idx for slot 0 is as given by resource grant - prb_dist->n_prb[0] = n_prb_1; + grant->n_prb[0] = n_prb_1; if (n_prb_1 < n_rb_ho/2) { fprintf(stderr, "Invalid Frequency Hopping parameters. Offset: %d, n_prb_1: %d\n", n_rb_ho, n_prb_1); } uint32_t n_prb_1_tilde = n_prb_1; // prb idx for slot 1 - switch(ra->freq_hop_fl) { + switch(dci->freq_hop_fl) { case SRSLTE_RA_PUSCH_HOP_QUART: - prb_dist->n_prb[1] = (n_rb_pusch/4+ n_prb_1_tilde)%n_rb_pusch; + grant->n_prb[1] = (n_rb_pusch/4+ n_prb_1_tilde)%n_rb_pusch; break; case SRSLTE_RA_PUSCH_HOP_QUART_NEG: if (n_prb_1 < n_rb_pusch/4) { - prb_dist->n_prb[1] = (n_rb_pusch+ n_prb_1_tilde -n_rb_pusch/4); + grant->n_prb[1] = (n_rb_pusch+ n_prb_1_tilde -n_rb_pusch/4); } else { - prb_dist->n_prb[1] = (n_prb_1_tilde -n_rb_pusch/4); + grant->n_prb[1] = (n_prb_1_tilde -n_rb_pusch/4); } break; case SRSLTE_RA_PUSCH_HOP_HALF: - prb_dist->n_prb[1] = (n_rb_pusch/2+ n_prb_1_tilde)%n_rb_pusch; + grant->n_prb[1] = (n_rb_pusch/2+ n_prb_1_tilde)%n_rb_pusch; break; default: break; } - INFO("n_rb_pusch: %d, prb1: %d, prb2: %d, L: %d\n", n_rb_pusch, prb_dist->n_prb[0], prb_dist->n_prb[1], prb_dist->L_prb); - prb_dist->freq_hopping = 1; + INFO("n_rb_pusch: %d, prb1: %d, prb2: %d, L: %d\n", n_rb_pusch, grant->n_prb[0], grant->n_prb[1], grant->L_prb); + grant->freq_hopping = 1; + } + return SRSLTE_SUCCESS; +} + +static int ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant) { + // 8.6.2 First paragraph + if (dci->mcs_idx <= 28) { + /* Table 8.6.1-1 on 36.213 */ + if (dci->mcs_idx < 11) { + grant->mcs.mod = SRSLTE_MOD_QPSK; + grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->L_prb); + } else if (dci->mcs_idx < 21) { + grant->mcs.mod = SRSLTE_MOD_16QAM; + grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx - 1, grant->L_prb); + } else if (dci->mcs_idx < 29) { + grant->mcs.mod = SRSLTE_MOD_64QAM; + grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx - 2, grant->L_prb); + } else { + fprintf(stderr, "Invalid MCS index %d\n", dci->mcs_idx); + return SRSLTE_ERROR; + } + } else if (dci->mcs_idx == 29 && dci->cqi_request && grant->L_prb <= 4) { + // 8.6.1 and 8.6.2 36.213 second paragraph + grant->mcs.mod = SRSLTE_MOD_QPSK; + grant->mcs.tbs = 0; + } else if (dci->mcs_idx >= 29) { + // Else use last TBS/Modulation and use mcs to obtain rv_idx + grant->mcs.tbs = 0; + grant->mcs.mod = 0; + dci->rv_idx = dci->mcs_idx - 28; + } + return SRSLTE_SUCCESS; +} + +/** Compute PRB allocation for Uplink as defined in 8.1 and 8.4 of 36.213 */ +int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, srslte_cell_t cell, + uint32_t n_rb_ho, uint32_t N_srs) +{ + + // Compute PRB allocation + if (!srslte_ul_dci_to_grant_prb_allocation(dci, grant, n_rb_ho, cell.nof_prb)) { + + // Compute MCS + if (!ul_dci_to_grant_mcs(dci, grant)) { + + // Fill rest of grant structure + grant->lstart = 0; + grant->nof_symb = 2*(SRSLTE_CP_NSYMB(cell.cp)-1) - N_srs; + grant->M_sc = grant->L_prb*SRSLTE_NRE; + grant->M_sc_init = grant->M_sc; // FIXME: What should M_sc_init be? + grant->nof_re = grant->nof_symb*grant->M_sc; + grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod); + grant->nof_bits = grant->nof_re * grant->Qm; + } else { + fprintf(stderr, "Error computing MCS\n"); + return SRSLTE_ERROR; + } + } else { + fprintf(stderr, "Error computing PRB allocation\n"); + return SRSLTE_ERROR; } return SRSLTE_SUCCESS; } /* Computes the number of RE for each PRB in the prb_dist structure */ -void srslte_ra_dl_alloc_re(srslte_ra_dl_alloc_t *prb_dist, uint32_t nof_prb, uint32_t nof_ports, - uint32_t nof_ctrl_symbols, srslte_cp_t cp) { - uint32_t i, j, s; - - /* Set start symbol according to Section 7.1.6.4 in 36.213 */ - prb_dist->lstart = nof_ctrl_symbols; - // Compute number of RE per subframe - for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - prb_dist->re_sf[i] = 0; - for (s = 0; s < 2; s++) { - for (j = 0; j < nof_prb; j++) { - if (prb_dist->slot[s].prb_idx[j]) { - prb_dist->re_sf[i] += ra_re_x_prb(i, s, j, - nof_prb, nof_ports, nof_ctrl_symbols, cp); - } +void srslte_dl_dci_to_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t cell, + uint32_t sf_idx, uint32_t nof_ctrl_symbols) +{ + uint32_t j, s; + + // Compute number of RE per PRB + grant->nof_re = 0; + for (s = 0; s < 2; s++) { + for (j = 0; j < cell.nof_prb; j++) { + if (grant->prb_idx[s][j]) { + grant->nof_re += ra_re_x_prb(sf_idx, s, j, + cell.nof_prb, cell.nof_ports, nof_ctrl_symbols, cell.cp); } } - } + } } + /** Compute PRB allocation for Downlink as defined in 7.1.6 of 36.213 */ -int srslte_ra_dl_alloc(srslte_ra_dl_alloc_t *prb_dist, srslte_ra_pdsch_t *ra, uint32_t nof_prb) { +static int dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, uint32_t nof_prb) { int i, j; uint32_t bitmask; uint32_t P = srslte_ra_type0_P(nof_prb); uint32_t n_rb_rbg_subset, n_rb_type1; - - bzero(prb_dist, sizeof(srslte_ra_dl_alloc_t)); - switch (ra->alloc_type) { + + bzero(grant, sizeof(srslte_ra_dl_grant_t)); + switch (dci->alloc_type) { case SRSLTE_RA_ALLOC_TYPE0: - bitmask = ra->type0_alloc.rbg_bitmask; + bitmask = dci->type0_alloc.rbg_bitmask; int nb = (int) ceilf((float) nof_prb / P); for (i = 0; i < nb; i++) { if (bitmask & (1 << (nb - i - 1))) { for (j = 0; j < P; j++) { if (i*P+j < nof_prb) { - prb_dist->slot[0].prb_idx[i * P + j] = true; - prb_dist->slot[0].nof_prb++; + grant->prb_idx[0][i * P + j] = true; + grant->nof_prb++; } } } } - memcpy(&prb_dist->slot[1], &prb_dist->slot[0], sizeof(srslte_ra_prb_slot_t)); + memcpy(&grant->prb_idx[1], &grant->prb_idx[0], SRSLTE_MAX_PRB*sizeof(bool)); break; case SRSLTE_RA_ALLOC_TYPE1: n_rb_type1 = srslte_ra_type1_N_rb(nof_prb); - if (ra->type1_alloc.rbg_subset < (nof_prb / P) % P) { + if (dci->type1_alloc.rbg_subset < (nof_prb / P) % P) { n_rb_rbg_subset = ((nof_prb - 1) / (P * P)) * P + P; - } else if (ra->type1_alloc.rbg_subset == ((nof_prb / P) % P)) { + } else if (dci->type1_alloc.rbg_subset == ((nof_prb / P) % P)) { n_rb_rbg_subset = ((nof_prb - 1) / (P * P)) * P + ((nof_prb - 1) % P) + 1; } else { n_rb_rbg_subset = ((nof_prb - 1) / (P * P)) * P; } - int shift = ra->type1_alloc.shift ? (n_rb_rbg_subset - n_rb_type1) : 0; - bitmask = ra->type1_alloc.vrb_bitmask; + int shift = dci->type1_alloc.shift ? (n_rb_rbg_subset - n_rb_type1) : 0; + bitmask = dci->type1_alloc.vrb_bitmask; for (i = 0; i < n_rb_type1; i++) { if (bitmask & (1 << (n_rb_type1 - i - 1))) { - prb_dist->slot[0].prb_idx[((i + shift) / P) - * P * P + ra->type1_alloc.rbg_subset * P + (i + shift) % P] = true; - prb_dist->slot[0].nof_prb++; + grant->prb_idx[0][((i + shift) / P) + * P * P + dci->type1_alloc.rbg_subset * P + (i + shift) % P] = true; + grant->nof_prb++; } } - memcpy(&prb_dist->slot[1], &prb_dist->slot[0], sizeof(srslte_ra_prb_slot_t)); + memcpy(&grant->prb_idx[1], &grant->prb_idx[0], SRSLTE_MAX_PRB*sizeof(bool)); break; case SRSLTE_RA_ALLOC_TYPE2: - if (ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { - for (i = 0; i < ra->type2_alloc.L_crb; i++) { - prb_dist->slot[0].prb_idx[i + ra->type2_alloc.RB_start] = true; - prb_dist->slot[0].nof_prb++; + if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { + for (i = 0; i < dci->type2_alloc.L_crb; i++) { + grant->prb_idx[0][i + dci->type2_alloc.RB_start] = true; + grant->nof_prb++; } - memcpy(&prb_dist->slot[1], &prb_dist->slot[0], sizeof(srslte_ra_prb_slot_t)); + memcpy(&grant->prb_idx[1], &grant->prb_idx[0], SRSLTE_MAX_PRB*sizeof(bool)); } else { /* Mapping of Virtual to Physical RB for distributed type is defined in * 6.2.3.2 of 36.211 @@ -262,7 +306,7 @@ int srslte_ra_dl_alloc(srslte_ra_dl_alloc_t *prb_dist, srslte_ra_pdsch_t *ra, ui int N_gap, N_tilde_vrb, n_tilde_vrb, n_tilde_prb, n_tilde2_prb, N_null, N_row, n_vrb; int n_tilde_prb_odd, n_tilde_prb_even; - if (ra->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1) { + if (dci->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1) { N_tilde_vrb = srslte_ra_type2_n_vrb_dl(nof_prb, true); N_gap = srslte_ra_type2_ngap(nof_prb, true); } else { @@ -271,8 +315,8 @@ int srslte_ra_dl_alloc(srslte_ra_dl_alloc_t *prb_dist, srslte_ra_pdsch_t *ra, ui } N_row = (int) ceilf((float) N_tilde_vrb / (4 * P)) * P; N_null = 4 * N_row - N_tilde_vrb; - for (i = 0; i < ra->type2_alloc.L_crb; i++) { - n_vrb = i + ra->type2_alloc.RB_start; + for (i = 0; i < dci->type2_alloc.L_crb; i++) { + n_vrb = i + dci->type2_alloc.RB_start; n_tilde_vrb = n_vrb % N_tilde_vrb; n_tilde_prb = 2 * N_row * (n_tilde_vrb % 2) + n_tilde_vrb / 2 + N_tilde_vrb * (n_vrb / N_tilde_vrb); @@ -295,19 +339,18 @@ int srslte_ra_dl_alloc(srslte_ra_dl_alloc_t *prb_dist, srslte_ra_pdsch_t *ra, ui + N_tilde_vrb * (n_vrb / N_tilde_vrb); if (n_tilde_prb_odd < N_tilde_vrb / 2) { - prb_dist->slot[0].prb_idx[n_tilde_prb_odd] = true; + grant->prb_idx[0][n_tilde_prb_odd] = true; } else { - prb_dist->slot[0].prb_idx[n_tilde_prb_odd + N_gap + grant->prb_idx[0][n_tilde_prb_odd + N_gap - N_tilde_vrb / 2] = true; } - prb_dist->slot[0].nof_prb++; + grant->nof_prb++; if (n_tilde_prb_even < N_tilde_vrb / 2) { - prb_dist->slot[1].prb_idx[n_tilde_prb_even] = true; + grant->prb_idx[1][n_tilde_prb_even] = true; } else { - prb_dist->slot[1].prb_idx[n_tilde_prb_even + N_gap + grant->prb_idx[1][n_tilde_prb_even + N_gap - N_tilde_vrb / 2] = true; } - prb_dist->slot[1].nof_prb++; } } break; @@ -318,46 +361,83 @@ int srslte_ra_dl_alloc(srslte_ra_dl_alloc_t *prb_dist, srslte_ra_pdsch_t *ra, ui return SRSLTE_SUCCESS; } -/* Returns the number of allocated PRB for Uplink */ -uint32_t srslte_ra_nprb_ul(srslte_ra_pusch_t *ra, uint32_t nof_prb) { - return ra->type2_alloc.L_crb; +/* Modulation order and transport block size determination 7.1.7 in 36.213 */ +static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, bool crc_is_crnti) { + uint32_t n_prb; + switch(dci->dci_format) { + case SRSLTE_RA_DCI_FORMAT1: + /* Table 7.1.7.1-1 on 36.213 */ + if (dci->mcs_idx < 10) { + grant->mcs.mod = SRSLTE_MOD_QPSK; + grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->nof_prb); + } else if (dci->mcs_idx < 17) { + grant->mcs.mod = !crc_is_crnti?SRSLTE_MOD_QPSK:SRSLTE_MOD_16QAM; + grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx - 1, grant->nof_prb); + } else if (dci->mcs_idx < 29) { + grant->mcs.mod = !crc_is_crnti?SRSLTE_MOD_QPSK:SRSLTE_MOD_64QAM; + grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx - 2, grant->nof_prb); + } else if (dci->mcs_idx == 29) { + grant->mcs.mod = SRSLTE_MOD_QPSK; + grant->mcs.tbs = 0; + } else if (dci->mcs_idx == 30) { + grant->mcs.mod = !crc_is_crnti?SRSLTE_MOD_QPSK:SRSLTE_MOD_16QAM; + grant->mcs.tbs = 0; + } else if (dci->mcs_idx == 31) { + grant->mcs.mod = !crc_is_crnti?SRSLTE_MOD_QPSK:SRSLTE_MOD_64QAM; + grant->mcs.tbs = 0; + } else { + return SRSLTE_ERROR; + } + break; + case SRSLTE_RA_DCI_FORMAT1A: + /* Downlink Transport Block size determination as defined in 7.1.7.2 on 36.213 */ + if (crc_is_crnti) { + n_prb = grant->nof_prb; + } else { + n_prb = dci->type2_alloc.n_prb1a == SRSLTE_RA_TYPE2_NPRB1A_2 ? 2 : 3; + } + if (dci->mcs_idx < 27 && n_prb > 0 && n_prb <= SRSLTE_MAX_PRB) { + grant->mcs.tbs = tbs_table[dci->mcs_idx][n_prb - 1]; + grant->mcs.mod = SRSLTE_MOD_QPSK; + } else { + return SRSLTE_ERROR; + } + break; + case SRSLTE_RA_DCI_FORMAT1C: + /* Downlink Transport Block size for Format 1C as defined in 7.1.7.2.2-1 on 36.213 */ + if (dci->mcs_idx < 32) { + grant->mcs.tbs = tbs_format1c_table[dci->mcs_idx]; + grant->mcs.mod = SRSLTE_MOD_QPSK; + } else { + return SRSLTE_ERROR; + } + break; + } + return SRSLTE_SUCCESS; } -/* Returns the number of allocated PRB for Downlink */ -uint32_t srslte_ra_nprb_dl(srslte_ra_pdsch_t *ra, uint32_t nof_prb) { - uint32_t nprb; - uint32_t nof_rbg, P; - switch (ra->alloc_type) { - case SRSLTE_RA_ALLOC_TYPE0: - // Get the number of allocated RBG except the last RBG - nof_rbg = srslte_bit_count(ra->type0_alloc.rbg_bitmask & 0xFFFFFFFE); - P = srslte_ra_type0_P(nof_prb); - if (nof_rbg > (uint32_t) ceilf((float) nof_prb / P)) { - nof_rbg = (uint32_t) ceilf((float) nof_prb / P) - 1; - } - nprb = nof_rbg * P; - - // last RBG may have smaller size. Add if set - uint32_t P_last = (nof_prb % P); - if (!P_last) - P_last = P; - nprb += P_last * (ra->type0_alloc.rbg_bitmask & 1); - break; - case SRSLTE_RA_ALLOC_TYPE1: - nprb = srslte_bit_count(ra->type1_alloc.vrb_bitmask); - if (nprb > srslte_ra_type1_N_rb(nof_prb)) { - fprintf(stderr, "Number of RB (%d) can not exceed %d\n", nprb, - srslte_ra_type1_N_rb(nof_prb)); - return SRSLTE_ERROR; +/** Obtains a DL grant from a DCI grant for PDSCH */ +int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, srslte_cell_t cell, + uint32_t sf_idx, uint32_t cfi, bool crc_is_crnti) +{ + // Compute PRB allocation + if (!dl_dci_to_grant_prb_allocation(dci, grant, cell.nof_prb)) { + // Compute number of RE + srslte_dl_dci_to_grant_nof_re(grant, cell, sf_idx, cell.nof_prb<10?(cfi+1):cfi); + // Compute MCS + if (!dl_dci_to_grant_mcs(dci, grant, crc_is_crnti)) { + // Fill rest of grant structure + grant->lstart = cell.nof_prb<10?(cfi+1):cfi; + grant->nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-grant->lstart; + grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod); + grant->nof_bits = grant->nof_re * grant->Qm; + } else { + return SRSLTE_ERROR; } - break; - case SRSLTE_RA_ALLOC_TYPE2: - nprb = ra->type2_alloc.L_crb; - break; - default: - return SRSLTE_ERROR; + } else { + return SRSLTE_ERROR; } - return nprb; + return SRSLTE_SUCCESS; } /* RBG size for type0 scheduling as in table 7.1.6.1-1 of 36.213 */ @@ -443,59 +523,7 @@ uint32_t srslte_ra_type2_n_vrb_dl(uint32_t nof_prb, bool ngap_is_1) { } } -/* Converts MCS index to srslte_ra_mcs_t structure for Downlink as defined inTable 7.1.7.1-1 on 36.213 */ -int srslte_ra_mcs_from_idx_dl(uint32_t mcs_idx, uint32_t nof_prb, srslte_ra_mcs_t *mcs) { - if (mcs_idx < 10) { - mcs->mod = SRSLTE_MOD_QPSK; - mcs->tbs = srslte_ra_tbs_from_idx(mcs_idx, nof_prb); - } else if (mcs_idx < 17) { - mcs->mod = SRSLTE_MOD_16QAM; - mcs->tbs = srslte_ra_tbs_from_idx(mcs_idx - 1, nof_prb); - } else if (mcs_idx < 29) { - mcs->mod = SRSLTE_MOD_64QAM; - mcs->tbs = srslte_ra_tbs_from_idx(mcs_idx - 2, nof_prb); - } else if (mcs_idx == 29) { - mcs->mod = SRSLTE_MOD_QPSK; - mcs->tbs = 0; - } else if (mcs_idx == 30) { - mcs->mod = SRSLTE_MOD_16QAM; - mcs->tbs = 0; - } else if (mcs_idx == 31) { - mcs->mod = SRSLTE_MOD_64QAM; - mcs->tbs = 0; - } else { - return SRSLTE_ERROR; - } - return SRSLTE_SUCCESS; -} - -/* Converts MCS index to srslte_ra_mcs_t structure for Uplink as defined in Table 8.6.1-1 on 36.213 */ -int srslte_ra_mcs_from_idx_ul(uint32_t mcs_idx, uint32_t nof_prb, srslte_ra_mcs_t *mcs) { - if (mcs_idx < 11) { - mcs->mod = SRSLTE_MOD_QPSK; - mcs->tbs = srslte_ra_tbs_from_idx(mcs_idx, nof_prb); - } else if (mcs_idx < 21) { - mcs->mod = SRSLTE_MOD_16QAM; - mcs->tbs = srslte_ra_tbs_from_idx(mcs_idx - 1, nof_prb); - } else if (mcs_idx < 29) { - mcs->mod = SRSLTE_MOD_64QAM; - mcs->tbs = srslte_ra_tbs_from_idx(mcs_idx - 2, nof_prb); - } else { - return SRSLTE_ERROR; - } - return SRSLTE_SUCCESS; -} - -/* Downlink Transport Block size for Format 1C as defined in 7.1.7.2.2-1 on 36.213 */ -int srslte_ra_tbs_from_idx_format1c(uint32_t tbs_idx) { - if (tbs_idx < 32) { - return tbs_format1c_table[tbs_idx]; - } else { - return SRSLTE_ERROR; - } -} - -/* Downlink Transport Block size determination as defined in 7.1.7.2 on 36.213 */ +/* Table 7.1.7.2.1-1: Transport block size table on 36.213 */ int srslte_ra_tbs_from_idx(uint32_t tbs_idx, uint32_t n_prb) { if (tbs_idx < 27 && n_prb > 0 && n_prb <= SRSLTE_MAX_PRB) { return tbs_table[tbs_idx][n_prb - 1]; @@ -523,39 +551,42 @@ int srslte_ra_tbs_to_table_idx(uint32_t tbs, uint32_t n_prb) { return SRSLTE_ERROR; } -void srslte_ra_pusch_fprint(FILE *f, srslte_ra_pusch_t *ra, uint32_t nof_prb) { +void srslte_ra_pusch_fprint(FILE *f, srslte_ra_ul_dci_t *dci, uint32_t nof_prb) { fprintf(f, " - Resource Allocation Type 2 mode :\t%s\n", - ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC ? "Localized" : "Distributed"); + dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC ? "Localized" : "Distributed"); fprintf(f, " + Frequency Hopping:\t\t\t"); - if (ra->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED) { + if (dci->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED) { fprintf(f, "No\n"); } else { fprintf(f, "Yes\n"); } - fprintf(f, " + Resource Indicator Value:\t\t%d\n", ra->type2_alloc.riv); - if (ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { + fprintf(f, " + Resource Indicator Value:\t\t%d\n", dci->type2_alloc.riv); + if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n", - ra->type2_alloc.L_crb, ra->type2_alloc.RB_start); + dci->type2_alloc.L_crb, dci->type2_alloc.RB_start); } else { fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n", - ra->type2_alloc.L_crb, ra->type2_alloc.RB_start); + dci->type2_alloc.L_crb, dci->type2_alloc.RB_start); fprintf(f, " + VRB gap selection:\t\t\tGap %d\n", - ra->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1 ? 1 : 2); + dci->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1 ? 1 : 2); fprintf(f, " + VRB gap:\t\t\t\t%d\n", - srslte_ra_type2_ngap(nof_prb, ra->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1)); + srslte_ra_type2_ngap(nof_prb, dci->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1)); } - fprintf(f, " - Number of PRBs:\t\t\t%d\n", srslte_ra_nprb_ul(ra, nof_prb)); - fprintf(f, " - Modulation and coding scheme index:\t%d\n", ra->mcs_idx); - fprintf(f, " - Modulation type:\t\t\t%s\n", srslte_mod_string(ra->mcs.mod)); - fprintf(f, " - Transport block size:\t\t%d\n", ra->mcs.tbs); - fprintf(f, " - New data indicator:\t\t\t%s\n", ra->ndi ? "Yes" : "No"); - fprintf(f, " - Redundancy version:\t\t\t%d\n", ra->rv_idx); + fprintf(f, " - Modulation and coding scheme index:\t%d\n", dci->mcs_idx); + fprintf(f, " - New data indicator:\t\t\t%s\n", dci->ndi ? "Yes" : "No"); + fprintf(f, " - Redundancy version:\t\t\t%d\n", dci->rv_idx); fprintf(f, " - TPC command for PUCCH:\t\t--\n"); } +void srslte_ra_ul_grant_fprint(FILE *f, srslte_ra_ul_grant_t *grant) { + fprintf(f, " - Number of PRBs:\t\t\t%d\n", grant->L_prb); + fprintf(f, " - Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs.mod)); + fprintf(f, " - Transport block size:\t\t%d\n", grant->mcs.tbs); +} + char *ra_type_string(srslte_ra_type_t alloc_type) { switch (alloc_type) { case SRSLTE_RA_ALLOC_TYPE0: @@ -569,54 +600,65 @@ char *ra_type_string(srslte_ra_type_t alloc_type) { } } - -void srslte_ra_pdsch_fprint(FILE *f, srslte_ra_pdsch_t *ra, uint32_t nof_prb) { +void srslte_ra_pdsch_fprint(FILE *f, srslte_ra_dl_dci_t *dci, uint32_t nof_prb) { fprintf(f, " - Resource Allocation Type:\t\t%s\n", - ra_type_string(ra->alloc_type)); - switch (ra->alloc_type) { + ra_type_string(dci->alloc_type)); + switch (dci->alloc_type) { case SRSLTE_RA_ALLOC_TYPE0: fprintf(f, " + Resource Block Group Size:\t\t%d\n", srslte_ra_type0_P(nof_prb)); - fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n", ra->type0_alloc.rbg_bitmask); + fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n", dci->type0_alloc.rbg_bitmask); break; case SRSLTE_RA_ALLOC_TYPE1: fprintf(f, " + Resource Block Group Size:\t\t%d\n", srslte_ra_type0_P(nof_prb)); - fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n", ra->type1_alloc.vrb_bitmask); - fprintf(f, " + RBG Subset:\t\t\t%d\n", ra->type1_alloc.rbg_subset); + fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n", dci->type1_alloc.vrb_bitmask); + fprintf(f, " + RBG Subset:\t\t\t%d\n", dci->type1_alloc.rbg_subset); fprintf(f, " + RBG Shift:\t\t\t\t%s\n", - ra->type1_alloc.shift ? "Yes" : "No"); + dci->type1_alloc.shift ? "Yes" : "No"); break; case SRSLTE_RA_ALLOC_TYPE2: fprintf(f, " + Type:\t\t\t\t%s\n", - ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC ? "Localized" : "Distributed"); - fprintf(f, " + Resource Indicator Value:\t\t%d\n", ra->type2_alloc.riv); - if (ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { + dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC ? "Localized" : "Distributed"); + fprintf(f, " + Resource Indicator Value:\t\t%d\n", dci->type2_alloc.riv); + if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n", - ra->type2_alloc.L_crb, ra->type2_alloc.RB_start); + dci->type2_alloc.L_crb, dci->type2_alloc.RB_start); } else { fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n", - ra->type2_alloc.L_crb, ra->type2_alloc.RB_start); + dci->type2_alloc.L_crb, dci->type2_alloc.RB_start); fprintf(f, " + VRB gap selection:\t\t\tGap %d\n", - ra->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1 ? 1 : 2); + dci->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1 ? 1 : 2); fprintf(f, " + VRB gap:\t\t\t\t%d\n", - srslte_ra_type2_ngap(nof_prb, ra->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1)); + srslte_ra_type2_ngap(nof_prb, dci->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1)); } break; } + fprintf(f, " - Modulation and coding scheme index:\t%d\n", dci->mcs_idx); + fprintf(f, " - HARQ process:\t\t\t%d\n", dci->harq_process); + fprintf(f, " - New data indicator:\t\t\t%s\n", dci->ndi ? "Yes" : "No"); + fprintf(f, " - Redundancy version:\t\t\t%d\n", dci->rv_idx); + fprintf(f, " - TPC command for PUCCH:\t\t--\n"); +} - srslte_ra_dl_alloc_t alloc; - srslte_ra_dl_alloc(&alloc, ra, nof_prb); - for (int s = 0; s < 2; s++) { - fprintf(f, " - PRB Bitmap Assignment %dst slot:\n", s); - srslte_ra_prb_fprint(f, &alloc.slot[s], nof_prb); - } +void srslte_ra_dl_grant_fprint(FILE *f, srslte_ra_dl_grant_t *grant) { + srslte_ra_prb_fprint(f, grant); + fprintf(f, " - Number of PRBs:\t\t\t%d\n", grant->nof_prb); + fprintf(f, " - Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs.mod)); + fprintf(f, " - Transport block size:\t\t%d\n", grant->mcs.tbs); +} - fprintf(f, " - Number of PRBs:\t\t\t%d\n", srslte_ra_nprb_dl(ra, nof_prb)); - fprintf(f, " - Modulation and coding scheme index:\t%d\n", ra->mcs_idx); - fprintf(f, " - Modulation type:\t\t\t%s\n", srslte_mod_string(ra->mcs.mod)); - fprintf(f, " - Transport block size:\t\t%d\n", ra->mcs.tbs); - fprintf(f, " - HARQ process:\t\t\t%d\n", ra->harq_process); - fprintf(f, " - New data indicator:\t\t\t%s\n", ra->ndi ? "Yes" : "No"); - fprintf(f, " - Redundancy version:\t\t\t%d\n", ra->rv_idx); - fprintf(f, " - TPC command for PUCCH:\t\t--\n"); +void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) { + if (grant->nof_prb > 0) { + for (int j=0;j<2;j++) { + fprintf(f, " - PRB Bitmap Assignment %dst slot:\n", j); + for (int i=0;iprb_idx[j][i]) { + fprintf(f, "%d, ", i); + } + } + fprintf(f, "\n"); + } + } + } + diff --git a/srslte/lib/phch/src/sch.c b/srslte/lib/phch/src/sch.c index 3bac4781c..42e9075d6 100644 --- a/srslte/lib/phch/src/sch.c +++ b/srslte/lib/phch/src/sch.c @@ -34,6 +34,7 @@ #include #include +#include "srslte/phch/pdsch.h" #include "srslte/phch/pusch.h" #include "srslte/phch/sch.h" #include "srslte/phch/uci.h" @@ -55,6 +56,33 @@ float beta_cqi_offset[16] = {-1.0, -1.0, 1.125, 1.25, 1.375, 1.625, 1.750, 2.0, 3.125, 3.5, 4.0, 5.0, 6.25}; +uint32_t srslte_sch_find_Ioffset_ack(float beta) { + for (int i=0;i<16;i++) { + if (beta_harq_offset[i] >= beta) { + return i; + } + } + return 0; +} + +uint32_t srslte_sch_find_Ioffset_ri(float beta) { + for (int i=0;i<16;i++) { + if (beta_ri_offset[i] >= beta) { + return i; + } + } + return 0; +} + +uint32_t srslte_sch_find_Ioffset_cqi(float beta) { + for (int i=0;i<16;i++) { + if (beta_cqi_offset[i] >= beta) { + return i; + } + } + return 0; +} + int srslte_sch_init(srslte_sch_t *q) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q) { @@ -69,22 +97,22 @@ int srslte_sch_init(srslte_sch_t *q) { goto clean; } - if (srslte_tcod_init(&q->encoder, MAX_LONG_CB)) { + if (srslte_tcod_init(&q->encoder, SRSLTE_TCOD_MAX_LEN_CB)) { fprintf(stderr, "Error initiating Turbo Coder\n"); goto clean; } - if (srslte_tdec_init(&q->decoder, MAX_LONG_CB)) { + if (srslte_tdec_init(&q->decoder, SRSLTE_TCOD_MAX_LEN_CB)) { fprintf(stderr, "Error initiating Turbo Decoder\n"); goto clean; } // Allocate floats for reception (LLRs) - q->cb_in = srslte_vec_malloc(sizeof(uint8_t) * MAX_LONG_CB); + q->cb_in = srslte_vec_malloc(sizeof(uint8_t) * SRSLTE_TCOD_MAX_LEN_CB); if (!q->cb_in) { goto clean; } - q->cb_out = srslte_vec_malloc(sizeof(float) * (3 * MAX_LONG_CB + 12)); + q->cb_out = srslte_vec_malloc(sizeof(float) * (3 * SRSLTE_TCOD_MAX_LEN_CB + 12)); if (!q->cb_out) { goto clean; } @@ -128,7 +156,10 @@ uint32_t srslte_sch_last_noi(srslte_sch_t *q) { /* Encode a transport block according to 36.212 5.3.2 * */ -static int encode_tb(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_t *e_bits, uint32_t nof_e_bits) +static int encode_tb(srslte_sch_t *q, + srslte_softbuffer_tx_t *soft_buffer, srslte_cbsegm_t *cb_segm, + uint32_t Qm, uint32_t rv, uint32_t nof_e_bits, + uint8_t *data, uint8_t *e_bits) { uint8_t parity[24]; uint8_t *p_parity = parity; @@ -136,30 +167,31 @@ static int encode_tb(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_ uint32_t i; uint32_t cb_len, rp, wp, rlen, F, n_e; int ret = SRSLTE_ERROR_INVALID_INPUTS; - uint32_t Qm = srslte_mod_bits_x_symbol(harq->mcs.mod); - if (q != NULL && - data != NULL && - harq != NULL) + if (q != NULL && + data != NULL && + e_bits != NULL && + cb_segm != NULL && + soft_buffer != NULL) { uint32_t Gp = nof_e_bits / Qm; uint32_t gamma = Gp; - if (harq->cb_segm.C > 0) { - gamma = Gp%harq->cb_segm.C; + if (cb_segm->C > 0) { + gamma = Gp%cb_segm->C; } - if (harq->rv == 0) { + if (rv == 0) { /* Compute transport block CRC */ - par = srslte_crc_checksum(&q->crc_tb, data, harq->mcs.tbs); + par = srslte_crc_checksum(&q->crc_tb, data, cb_segm->tbs); /* parity bits will be appended later */ srslte_bit_pack(par, &p_parity, 24); if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("DATA: ", 0); - srslte_vec_fprint_b(stdout, data, harq->mcs.tbs); + srslte_vec_fprint_b(stdout, data, cb_segm->tbs); DEBUG("PARITY: ", 0); srslte_vec_fprint_b(stdout, parity, 24); } @@ -167,37 +199,37 @@ static int encode_tb(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_ wp = 0; rp = 0; - for (i = 0; i < harq->cb_segm.C; i++) { + for (i = 0; i < cb_segm->C; i++) { /* Get read lengths */ - if (i < harq->cb_segm.C2) { - cb_len = harq->cb_segm.K2; + if (i < cb_segm->C2) { + cb_len = cb_segm->K2; } else { - cb_len = harq->cb_segm.K1; + cb_len = cb_segm->K1; } - if (harq->cb_segm.C > 1) { + if (cb_segm->C > 1) { rlen = cb_len - 24; } else { rlen = cb_len; } if (i == 0) { - F = harq->cb_segm.F; + F = cb_segm->F; } else { F = 0; } - if (i <= harq->cb_segm.C - gamma - 1) { - n_e = Qm * (Gp/harq->cb_segm.C); + if (i <= cb_segm->C - gamma - 1) { + n_e = Qm * (Gp/cb_segm->C); } else { - n_e = Qm * ((uint32_t) ceilf((float) Gp/harq->cb_segm.C)); + n_e = Qm * ((uint32_t) ceilf((float) Gp/cb_segm->C)); } INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i, cb_len, rlen - F, wp, rp, F, n_e); - if (harq->rv == 0) { + if (rv == 0) { /* Copy data to another buffer, making space for the Codeblock CRC */ - if (i < harq->cb_segm.C - 1) { + if (i < cb_segm->C - 1) { // Copy data memcpy(&q->cb_in[F], &data[rp], (rlen - F) * sizeof(uint8_t)); } else { @@ -212,7 +244,7 @@ static int encode_tb(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_ q->cb_in[j] = 0; } /* Attach Codeblock CRC */ - if (harq->cb_segm.C > 1) { + if (cb_segm->C > 1) { srslte_crc_attach(&q->crc_cb, q->cb_in, rlen); } /* Set the filler bits to */ @@ -229,9 +261,9 @@ static int encode_tb(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_ } /* Rate matching */ - if (srslte_rm_turbo_tx(harq->pdsch_w_buff_c[i], harq->w_buff_size, + if (srslte_rm_turbo_tx(soft_buffer->buffer_b[i], soft_buffer->buff_size, (uint8_t*) q->cb_out, 3 * cb_len + 12, - &e_bits[wp], n_e, harq->rv)) + &e_bits[wp], n_e, rv)) { fprintf(stderr, "Error in rate matching\n"); return SRSLTE_ERROR; @@ -251,21 +283,25 @@ static int encode_tb(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_ /* Decode a transport block according to 36.212 5.3.2 * */ -static int decode_tb(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_t *data, uint32_t nof_e_bits) +static int decode_tb(srslte_sch_t *q, + srslte_softbuffer_rx_t *softbuffer, srslte_cbsegm_t *cb_segm, + uint32_t Qm, uint32_t rv, uint32_t nof_e_bits, + float *e_bits, uint8_t *data) { uint8_t parity[24]; uint8_t *p_parity = parity; uint32_t par_rx, par_tx; uint32_t i; uint32_t cb_len, rp, wp, rlen, F, n_e; - uint32_t Qm = srslte_mod_bits_x_symbol(harq->mcs.mod); - if (q != NULL && - data != NULL && - harq != NULL) + if (q != NULL && + data != NULL && + softbuffer != NULL && + e_bits != NULL && + cb_segm != NULL) { - if (harq->mcs.tbs == 0 || harq->cb_segm.C == 0) { + if (cb_segm->tbs == 0 || cb_segm->C == 0) { return SRSLTE_SUCCESS; } @@ -275,43 +311,43 @@ static int decode_tb(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_ uint32_t Gp = nof_e_bits / Qm; uint32_t gamma=Gp; - if (harq->cb_segm.C>0) { - gamma = Gp%harq->cb_segm.C; + if (cb_segm->C>0) { + gamma = Gp%cb_segm->C; } bool early_stop = true; - for (i = 0; i < harq->cb_segm.C && early_stop; i++) { + for (i = 0; i < cb_segm->C && early_stop; i++) { /* Get read/write lengths */ - if (i < harq->cb_segm.C2) { - cb_len = harq->cb_segm.K2; + if (i < cb_segm->C2) { + cb_len = cb_segm->K2; } else { - cb_len = harq->cb_segm.K1; + cb_len = cb_segm->K1; } - if (harq->cb_segm.C == 1) { + if (cb_segm->C == 1) { rlen = cb_len; } else { rlen = cb_len - 24; } if (i == 0) { - F = harq->cb_segm.F; + F = cb_segm->F; } else { F = 0; } - if (i <= harq->cb_segm.C - gamma - 1) { - n_e = Qm * (Gp/harq->cb_segm.C); + if (i <= cb_segm->C - gamma - 1) { + n_e = Qm * (Gp/cb_segm->C); } else { - n_e = Qm * ((uint32_t) ceilf((float) Gp/harq->cb_segm.C)); + n_e = Qm * ((uint32_t) ceilf((float) Gp/cb_segm->C)); } INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i, cb_len, rlen - F, wp, rp, F, n_e); /* Rate Unmatching */ - if (srslte_rm_turbo_rx(harq->pdsch_w_buff_f[i], harq->w_buff_size, + if (srslte_rm_turbo_rx(softbuffer->buffer_f[i], softbuffer->buff_size, &e_bits[rp], n_e, - (float*) q->cb_out, 3 * cb_len + 12, harq->rv, F)) { + (float*) q->cb_out, 3 * cb_len + 12, rv, F)) { fprintf(stderr, "Error in rate matching\n"); return SRSLTE_ERROR; } @@ -334,12 +370,12 @@ static int decode_tb(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_ srslte_tdec_iteration(&q->decoder, (float*) q->cb_out, cb_len); q->nof_iterations++; - if (harq->cb_segm.C > 1) { + if (cb_segm->C > 1) { len_crc = cb_len; cb_in_ptr = q->cb_in; crc_ptr = &q->crc_cb; } else { - len_crc = harq->mcs.tbs+24; + len_crc = cb_segm->tbs+24; cb_in_ptr = &q->cb_in[F]; crc_ptr = &q->crc_tb; } @@ -362,7 +398,7 @@ static int decode_tb(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_ // If CB CRC is not correct, early_stop will be false and wont continue with rest of CBs /* Copy data to another buffer, removing the Codeblock CRC */ - if (i < harq->cb_segm.C - 1) { + if (i < cb_segm->C - 1) { memcpy(&data[wp], &q->cb_in[F], (rlen - F) * sizeof(uint8_t)); } else { DEBUG("Last CB, appending parity: %d to %d from %d and 24 from %d\n", @@ -385,7 +421,7 @@ static int decode_tb(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_ INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp); // Compute transport block CRC - par_rx = srslte_crc_checksum(&q->crc_tb, data, harq->mcs.tbs); + par_rx = srslte_crc_checksum(&q->crc_tb, data, cb_segm->tbs); // check parity bits par_tx = srslte_bit_unpack(&p_parity, 24); @@ -408,23 +444,36 @@ static int decode_tb(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_ } } -int srslte_dlsch_decode(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_t *data) +int srslte_dlsch_decode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, + float *e_bits, uint8_t *data) { - return decode_tb(q, harq, e_bits, data, harq->nof_bits); + return decode_tb(q, + softbuffer, &cfg->cb_segm, + cfg->grant.Qm, cfg->rv, cfg->grant.nof_bits, + e_bits, data); } -int srslte_dlsch_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_t *e_bits) { - return encode_tb(q, harq, data, e_bits, harq->nof_bits); +int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, uint8_t *e_bits) +{ + return encode_tb(q, + softbuffer, &cfg->cb_segm, + cfg->grant.Qm, cfg->rv, cfg->grant.nof_bits, + data, e_bits); } -int srslte_ulsch_decode(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_t *data) +int srslte_ulsch_decode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, + float *e_bits, uint8_t *data) { - return decode_tb(q, harq, e_bits, data, harq->nof_bits); + return decode_tb(q, + softbuffer, &cfg->cb_segm, + cfg->grant.Qm, cfg->rv, cfg->grant.nof_bits, + e_bits, data); } /* UL-SCH channel interleaver according to 5.5.2.8 of 36.212 */ -void ulsch_interleave(uint8_t *g_bits, uint32_t Q_m, uint32_t H_prime_total, uint32_t N_pusch_symbs, uint8_t *q_bits) +void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, uint8_t *q_bits) { uint32_t rows = H_prime_total/N_pusch_symbs; @@ -433,11 +482,11 @@ void ulsch_interleave(uint8_t *g_bits, uint32_t Q_m, uint32_t H_prime_total, uin uint32_t idx = 0; for(uint32_t j=0; j= 10) { - q_bits[j*Q_m + i*rows*Q_m + k] -= 10; + for(uint32_t k=0; k= 10) { + q_bits[j*Qm + i*rows*Qm + k] -= 10; } else { - q_bits[j*Q_m + i*rows*Q_m + k] = g_bits[idx]; + q_bits[j*Qm + i*rows*Qm + k] = g_bits[idx]; idx++; } } @@ -446,15 +495,18 @@ void ulsch_interleave(uint8_t *g_bits, uint32_t Q_m, uint32_t H_prime_total, uin } -int srslte_ulsch_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_t *g_bits, uint8_t *q_bits) +int srslte_ulsch_encode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, uint8_t *g_bits, uint8_t *q_bits) { srslte_uci_data_t uci_data; bzero(&uci_data, sizeof(srslte_uci_data_t)); - return srslte_ulsch_uci_encode(q, harq, data, uci_data, g_bits, q_bits); + return srslte_ulsch_uci_encode(q, cfg, softbuffer, data, uci_data, g_bits, q_bits); } - -int srslte_ulsch_uci_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, srslte_uci_data_t uci_data, uint8_t *g_bits, uint8_t *q_bits) +int srslte_ulsch_uci_encode(srslte_sch_t *q, + srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, srslte_uci_data_t uci_data, + uint8_t *g_bits, uint8_t *q_bits) { int ret; @@ -462,20 +514,19 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint32_t Q_prime_cqi = 0; uint32_t Q_prime_ack = 0; uint32_t Q_prime_ri = 0; - uint32_t Q_m = srslte_mod_bits_x_symbol(harq->mcs.mod); - - uint32_t nof_symbols = 12*harq->ul_alloc.L_prb*SRSLTE_NRE; - uint32_t nb_q = nof_symbols * Q_m; + uint32_t nb_q = cfg->grant.nof_bits; + uint32_t Qm = cfg->grant.Qm; + bzero(q_bits, sizeof(uint8_t) * nb_q); // Encode RI if (uci_data.uci_ri_len > 0) { float beta = beta_ri_offset[uci_data.I_offset_ri]; - if (harq->mcs.tbs == 0) { + if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[uci_data.I_offset_cqi]; } - ret = srslte_uci_encode_ri(uci_data.uci_ri, uci_data.uci_cqi_len, beta, harq, nb_q/Q_m, q_bits); + ret = srslte_uci_encode_ri(cfg, uci_data.uci_ri, uci_data.uci_cqi_len, beta, nb_q/Qm, q_bits); if (ret < 0) { return ret; } @@ -484,37 +535,39 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, // Encode CQI if (uci_data.uci_cqi_len > 0) { - - ret = srslte_uci_encode_cqi_pusch(&q->uci_cqi, uci_data.uci_cqi, uci_data.uci_cqi_len, + ret = srslte_uci_encode_cqi_pusch(&q->uci_cqi, cfg, + uci_data.uci_cqi, uci_data.uci_cqi_len, beta_cqi_offset[uci_data.I_offset_cqi], - Q_prime_ri, harq, g_bits); + Q_prime_ri, g_bits); if (ret < 0) { return ret; } Q_prime_cqi = (uint32_t) ret; } - e_offset += Q_prime_cqi*Q_m; + e_offset += Q_prime_cqi*Qm; // Encode UL-SCH - if (harq->mcs.tbs > 0) { - uint32_t G = nb_q/Q_m - Q_prime_ri - Q_prime_cqi; - ret = encode_tb(q, harq, data, &g_bits[e_offset], G*Q_m); + if (cfg->cb_segm.tbs > 0) { + uint32_t G = nb_q/Qm - Q_prime_ri - Q_prime_cqi; + ret = encode_tb(q, softbuffer, &cfg->cb_segm, + Qm, cfg->rv, G*Qm, + data, &g_bits[e_offset]); if (ret) { return ret; } } // Interleave UL-SCH (and RI and CQI) - ulsch_interleave(g_bits, Q_m, nb_q/Q_m, harq->nof_symb, q_bits); + ulsch_interleave(g_bits, Qm, nb_q/Qm, cfg->grant.nof_symb, q_bits); // Encode (and interleave) ACK if (uci_data.uci_ack_len > 0) { float beta = beta_harq_offset[uci_data.I_offset_ack]; - if (harq->mcs.tbs == 0) { + if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[uci_data.I_offset_cqi]; } - ret = srslte_uci_encode_ack(uci_data.uci_ack, uci_data.uci_cqi_len, beta, harq, nb_q/Q_m, q_bits); + ret = srslte_uci_encode_ack(cfg, uci_data.uci_ack, uci_data.uci_cqi_len, beta, nb_q/Qm, q_bits); if (ret < 0) { return ret; } @@ -523,8 +576,6 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, INFO("Q_prime_ack=%d, Q_prime_cqi=%d, Q_prime_ri=%d\n",Q_prime_ack, Q_prime_cqi, Q_prime_ri); - - return SRSLTE_SUCCESS; } diff --git a/srslte/lib/phch/src/softbuffer.c b/srslte/lib/phch/src/softbuffer.c new file mode 100644 index 000000000..db6fc574f --- /dev/null +++ b/srslte/lib/phch/src/softbuffer.c @@ -0,0 +1,164 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \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 Lesser 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 Lesser General Public License for more details. + * + * A copy of the GNU Lesser 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 +#include +#include +#include +#include +#include +#include +#include + +#include "srslte/common/phy_common.h" +#include "srslte/phch/ra.h" +#include "srslte/fec/turbodecoder.h" +#include "srslte/phch/softbuffer.h" +#include "srslte/utils/vector.h" +#include "srslte/utils/debug.h" + +#define MAX_PDSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12) + +int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t *q, srslte_cell_t cell) { + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL) { + ret = SRSLTE_ERROR; + + bzero(q, sizeof(srslte_softbuffer_rx_t)); + + ret = srslte_ra_tbs_from_idx(26, cell.nof_prb); + if (ret != SRSLTE_ERROR) { + q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1; + + q->buffer_f = srslte_vec_malloc(sizeof(float*) * q->max_cb); + if (!q->buffer_f) { + perror("malloc"); + return SRSLTE_ERROR; + } + + // FIXME: Use HARQ buffer limitation based on UE category + q->buff_size = cell.nof_prb * MAX_PDSCH_RE(cell.cp) * 6 * 10; + for (uint32_t i=0;imax_cb;i++) { + q->buffer_f[i] = srslte_vec_malloc(sizeof(float) * q->buff_size); + if (!q->buffer_f[i]) { + perror("malloc"); + return SRSLTE_ERROR; + } + } + srslte_softbuffer_rx_reset(q); + ret = SRSLTE_SUCCESS; + } + } + return ret; +} + +void srslte_softbuffer_rx_free(srslte_softbuffer_rx_t *q) { + if (q) { + if (q->buffer_f) { + for (uint32_t i=0;imax_cb;i++) { + if (q->buffer_f[i]) { + free(q->buffer_f[i]); + } + } + free(q->buffer_f); + } + bzero(q, sizeof(srslte_softbuffer_rx_t)); + } +} + +void srslte_softbuffer_rx_reset(srslte_softbuffer_rx_t *q) { + int i; + if (q->buffer_f) { + for (i=0;imax_cb;i++) { + if (q->buffer_f[i]) { + bzero(q->buffer_f[i], sizeof(float) * q->buff_size); + } + } + } +} + + + +int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t *q, srslte_cell_t cell) { + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL) { + ret = SRSLTE_ERROR; + + bzero(q, sizeof(srslte_softbuffer_tx_t)); + + ret = srslte_ra_tbs_from_idx(26, cell.nof_prb); + if (ret != SRSLTE_ERROR) { + q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1; + + q->buffer_b = srslte_vec_malloc(sizeof(uint8_t*) * q->max_cb); + if (!q->buffer_b) { + perror("malloc"); + return SRSLTE_ERROR; + } + + // FIXME: Use HARQ buffer limitation based on UE category + q->buff_size = cell.nof_prb * MAX_PDSCH_RE(cell.cp) * 6 * 10; + for (uint32_t i=0;imax_cb;i++) { + q->buffer_b[i] = srslte_vec_malloc(sizeof(float) * q->buff_size); + if (!q->buffer_b[i]) { + perror("malloc"); + return SRSLTE_ERROR; + } + } + srslte_softbuffer_tx_reset(q); + ret = SRSLTE_SUCCESS; + } + } + return ret; +} + +void srslte_softbuffer_tx_free(srslte_softbuffer_tx_t *q) { + if (q) { + if (q->buffer_b) { + for (uint32_t i=0;imax_cb;i++) { + if (q->buffer_b[i]) { + free(q->buffer_b[i]); + } + } + free(q->buffer_b); + } + bzero(q, sizeof(srslte_softbuffer_tx_t)); + } +} + +void srslte_softbuffer_tx_reset(srslte_softbuffer_tx_t *q) { + int i; + if (q->buffer_b) { + for (i=0;imax_cb;i++) { + if (q->buffer_b[i]) { + bzero(q->buffer_b[i], sizeof(uint8_t) * q->buff_size); + } + } + } +} diff --git a/srslte/lib/phch/src/uci.c b/srslte/lib/phch/src/uci.c index 4a277bcda..8c48a8864 100644 --- a/srslte/lib/phch/src/uci.c +++ b/srslte/lib/phch/src/uci.c @@ -35,7 +35,7 @@ #include #include "srslte/phch/uci.h" -#include "srslte/phch/harq.h" +#include "srslte/fec/cbsegm.h" #include "srslte/fec/convcoder.h" #include "srslte/fec/crc.h" #include "srslte/fec/rm_conv.h" @@ -114,22 +114,21 @@ void srslte_uci_cqi_free(srslte_uci_cqi_pusch_t *q) { } -static uint32_t Q_prime_cqi(uint32_t O, float beta, uint32_t Q_prime_ri, srslte_harq_t *harq) { - uint32_t M_sc = harq->ul_alloc.L_prb * SRSLTE_NRE; +static uint32_t Q_prime_cqi(srslte_pusch_cfg_t *cfg, + uint32_t O, float beta, uint32_t Q_prime_ri) +{ - uint32_t K = harq->cb_segm.C1*harq->cb_segm.K1 + - harq->cb_segm.C2*harq->cb_segm.K2; + uint32_t K = cfg->cb_segm.C1*cfg->cb_segm.K1 + cfg->cb_segm.C2*cfg->cb_segm.K2; uint32_t Q_prime = 0; + uint32_t L = (O<11)?0:8; + uint32_t x = 999999; + if (K > 0) { - uint32_t M_sc_init = harq->nof_prb * SRSLTE_NRE; - uint32_t L = (O<11)?0:8; - uint32_t x = (uint32_t) ceilf((float) (O+L)*M_sc_init*harq->nof_symb*beta/K); - - Q_prime = SRSLTE_MIN(x, M_sc * harq->nof_symb - Q_prime_ri); - } else { - Q_prime = 12*harq->ul_alloc.L_prb*SRSLTE_NRE - Q_prime_ri; + x = (uint32_t) ceilf((float) (O+L)*cfg->grant.M_sc_init*cfg->grant.nof_symb*beta/K); } + + Q_prime = SRSLTE_MIN(x, cfg->grant.M_sc * cfg->grant.nof_symb - Q_prime_ri); return Q_prime; } @@ -217,21 +216,23 @@ int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_b /* Encode UCI CQI/PMI as described in 5.2.2.6 of 36.212 */ -int srslte_uci_encode_cqi_pusch(srslte_uci_cqi_pusch_t *q, uint8_t *cqi_data, uint32_t cqi_len, float beta, uint32_t Q_prime_ri, - srslte_harq_t *harq, uint8_t *q_bits) +int srslte_uci_encode_cqi_pusch(srslte_uci_cqi_pusch_t *q, srslte_pusch_cfg_t *cfg, + uint8_t *cqi_data, uint32_t cqi_len, + float beta, uint32_t Q_prime_ri, + uint8_t *q_bits) { if (beta < 0) { fprintf(stderr, "Error beta is reserved\n"); return -1; } - uint32_t Q_prime = Q_prime_cqi(cqi_len, beta, Q_prime_ri, harq); - uint32_t Q_m = srslte_mod_bits_x_symbol(harq->mcs.mod); + + uint32_t Q_prime = Q_prime_cqi(cfg, cqi_len, beta, Q_prime_ri); int ret = SRSLTE_ERROR; if (cqi_len <= 11) { - ret = encode_cqi_short(q, cqi_data, cqi_len, q_bits, Q_prime*Q_m); + ret = encode_cqi_short(q, cqi_data, cqi_len, q_bits, Q_prime*cfg->grant.Qm); } else { - ret = encode_cqi_long(q, cqi_data, cqi_len, q_bits, Q_prime*Q_m); + ret = encode_cqi_long(q, cqi_data, cqi_len, q_bits, Q_prime*cfg->grant.Qm); } if (ret) { return ret; @@ -242,7 +243,7 @@ int srslte_uci_encode_cqi_pusch(srslte_uci_cqi_pusch_t *q, uint8_t *cqi_data, ui /* Inserts UCI-ACK bits into the correct positions in the g buffer before interleaving */ static int uci_ulsch_interleave_ack(uint8_t ack_coded_bits[6], uint32_t ack_q_bit_idx, - uint32_t Q_m, uint32_t H_prime_total, uint32_t N_pusch_symbs, srslte_cp_t cp, + uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, srslte_cp_t cp, uint8_t *q_bits) { const uint32_t ack_column_set_norm[4] = {2, 3, 8, 9}; @@ -253,9 +254,9 @@ static int uci_ulsch_interleave_ack(uint8_t ack_coded_bits[6], uint32_t ack_q_bi uint32_t row = H_prime_total/N_pusch_symbs-1-ack_q_bit_idx/4; uint32_t colidx = (3*ack_q_bit_idx)%4; uint32_t col = SRSLTE_CP_ISNORM(cp)?ack_column_set_norm[colidx]:ack_column_set_ext[colidx]; - for(uint32_t k=0; kul_alloc.L_prb * SRSLTE_NRE; - - uint32_t K = harq->cb_segm.C1*harq->cb_segm.K1 + - harq->cb_segm.C2*harq->cb_segm.K2; + uint32_t K = cfg->cb_segm.C1*cfg->cb_segm.K1 + cfg->cb_segm.C2*cfg->cb_segm.K2; // If not carrying UL-SCH, get Q_prime according to 5.2.4.1 if (K == 0) { @@ -311,19 +310,17 @@ static uint32_t Q_prime_ri_ack(uint32_t O, uint32_t O_cqi, float beta, srslte_ha } } - uint32_t M_sc_init = harq->nof_prb * SRSLTE_NRE; - - uint32_t x = (uint32_t) ceilf((float) O*M_sc_init*harq->nof_symb*beta/K); + uint32_t x = (uint32_t) ceilf((float) O*cfg->grant.M_sc_init*cfg->grant.nof_symb*beta/K); - uint32_t Q_prime = SRSLTE_MIN(x, 4*M_sc); + uint32_t Q_prime = SRSLTE_MIN(x, 4*cfg->grant.M_sc); return Q_prime; } -static void encode_ri_ack(uint8_t data, uint8_t q_encoded_bits[6], uint8_t Q_m) { +static void encode_ri_ack(uint8_t data, uint8_t q_encoded_bits[6], uint8_t Qm) { q_encoded_bits[0] = data; q_encoded_bits[1] = 2; - for (uint32_t i=2;imcs.mod); - uint32_t Qprime = Q_prime_ri_ack(1, O_cqi, beta, harq); + uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); uint8_t q_encoded_bits[6]; - encode_ri_ack(data, q_encoded_bits, Q_m); + encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm); for (uint32_t i=0;inof_symb, harq->cell.cp, q_bits); + uci_ulsch_interleave_ack(q_encoded_bits, i, cfg->grant.Qm, H_prime_total, cfg->grant.nof_symb, cfg->cp, q_bits); } return (int) Qprime; @@ -357,23 +354,22 @@ int srslte_uci_encode_ack(uint8_t data, uint32_t O_cqi, /* Encode UCI RI bits as described in 5.2.2.6 of 36.212 * Currently only supporting 1-bit RI */ -int srslte_uci_encode_ri(uint8_t data, uint32_t O_cqi, float beta, - srslte_harq_t *harq, uint32_t H_prime_total, +int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg, + uint8_t data, + uint32_t O_cqi, float beta, uint32_t H_prime_total, uint8_t *q_bits) { if (beta < 0) { fprintf(stderr, "Error beta is reserved\n"); return -1; } - - uint32_t Q_m = srslte_mod_bits_x_symbol(harq->mcs.mod); - uint32_t Qprime = Q_prime_ri_ack(1, O_cqi, beta, harq); + uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); uint8_t q_encoded_bits[6]; - encode_ri_ack(data, q_encoded_bits, Q_m); + encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm); for (uint32_t i=0;inof_symb, harq->cell.cp, q_bits); + uci_ulsch_interleave_ri(q_encoded_bits, i, cfg->grant.Qm, H_prime_total, cfg->grant.nof_symb, cfg->cp, q_bits); } return (int) Qprime; diff --git a/srslte/lib/phch/test/dci_unpacking.c b/srslte/lib/phch/test/dci_unpacking.c index aa7f0298d..6a1880af3 100644 --- a/srslte/lib/phch/test/dci_unpacking.c +++ b/srslte/lib/phch/test/dci_unpacking.c @@ -39,7 +39,7 @@ void usage(char *prog) { int main(int argc, char **argv) { srslte_dci_msg_t msg; - srslte_ra_pdsch_t ra_dl; + srslte_ra_dl_dci_t ra_dl; int len, rlen; int nof_prb; int nwords; @@ -91,7 +91,7 @@ int main(int argc, char **argv) { srslte_dci_msg_type_fprint(stdout, dci_type); switch (dci_type.type) { case SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED: - bzero(&ra_dl, sizeof(srslte_ra_pdsch_t)); + bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t)); srslte_dci_msg_unpack_pdsch(&msg, &ra_dl, nof_prb, false); srslte_ra_pdsch_fprint(stdout, &ra_dl, nof_prb); break; diff --git a/srslte/lib/phch/test/dlsch_encode_test_mex.c b/srslte/lib/phch/test/dlsch_encode_test_mex.c index 5fed221df..a0976ebaa 100644 --- a/srslte/lib/phch/test/dlsch_encode_test_mex.c +++ b/srslte/lib/phch/test/dlsch_encode_test_mex.c @@ -46,16 +46,14 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { srslte_sch_t dlsch; uint8_t *trblkin; - srslte_ra_mcs_t mcs; - srslte_ra_dl_alloc_t prb_alloc; - srslte_harq_t harq_process; - uint32_t rv; + srslte_pdsch_cfg_t cfg; + srslte_softbuffer_tx_t softbuffer; if (nrhs < NOF_INPUTS) { help(); return; } - + if (srslte_sch_init(&dlsch)) { mexErrMsgTxt("Error initiating DL-SCH\n"); return; @@ -63,18 +61,14 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) srslte_cell_t cell; cell.nof_prb = 100; cell.id=1; - if (srslte_harq_init(&harq_process, cell)) { - mexErrMsgTxt("Error initiating HARQ\n"); - return; - } - - mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin); - if (mcs.tbs == 0) { + + cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin); + if (cfg.grant.mcs.tbs == 0) { mexErrMsgTxt("Error trblklen is zero\n"); return; } - if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) { + if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &cfg.rv)) { mexErrMsgTxt("Field RV not found in dlsch config\n"); return; } @@ -82,36 +76,42 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation"); if (!strcmp(mod_str, "QPSK")) { - mcs.mod = SRSLTE_MOD_QPSK; + cfg.grant.mcs.mod = SRSLTE_MOD_QPSK; + cfg.grant.Qm = 2; } else if (!strcmp(mod_str, "16QAM")) { - mcs.mod = SRSLTE_MOD_16QAM; + cfg.grant.mcs.mod = SRSLTE_MOD_16QAM; + cfg.grant.Qm = 4; } else if (!strcmp(mod_str, "64QAM")) { - mcs.mod = SRSLTE_MOD_64QAM; + cfg.grant.mcs.mod = SRSLTE_MOD_64QAM; + cfg.grant.Qm = 6; } else { mexErrMsgTxt("Unknown modulation\n"); return; } mxFree(mod_str); - - if (srslte_harq_setup_dl(&harq_process, mcs, rv, 0, &prb_alloc)) { - mexErrMsgTxt("Error configuring HARQ process\n"); - return; + + if (srslte_softbuffer_tx_init(&softbuffer, cell)) { + mexErrMsgTxt("Error initiating DL-SCH soft buffer\n"); + return; } - harq_process.nof_bits = mxGetScalar(OUTLEN); - - uint8_t *e_bits = srslte_vec_malloc(harq_process.nof_bits* sizeof(uint8_t)); + + cfg.grant.nof_bits = mxGetScalar(OUTLEN); + uint8_t *e_bits = srslte_vec_malloc(cfg.grant.nof_bits * sizeof(uint8_t)); if (!e_bits) { return; } - - if (srslte_dlsch_encode(&dlsch, &harq_process, trblkin, e_bits)) { + if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) { + mexErrMsgTxt("Error computing CB segmentation\n"); + return; + } + if (srslte_dlsch_encode(&dlsch, &cfg, &softbuffer, trblkin, e_bits)) { mexErrMsgTxt("Error encoding TB\n"); return; } if (nlhs >= 1) { - mexutils_write_uint8(e_bits, &plhs[0], harq_process.nof_bits, 1); + mexutils_write_uint8(e_bits, &plhs[0], cfg.grant.nof_bits, 1); } srslte_sch_free(&dlsch); diff --git a/srslte/lib/phch/test/pdcch_file_test.c b/srslte/lib/phch/test/pdcch_file_test.c index 3d647da7e..cae04d8c2 100644 --- a/srslte/lib/phch/test/pdcch_file_test.c +++ b/srslte/lib/phch/test/pdcch_file_test.c @@ -200,7 +200,7 @@ void base_free() { } int main(int argc, char **argv) { - srslte_ra_pdsch_t ra_dl; + srslte_ra_dl_dci_t ra_dl; int i; int frame_cnt; int ret; @@ -264,7 +264,7 @@ int main(int argc, char **argv) { srslte_dci_msg_type_fprint(stdout, type); switch(type.type) { case SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED: - bzero(&ra_dl, sizeof(srslte_ra_pdsch_t)); + bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t)); if (srslte_dci_msg_unpack_pdsch(&dci_msg, &ra_dl, cell.nof_prb, rnti != SRSLTE_SIRNTI)) { fprintf(stderr, "Can't unpack PDSCH message\n"); } else { diff --git a/srslte/lib/phch/test/pdcch_test.c b/srslte/lib/phch/test/pdcch_test.c index abb93afb0..3abc911e8 100644 --- a/srslte/lib/phch/test/pdcch_test.c +++ b/srslte/lib/phch/test/pdcch_test.c @@ -109,7 +109,7 @@ int main(int argc, char **argv) { srslte_pdcch_t pdcch; srslte_dci_msg_t dci_tx[2], dci_rx[2], dci_tmp; srslte_dci_location_t dci_locations[2]; - srslte_ra_pdsch_t ra_dl; + srslte_ra_dl_dci_t ra_dl; srslte_regs_t regs; int i, j; cf_t *ce[SRSLTE_MAX_PORTS]; @@ -160,7 +160,7 @@ int main(int argc, char **argv) { } nof_dcis = 2; - bzero(&ra_dl, sizeof(srslte_ra_pdsch_t)); + bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t)); ra_dl.harq_process = 0; ra_dl.mcs_idx = 5; ra_dl.ndi = 0; diff --git a/srslte/lib/phch/test/pdsch_file_test.c b/srslte/lib/phch/test/pdsch_file_test.c index 0a3ce99dc..8329f3991 100644 --- a/srslte/lib/phch/test/pdsch_file_test.c +++ b/srslte/lib/phch/test/pdsch_file_test.c @@ -57,13 +57,8 @@ uint32_t sf_idx = 0; srslte_dci_format_t dci_format = SRSLTE_DCI_FORMAT1A; srslte_filesource_t fsrc; -srslte_pdcch_t pdcch; -srslte_pdsch_t pdsch; -srslte_harq_t harq_process; -cf_t *input_buffer, *fft_buffer, *ce[SRSLTE_MAX_PORTS]; -srslte_regs_t regs; -srslte_ofdm_t fft; -srslte_chest_dl_t chest; +srslte_ue_dl_t ue_dl; +cf_t *input_buffer; void usage(char *prog) { printf("Usage: %s [rovfcenmps] -i input_file\n", prog); @@ -132,7 +127,6 @@ void parse_args(int argc, char **argv) { } int base_init() { - int i; if (srslte_filesource_init(&fsrc, input_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) { fprintf(stderr, "Error opening file %s\n", input_file_name); @@ -147,98 +141,31 @@ int base_init() { exit(-1); } - fft_buffer = malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); - if (!fft_buffer) { - perror("malloc"); - return -1; - } - - for (i=0;i 0) { + printf("PDSCH Decoded OK!\n"); + } else if (ret == 0) { + printf("No DCI grant found\n"); + } else if (ret < 0) { + printf("Error decoding PDSCH\n"); } - for (i=0;i 0) { - if (srslte_harq_setup_dl(&harq_process, ra_dl.mcs, ra_dl.rv_idx, sf_idx, &ra_dl.prb_alloc)) { - fprintf(stderr, "Error configuring HARQ process\n"); - goto goout; - } - if (srslte_pdsch_decode(&pdsch, &harq_process, fft_buffer, ce, srslte_chest_dl_get_noise_estimate(&chest), data)) { - fprintf(stderr, "Error decoding PDSCH\n"); - goto goout; - } else { - printf("PDSCH Decoded OK!\n"); - } - } else { - printf("Received DCI with no resource allocation\n"); - } - sf_idx = (sf_idx+1)%10; - } - + sf_idx = (sf_idx+1)%10; nof_frames++; - } while (nof_frames <= max_frames); + } while (nof_frames <= max_frames && ret == 0); - ret = 0; - -goout: base_free(); - exit(ret); + if (ret > 0) { + exit(0); + } else { + exit(-1); + } } diff --git a/srslte/lib/phch/test/pdsch_test.c b/srslte/lib/phch/test/pdsch_test.c index cc6237b57..e831b531d 100644 --- a/srslte/lib/phch/test/pdsch_test.c +++ b/srslte/lib/phch/test/pdsch_test.c @@ -127,45 +127,49 @@ int main(int argc, char **argv) { uint32_t i, j; uint8_t *data = NULL; cf_t *ce[SRSLTE_MAX_PORTS]; - uint32_t nof_re; cf_t *slot_symbols[SRSLTE_MAX_PORTS]; int ret = -1; struct timeval t[3]; - srslte_ra_mcs_t mcs; - srslte_ra_dl_alloc_t prb_alloc; - srslte_harq_t harq_process; + srslte_pdsch_cfg_t pdsch_cfg; + srslte_softbuffer_tx_t softbuffer_tx; + srslte_softbuffer_rx_t softbuffer_rx; uint32_t rv; parse_args(argc,argv); bzero(&pdsch, sizeof(srslte_pdsch_t)); - bzero(&harq_process, sizeof(srslte_harq_t)); + bzero(&pdsch_cfg, sizeof(srslte_pdsch_cfg_t)); bzero(ce, sizeof(cf_t*)*SRSLTE_MAX_PORTS); bzero(slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS); - nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE; + pdsch_cfg.grant.nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE; - mcs.mod = modulation; + pdsch_cfg.grant.mcs.mod = modulation; - prb_alloc.slot[0].nof_prb = cell.nof_prb; - for (i=0;i 0) { slot_symbols[0][j] += slot_symbols[i][j]; } @@ -220,16 +226,16 @@ int main(int argc, char **argv) { } gettimeofday(&t[1], NULL); - int r = srslte_pdsch_decode(&pdsch, &harq_process, slot_symbols[0], ce, 0, data); + int r = srslte_pdsch_decode(&pdsch, &pdsch_cfg, &softbuffer_rx, slot_symbols[0], ce, 0, data); gettimeofday(&t[2], NULL); get_time_interval(t); if (r) { - printf("Error decoding TBS: %d\n", mcs.tbs); + printf("Error decoding TBS: %d\n", pdsch_cfg.grant.mcs.tbs); ret = -1; goto quit; } else { if (nof_tbs == 0) { - printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) mcs.tbs/t[0].tv_usec); + printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) pdsch_cfg.grant.mcs.tbs/t[0].tv_usec); } } } @@ -237,7 +243,8 @@ int main(int argc, char **argv) { ret = 0; quit: srslte_pdsch_free(&pdsch); - srslte_harq_free(&harq_process); + srslte_softbuffer_tx_free(&softbuffer_tx); + srslte_softbuffer_rx_free(&softbuffer_rx); for (i=0;i NOF_INPUTS + 1) { @@ -204,28 +207,28 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) noise_power = srslte_chest_dl_get_noise_estimate(&chest); } - uint8_t *data = malloc(sizeof(uint8_t) * mcs.tbs); + uint8_t *data = malloc(sizeof(uint8_t) * cfg.grant.mcs.tbs); if (!data) { return; } - int r = srslte_pdsch_decode(&pdsch, &harq_process, input_fft, ce, noise_power, data); + int r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, data); if (nlhs >= 1) { plhs[0] = mxCreateLogicalScalar(r == 0); } if (nlhs >= 2) { - mexutils_write_uint8(data, &plhs[1], mcs.tbs, 1); + mexutils_write_uint8(data, &plhs[1], cfg.grant.mcs.tbs, 1); } if (nlhs >= 3) { - mexutils_write_cf(pdsch.symbols[0], &plhs[2], harq_process.dl_alloc.re_sf[sf_idx], 1); + mexutils_write_cf(pdsch.symbols[0], &plhs[2], cfg.grant.nof_re, 1); } if (nlhs >= 4) { - mexutils_write_cf(pdsch.d, &plhs[3], harq_process.dl_alloc.re_sf[sf_idx], 1); + mexutils_write_cf(pdsch.d, &plhs[3], cfg.grant.nof_re, 1); } if (nlhs >= 5) { - mexutils_write_f(pdsch.e, &plhs[4], harq_process.dl_alloc.re_sf[sf_idx] * srslte_mod_bits_x_symbol(mcs.mod), 1); + mexutils_write_f(pdsch.e, &plhs[4], cfg.grant.nof_bits, 1); } srslte_chest_dl_free(&chest); diff --git a/srslte/lib/phch/test/phich_file_test.c b/srslte/lib/phch/test/phich_file_test.c index 43af61a75..3479cb686 100644 --- a/srslte/lib/phch/test/phich_file_test.c +++ b/srslte/lib/phch/test/phich_file_test.c @@ -261,7 +261,7 @@ int main(int argc, char **argv) { exit(-1); } - INFO("%d/%d, ack_rx: %d, ns: %d, distance: %d\n", + INFO("%d/%d, ack_rx: %d, ns: %d, distance: %f\n", ngroup, nseq, ack_rx, numsubframe, distance); } } diff --git a/srslte/lib/phch/test/phich_test.c b/srslte/lib/phch/test/phich_test.c index 5c50ae70a..f9eeb6876 100644 --- a/srslte/lib/phch/test/phich_test.c +++ b/srslte/lib/phch/test/phich_test.c @@ -186,7 +186,7 @@ int main(int argc, char **argv) { printf("Error decoding ACK\n"); exit(-1); } - INFO("%d/%d, ack_tx: %d, ack_rx: %d, ns: %d, distance: %d\n", + INFO("%d/%d, ack_tx: %d, ack_rx: %d, ns: %d, distance: %f\n", ngroup, nseq, ack[ngroup][nseq], ack_rx, nsf, distance); if (ack[ngroup][nseq] != ack_rx) { printf("Invalid received ACK: %d!=%d\n", ack[ngroup][nseq], ack_rx); diff --git a/srslte/lib/phch/test/pusch_encode_test_mex.c b/srslte/lib/phch/test/pusch_encode_test_mex.c index 90d6c1aea..0f9f96b29 100644 --- a/srslte/lib/phch/test/pusch_encode_test_mex.c +++ b/srslte/lib/phch/test/pusch_encode_test_mex.c @@ -80,20 +80,19 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) - - uint32_t sf_idx=0; - if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) { + srslte_pusch_cfg_t cfg; + bzero(&cfg, sizeof(srslte_pusch_cfg_t)); + if (mexutils_read_uint32_struct(UECFG, "NSubframe", &cfg.sf_idx)) { mexErrMsgTxt("Field NSubframe not found in UE config\n"); return; } - srslte_ra_mcs_t mcs; char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation"); if (!strcmp(mod_str, "QPSK")) { - mcs.mod = SRSLTE_MOD_QPSK; + cfg.grant.mcs.mod = SRSLTE_MOD_QPSK; } else if (!strcmp(mod_str, "16QAM")) { - mcs.mod = SRSLTE_MOD_16QAM; + cfg.grant.mcs.mod = SRSLTE_MOD_16QAM; } else if (!strcmp(mod_str, "64QAM")) { - mcs.mod = SRSLTE_MOD_64QAM; + cfg.grant.mcs.mod = SRSLTE_MOD_64QAM; } else { mexErrMsgTxt("Unknown modulation\n"); return; @@ -108,27 +107,32 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) mexErrMsgTxt("Error field PRBSet not found\n"); return; } - - srslte_ra_ul_alloc_t prb_alloc; - bzero(&prb_alloc, sizeof(srslte_ra_ul_alloc_t)); - prb_alloc.L_prb = mexutils_read_f(p, &prbset); - prb_alloc.n_prb[0] = prbset[0]; - prb_alloc.n_prb[1] = prbset[0]; + cfg.grant.L_prb = mexutils_read_f(p, &prbset); + cfg.grant.n_prb[0] = prbset[0]; + cfg.grant.n_prb[1] = prbset[0]; + cfg.grant.lstart = 0; + cfg.grant.nof_symb = 2*(SRSLTE_CP_NSYMB(cell.cp)-1); + cfg.grant.M_sc = cfg.grant.L_prb*SRSLTE_NRE; + cfg.grant.M_sc_init = cfg.grant.M_sc; // FIXME: What should M_sc_init be? + cfg.grant.nof_re = cfg.grant.nof_symb*cfg.grant.M_sc; + cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod); + cfg.grant.nof_bits = cfg.grant.nof_re * cfg.grant.Qm; + free(prbset); - mexPrintf("L_prb: %d, n_prb: %d\n", prb_alloc.L_prb, prb_alloc.n_prb[2*sf_idx]); + mexPrintf("L_prb: %d, n_prb: %d\n", cfg.grant.L_prb, cfg.grant.n_prb[0]); uint8_t *trblkin = NULL; - mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin); + cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin); - srslte_harq_t harq_process; - if (srslte_harq_init(&harq_process, cell)) { - mexErrMsgTxt("Error initiating HARQ process\n"); + srslte_softbuffer_tx_t softbuffer; + if (srslte_softbuffer_tx_init(&softbuffer, cell)) { + mexErrMsgTxt("Error initiating soft buffer\n"); return; } - if (srslte_harq_setup_ul(&harq_process, mcs, 0, sf_idx, &prb_alloc)) { - mexErrMsgTxt("Error configuring HARQ process\n"); - return; + if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) { + mexErrMsgTxt("Error computing CB segmentation\n"); + return; } uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp); @@ -156,36 +160,39 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) free(tmp); - if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetCQI", &uci_data.I_offset_cqi)) { + float beta; + if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) { uci_data.I_offset_cqi = 7; + } else { + uci_data.I_offset_cqi = srslte_sch_find_Ioffset_cqi(beta); } - if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetRI", &uci_data.I_offset_ri)) { + if (mexutils_read_float_struct(PUSCHCFG, "BetaRI", &beta)) { uci_data.I_offset_ri = 2; + } else { + uci_data.I_offset_ri = srslte_sch_find_Ioffset_ri(beta); } - if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetACK", &uci_data.I_offset_ack)) { + if (mexutils_read_float_struct(PUSCHCFG, "BetaACK", &beta)) { uci_data.I_offset_ack = 0; + } else { + uci_data.I_offset_ack = srslte_sch_find_Ioffset_ack(beta); } - mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d (%d), RI_len: %d (%d)\n", mcs.tbs, + mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d (%d), RI_len: %d (%d)\n", cfg.grant.mcs.tbs, uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ack, uci_data.uci_ri_len, uci_data.uci_ri); - - mexPrintf("NofRE: %d, NofBits: %d, TBS: %d\n", harq_process.nof_re, harq_process.nof_bits, harq_process.mcs.tbs); - int r = srslte_pusch_uci_encode(&pusch, &harq_process, trblkin, uci_data, sf_symbols); + mexPrintf("I_cqi: %d, I_ri: %d, I_ack=%d\n", uci_data.I_offset_cqi, uci_data.I_offset_ri, uci_data.I_offset_ack); + + mexPrintf("NofRE: %d, NofBits: %d, TBS: %d\n", cfg.grant.nof_re, cfg.grant.nof_bits, cfg.grant.mcs.tbs); + int r = srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, sf_symbols); if (r < 0) { mexErrMsgTxt("Error encoding PUSCH\n"); return; } - uint32_t rv=0; - if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) { + if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &cfg.rv)) { mexErrMsgTxt("Field RV not found in pdsch config\n"); return; } - if (rv > 0) { - if (srslte_harq_setup_ul(&harq_process, mcs, rv, sf_idx, &prb_alloc)) { - mexErrMsgTxt("Error configuring HARQ process\n"); - return; - } - r = srslte_pusch_uci_encode(&pusch, &harq_process, trblkin, uci_data, sf_symbols); + if (cfg.rv > 0) { + r = srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, sf_symbols); if (r < 0) { mexErrMsgTxt("Error encoding PUSCH\n"); return; @@ -210,7 +217,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) mexutils_write_cf(sf_symbols, &plhs[1], nof_re, 1); } if (nlhs >= 3) { - mexutils_write_cf(pusch.z, &plhs[2], harq_process.nof_re, 1); + mexutils_write_cf(pusch.z, &plhs[2], cfg.grant.nof_re, 1); } srslte_pusch_free(&pusch); free(trblkin); diff --git a/srslte/lib/phch/test/pusch_test.c b/srslte/lib/phch/test/pusch_test.c index 086544412..01e536969 100644 --- a/srslte/lib/phch/test/pusch_test.c +++ b/srslte/lib/phch/test/pusch_test.c @@ -135,29 +135,49 @@ int main(int argc, char **argv) { cf_t *sf_symbols = NULL; int ret = -1; struct timeval t[3]; - srslte_ra_mcs_t mcs; - srslte_ra_ul_alloc_t prb_alloc; - srslte_harq_t harq_process; + srslte_pusch_cfg_t cfg; + srslte_softbuffer_tx_t softbuffer; parse_args(argc,argv); - mcs.tbs = tbs; - mcs.mod = modulation; - - bzero(&prb_alloc, sizeof(srslte_ra_ul_alloc_t)); - + bzero(&cfg, sizeof(srslte_pusch_cfg_t)); + + srslte_ra_ul_dci_t dci; + dci.freq_hop_fl = freq_hop; + if (riv < 0) { + dci.type2_alloc.L_crb = L_prb; + dci.type2_alloc.RB_start = n_prb; + } else { + srslte_ra_type2_from_riv((uint32_t) riv, &dci.type2_alloc.L_crb, &dci.type2_alloc.RB_start, cell.nof_prb, cell.nof_prb); + } + cfg.grant.mcs.tbs = tbs; + cfg.grant.mcs.mod = modulation; + + // Compute PRB allocation + if (!srslte_ul_dci_to_grant_prb_allocation(&dci, &cfg.grant, 0, cell.nof_prb)) { + cfg.grant.lstart = 0; + cfg.grant.nof_symb = 2*(SRSLTE_CP_NSYMB(cell.cp)-1); + cfg.grant.M_sc = cfg.grant.L_prb*SRSLTE_NRE; + cfg.grant.M_sc_init = cfg.grant.M_sc; // FIXME: What should M_sc_init be? + cfg.grant.nof_re = cfg.grant.nof_symb*cfg.grant.M_sc; + cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod); + cfg.grant.nof_bits = cfg.grant.nof_re * cfg.grant.Qm; + } + if (srslte_pusch_init(&pusch, cell)) { fprintf(stderr, "Error creating PDSCH object\n"); goto quit; } srslte_pusch_set_rnti(&pusch, 1234); - if (srslte_harq_init(&harq_process, cell)) { - fprintf(stderr, "Error initiating HARQ process\n"); + if (srslte_softbuffer_tx_init(&softbuffer, cell)) { + fprintf(stderr, "Error initiating soft buffer\n"); goto quit; } printf("Encoding rv_idx=%d\n",rv_idx); + cfg.rv = 0; + cfg.sf_idx = subframe; uint8_t tmp[20]; for (uint32_t i=0;i<20;i++) { @@ -167,28 +187,18 @@ int main(int argc, char **argv) { bzero(&uci_data, sizeof(srslte_uci_data_t)); uci_data.I_offset_cqi = 7; uci_data.I_offset_ri = 2; - uci_data.I_offset_ack = 0; + uci_data.I_offset_ack = 4; - uci_data.uci_cqi_len = 0; + uci_data.uci_cqi_len = 8; uci_data.uci_ri_len = 0; - uci_data.uci_ack_len = 0; + uci_data.uci_ack_len = 1; uci_data.uci_cqi = tmp; - uci_data.uci_ri = 1; - uci_data.uci_ack = 1; + uci_data.uci_ri = 0; + uci_data.uci_ack = 0; - srslte_ra_pusch_t dci; - dci.freq_hop_fl = freq_hop; - if (riv < 0) { - dci.type2_alloc.L_crb = L_prb; - dci.type2_alloc.RB_start = n_prb; - } else { - srslte_ra_type2_from_riv((uint32_t) riv, &dci.type2_alloc.L_crb, &dci.type2_alloc.RB_start, cell.nof_prb, cell.nof_prb); - } - srslte_ra_ul_alloc(&prb_alloc, &dci, 0, cell.nof_prb); - - if (srslte_harq_setup_ul(&harq_process, mcs, 0, subframe, &prb_alloc)) { - fprintf(stderr, "Error configuring HARQ process\n"); + if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) { + fprintf(stderr, "Error configuring CB segmentation\n"); goto quit; } srslte_pusch_hopping_cfg_t ul_hopping; @@ -206,34 +216,29 @@ int main(int argc, char **argv) { goto quit; } - data = malloc(sizeof(uint8_t) * mcs.tbs); + data = malloc(sizeof(uint8_t) * cfg.grant.mcs.tbs); if (!data) { perror("malloc"); goto quit; } - for (uint32_t i=0;i 0) { - if (srslte_harq_setup_ul(&harq_process, mcs, rv_idx, subframe, &prb_alloc)) { - fprintf(stderr, "Error configuring HARQ process\n"); - goto quit; - } - - if (srslte_pusch_uci_encode(&pusch, &harq_process, data, uci_data, sf_symbols)) { + cfg.rv = rv_idx; + if (srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, data, uci_data, sf_symbols)) { fprintf(stderr, "Error encoding TB\n"); exit(-1); } } - - + cf_t *scfdma = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); bzero(scfdma, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); srslte_ofdm_t fft; @@ -251,13 +256,13 @@ int main(int argc, char **argv) { ret = -1; goto quit; } else { - printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) mcs.tbs/t[0].tv_usec); + printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) cfg.grant.mcs.tbs/t[0].tv_usec); } ret = 0; quit: srslte_pusch_free(&pusch); - srslte_harq_free(&harq_process); + srslte_softbuffer_tx_free(&softbuffer); if (sf_symbols) { free(sf_symbols); diff --git a/srslte/lib/phch/test/ulsch_encode_test_mex.c b/srslte/lib/phch/test/ulsch_encode_test_mex.c index 6e3973d75..e8ed5eb9e 100644 --- a/srslte/lib/phch/test/ulsch_encode_test_mex.c +++ b/srslte/lib/phch/test/ulsch_encode_test_mex.c @@ -48,17 +48,18 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { srslte_sch_t ulsch; uint8_t *trblkin; - srslte_ra_mcs_t mcs; - srslte_ra_ul_alloc_t prb_alloc; - srslte_harq_t harq_process; - uint32_t rv; + srslte_pusch_cfg_t cfg; + srslte_softbuffer_tx_t softbuffer; srslte_uci_data_t uci_data; bzero(&uci_data, sizeof(srslte_uci_data_t)); - + uint32_t rv; + if (nrhs < NOF_INPUTS) { help(); return; } + bzero(&cfg, sizeof(srslte_pusch_cfg_t)); + if (srslte_sch_init(&ulsch)) { mexErrMsgTxt("Error initiating ULSCH\n"); return; @@ -67,12 +68,13 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) cell.nof_prb = 100; cell.id=1; cell.cp=SRSLTE_CP_NORM; - if (srslte_harq_init(&harq_process, cell)) { + + if (srslte_softbuffer_tx_init(&softbuffer, cell)) { mexErrMsgTxt("Error initiating HARQ\n"); return; } - mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin); + cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin); uci_data.uci_cqi_len = mexutils_read_uint8(CQI, &uci_data.uci_cqi); uint8_t *tmp; @@ -87,7 +89,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) } free(tmp); - mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d, RI_len: %d\n", mcs.tbs, + mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d, RI_len: %d\n", cfg.grant.mcs.tbs, uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ri_len); if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) { @@ -95,24 +97,31 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) return; } - if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetCQI", &uci_data.I_offset_cqi)) { + float beta; + if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) { uci_data.I_offset_cqi = 7; + } else { + uci_data.I_offset_cqi = srslte_sch_find_Ioffset_cqi(beta); } - if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetRI", &uci_data.I_offset_ri)) { + if (mexutils_read_float_struct(PUSCHCFG, "BetaRI", &beta)) { uci_data.I_offset_ri = 2; + } else { + uci_data.I_offset_ri = srslte_sch_find_Ioffset_ri(beta); } - if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetACK", &uci_data.I_offset_ack)) { + if (mexutils_read_float_struct(PUSCHCFG, "BetaACK", &beta)) { uci_data.I_offset_ack = 0; + } else { + uci_data.I_offset_ack = srslte_sch_find_Ioffset_ack(beta); } char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation"); if (!strcmp(mod_str, "QPSK")) { - mcs.mod = SRSLTE_MOD_QPSK; + cfg.grant.mcs.mod = SRSLTE_MOD_QPSK; } else if (!strcmp(mod_str, "16QAM")) { - mcs.mod = SRSLTE_MOD_16QAM; + cfg.grant.mcs.mod = SRSLTE_MOD_16QAM; } else if (!strcmp(mod_str, "64QAM")) { - mcs.mod = SRSLTE_MOD_64QAM; + cfg.grant.mcs.mod = SRSLTE_MOD_64QAM; } else { mexErrMsgTxt("Unknown modulation\n"); return; @@ -128,49 +137,56 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) return; } - prb_alloc.L_prb = mexutils_read_f(p, &prbset); - prb_alloc.n_prb[0] = prbset[0]; - prb_alloc.n_prb[1] = prbset[0]; + cfg.grant.L_prb = mexutils_read_f(p, &prbset); + cfg.grant.n_prb[0] = prbset[0]; + cfg.grant.n_prb[1] = prbset[0]; free(prbset); - - mexPrintf("Q_m: %d, NPRB: %d, RV: %d\n", srslte_mod_bits_x_symbol(mcs.mod), prb_alloc.L_prb, rv); + cfg.grant.L_prb = mexutils_read_f(p, &prbset); + cfg.grant.n_prb[0] = prbset[0]; + cfg.grant.n_prb[1] = prbset[0]; + cfg.grant.lstart = 0; + cfg.grant.nof_symb = 2*(SRSLTE_CP_NSYMB(cell.cp)-1); + cfg.grant.M_sc = cfg.grant.L_prb*SRSLTE_NRE; + cfg.grant.M_sc_init = cfg.grant.M_sc; // FIXME: What should M_sc_init be? + cfg.grant.nof_re = cfg.grant.nof_symb*cfg.grant.M_sc; + cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod); + cfg.grant.nof_bits = cfg.grant.nof_re * cfg.grant.Qm; - if (srslte_harq_setup_ul(&harq_process, mcs, 0, 0, &prb_alloc)) { + mexPrintf("Q_m: %d, NPRB: %d, RV: %d\n", srslte_mod_bits_x_symbol(cfg.grant.mcs.mod), cfg.grant.L_prb, cfg.rv); + + if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) { mexErrMsgTxt("Error configuring HARQ process\n"); return; } - uint8_t *q_bits = srslte_vec_malloc(harq_process.nof_bits * sizeof(uint8_t)); + uint8_t *q_bits = srslte_vec_malloc(cfg.grant.nof_bits * sizeof(uint8_t)); if (!q_bits) { return; } - uint8_t *g_bits = srslte_vec_malloc(harq_process.nof_bits * sizeof(uint8_t)); + uint8_t *g_bits = srslte_vec_malloc(cfg.grant.nof_bits * sizeof(uint8_t)); if (!g_bits) { return; } - if (srslte_ulsch_uci_encode(&ulsch, &harq_process, trblkin, uci_data, g_bits, q_bits)) + if (srslte_ulsch_uci_encode(&ulsch, &cfg, &softbuffer, trblkin, uci_data, g_bits, q_bits)) { mexErrMsgTxt("Error encoding TB\n"); return; } if (rv > 0) { - if (srslte_harq_setup_ul(&harq_process, mcs, rv, 0, &prb_alloc)) { - mexErrMsgTxt("Error configuring HARQ process\n"); - return; - } - if (srslte_ulsch_uci_encode(&ulsch, &harq_process, trblkin, uci_data, g_bits, q_bits)) { + cfg.rv = rv; + if (srslte_ulsch_uci_encode(&ulsch, &cfg, &softbuffer, trblkin, uci_data, g_bits, q_bits)) { mexErrMsgTxt("Error encoding TB\n"); return; } } if (nlhs >= 1) { - mexutils_write_uint8(q_bits, &plhs[0], harq_process.nof_bits, 1); + mexutils_write_uint8(q_bits, &plhs[0], cfg.grant.nof_bits, 1); } srslte_sch_free(&ulsch); - srslte_harq_free(&harq_process); + srslte_softbuffer_tx_free(&softbuffer); free(trblkin); free(g_bits); diff --git a/srslte/lib/sync/test/pss_file.c b/srslte/lib/sync/test/pss_file.c index 5005b06d4..75b0497bc 100644 --- a/srslte/lib/sync/test/pss_file.c +++ b/srslte/lib/sync/test/pss_file.c @@ -286,7 +286,7 @@ int main(int argc, char **argv) { frame_cnt++; printf("[%5d]: Pos: %5d, PSR: %4.1f (~%4.1f) Pdet: %4.2f, " - "FA: %4.2f, CFO: %+4.1f KHz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f\%\r", + "FA: %4.2f, CFO: %+4.1f KHz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f%%\r", frame_cnt, peak_idx, peak_value, mean_peak, diff --git a/srslte/lib/sync/test/pss_usrp.c b/srslte/lib/sync/test/pss_usrp.c index dad721dc6..d88a2f127 100644 --- a/srslte/lib/sync/test/pss_usrp.c +++ b/srslte/lib/sync/test/pss_usrp.c @@ -296,7 +296,7 @@ int main(int argc, char **argv) { frame_cnt++; printf("[%5d]: Pos: %5d, PSR: %4.1f (~%4.1f) Pdet: %4.2f, " - "FA: %4.2f, CFO: %+4.1f KHz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f\%\r", + "FA: %4.2f, CFO: %+4.1f KHz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f%%\r", frame_cnt, peak_idx, peak_value, mean_peak, diff --git a/srslte/lib/ue/src/ue_dl.c b/srslte/lib/ue/src/ue_dl.c index 08151509b..8d5e3e7bf 100644 --- a/srslte/lib/ue/src/ue_dl.c +++ b/srslte/lib/ue/src/ue_dl.c @@ -84,11 +84,9 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q, fprintf(stderr, "Error creating PDSCH object\n"); goto clean_exit; } - for (uint32_t i=0;iharq_process[i], q->cell)) { - fprintf(stderr, "Error initiating HARQ process\n"); - goto clean_exit; - } + if (srslte_softbuffer_rx_init(&q->softbuffer, q->cell)) { + fprintf(stderr, "Error initiating soft buffer\n"); + goto clean_exit; } q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); if (!q->sf_symbols) { @@ -125,9 +123,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) { srslte_phich_free(&q->phich); srslte_pdcch_free(&q->pdcch); srslte_pdsch_free(&q->pdsch); - for (uint32_t i=0;iharq_process[i]); - } + srslte_softbuffer_rx_free(&q->softbuffer); if (q->sf_symbols) { free(q->sf_symbols); } @@ -136,9 +132,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) { free(q->ce[i]); } } - bzero(q, sizeof(srslte_ue_dl_t)); - } } @@ -152,7 +146,8 @@ void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q, uint16_t rnti) { } void srslte_ue_dl_reset(srslte_ue_dl_t *q) { - srslte_harq_reset(&q->harq_process[0]); + srslte_softbuffer_rx_reset(&q->softbuffer); + bzero(&q->pdsch_cfg, sizeof(srslte_pdsch_cfg_t)); } srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1,SRSLTE_DCI_FORMAT1A}; // SRSLTE_DCI_FORMAT1B should go here also @@ -212,22 +207,26 @@ int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_ int ret = SRSLTE_ERROR; q->nof_detected++; - if (srslte_dci_msg_to_ra_dl(dci_msg, rnti, q->cell, cfi, &q->ra_dl)) { + + srslte_ra_dl_dci_t dl_dci; + + if (srslte_dci_msg_to_dl_grant(dci_msg, rnti, q->cell, cfi, sf_idx, &dl_dci, &q->pdsch_cfg.grant)) { fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n"); return SRSLTE_ERROR; } - - if (rnti != SRSLTE_SIRNTI) { - rvidx = q->ra_dl.rv_idx; + if (srslte_cbsegm(&q->pdsch_cfg.cb_segm, q->pdsch_cfg.grant.mcs.tbs)) { + fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", q->pdsch_cfg.grant.mcs.tbs); + return SRSLTE_ERROR; } - if (srslte_harq_setup_dl(&q->harq_process[0], q->ra_dl.mcs, rvidx, sf_idx, &q->ra_dl.prb_alloc)) { - fprintf(stderr, "Error configuring HARQ process\n"); - return SRSLTE_ERROR; + q->pdsch_cfg.sf_idx = sf_idx; + if (rnti == SRSLTE_SIRNTI) { + q->pdsch_cfg.rv = rvidx; + } else { + q->pdsch_cfg.rv = dl_dci.rv_idx; } - if (q->harq_process[0].mcs.mod > 0 && q->harq_process[0].mcs.tbs >= 0) { - ret = srslte_pdsch_decode_rnti(&q->pdsch, &q->harq_process[0], q->sf_symbols, - q->ce, 0, - rnti, data); + if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) { + ret = srslte_pdsch_decode_rnti(&q->pdsch, &q->pdsch_cfg, &q->softbuffer, + q->sf_symbols, q->ce, 0, rnti, data); if (ret == SRSLTE_ERROR) { q->pkt_errors++; @@ -236,7 +235,7 @@ int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_ } else if (ret == SRSLTE_SUCCESS) { if (SRSLTE_VERBOSE_ISINFO()) { INFO("Decoded Message: ", 0); - srslte_vec_fprint_hex(stdout, data, q->ra_dl.mcs.tbs); + srslte_vec_fprint_hex(stdout, data, q->pdsch_cfg.grant.mcs.tbs); } } q->pkts_total++; @@ -317,7 +316,7 @@ int srslte_ue_dl_decode_rnti_rv(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, u } if (found_dci == 1 && ret == SRSLTE_SUCCESS) { - return q->ra_dl.mcs.tbs; + return q->pdsch_cfg.grant.mcs.tbs; } else { return 0; } diff --git a/srslte/lib/ue/src/ue_ul.c b/srslte/lib/ue/src/ue_ul.c index 3f0668108..466b1ab91 100644 --- a/srslte/lib/ue/src/ue_ul.c +++ b/srslte/lib/ue/src/ue_ul.c @@ -39,7 +39,7 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q, - srslte_cell_t cell) + srslte_cell_t cell) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -74,11 +74,9 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q, 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"); - goto clean_exit; - } + if (srslte_softbuffer_tx_init(&q->softbuffer, q->cell)) { + fprintf(stderr, "Error initiating soft buffer\n"); + goto clean_exit; } if (srslte_refsignal_ul_init(&q->dmrs, cell)) { fprintf(stderr, "Error initiating srslte_refsignal_ul\n"); @@ -113,9 +111,8 @@ void srslte_ue_ul_free(srslte_ue_ul_t *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]); - } + srslte_softbuffer_tx_free(&q->softbuffer); + srslte_cfo_free(&q->cfo); srslte_refsignal_ul_free(&q->dmrs); @@ -154,14 +151,14 @@ void srslte_ue_ul_set_rnti(srslte_ue_ul_t *q, uint16_t rnti) { } void srslte_ue_ul_reset(srslte_ue_ul_t *q) { - srslte_harq_reset(&q->harq_process[0]); + srslte_softbuffer_tx_reset(&q->softbuffer); } 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_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); @@ -274,11 +271,7 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data, } 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); + float norm_factor = (float) q->cell.nof_prb/10; 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)); @@ -288,64 +281,84 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data, 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) +int srslte_ue_ul_pusch_encode(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, uint8_t *data, uint32_t sf_idx, uint32_t rv, cf_t *output_signal) { srslte_uci_data_t uci_data; bzero(&uci_data, sizeof(srslte_uci_data_t)); - return srslte_ue_ul_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, q->current_rnti, output_signal); + return srslte_ue_ul_pusch_uci_encode_rnti(q, grant, data, uci_data, sf_idx, rv, q->current_rnti, output_signal); } -int srslte_ue_ul_pusch_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, uint32_t sf_idx, uint16_t rnti, cf_t *output_signal) +int srslte_ue_ul_pusch_encode_rnti(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, uint8_t *data, uint32_t sf_idx, uint32_t rv, uint16_t rnti, cf_t *output_signal) { srslte_uci_data_t uci_data; bzero(&uci_data, sizeof(srslte_uci_data_t)); - return srslte_ue_ul_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, rnti, output_signal); + return srslte_ue_ul_pusch_uci_encode_rnti(q, grant, data, uci_data, sf_idx, rv,rnti, output_signal); } -int srslte_ue_ul_pusch_uci_encode(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, srslte_uci_data_t uci_data, uint32_t sf_idx, cf_t *output_signal) +int srslte_ue_ul_pusch_uci_encode(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, uint8_t *data, srslte_uci_data_t uci_data, uint32_t sf_idx, uint32_t rv, cf_t *output_signal) { - return srslte_ue_ul_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, q->current_rnti, output_signal); + return srslte_ue_ul_pusch_uci_encode_rnti(q, grant, data, uci_data, sf_idx, rv, q->current_rnti, output_signal); } -int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, srslte_uci_data_t uci_data, - uint32_t sf_idx, uint16_t rnti, - cf_t *output_signal) +int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, + uint8_t *data, srslte_uci_data_t uci_data, + uint32_t sf_idx, uint32_t rv, uint16_t rnti, + cf_t *output_signal) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && - ra_ul != NULL && + grant != NULL && data != NULL && output_signal != NULL) { - if (ra_ul->prb_alloc.L_prb == 0) { + if (grant->L_prb == 0) { fprintf(stderr, "Invalid UL PRB allocation (L_prb=0)\n"); return ret; } ret = SRSLTE_ERROR; - if (srslte_harq_setup_ul(&q->harq_process[0], ra_ul->mcs, ra_ul->rv_idx, sf_idx, &ra_ul->prb_alloc)) { - fprintf(stderr, "Error configuring HARQ process\n"); - return ret; - } - - if (srslte_pusch_encode_rnti(&q->pusch, &q->harq_process[0], data, rnti, q->sf_symbols)) { + memcpy(&q->pusch_cfg.grant, grant, sizeof(srslte_ra_ul_grant_t)); + q->pusch_cfg.sf_idx = sf_idx; + q->pusch_cfg.rv = rv; + q->pusch_cfg.cp = q->cell.cp; + srslte_cbsegm(&q->pusch_cfg.cb_segm, grant->mcs.tbs); + + return srslte_ue_ul_pusch_encode_cfg(q, &q->pusch_cfg, data, uci_data, rnti, output_signal); + } + return ret; +} + +int srslte_ue_ul_pusch_encode_cfg(srslte_ue_ul_t *q, srslte_pusch_cfg_t *cfg, + uint8_t *data, srslte_uci_data_t uci_data, + uint16_t rnti, + cf_t *output_signal) +{ + + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + cfg != NULL && + data != NULL && + output_signal != NULL) + { + if (srslte_pusch_encode_rnti(&q->pusch, cfg, &q->softbuffer, data, rnti, q->sf_symbols)) { fprintf(stderr, "Error encoding TB\n"); return ret; } // FIXME: Pregenerate for all possible number of prb - if (srslte_refsignal_dmrs_pusch_gen(&q->dmrs, q->harq_process[0].ul_alloc.L_prb, sf_idx, q->refsignal)) + if (srslte_refsignal_dmrs_pusch_gen(&q->dmrs, cfg->grant.L_prb, cfg->sf_idx, q->refsignal)) { fprintf(stderr, "Error generating PUSCH DRMS signals\n"); return ret; } srslte_refsignal_dmrs_pusch_put(&q->dmrs, q->refsignal, - q->harq_process[0].ul_alloc.L_prb, - q->harq_process[0].ul_alloc.n_prb_tilde, - q->sf_symbols); + cfg->grant.L_prb, + cfg->grant.n_prb_tilde, + q->sf_symbols); srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); @@ -354,7 +367,7 @@ int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ } if (q->normalize_en) { - float norm_factor = (float) q->cell.nof_prb/10/sqrtf(q->harq_process[0].ul_alloc.L_prb); + float norm_factor = (float) q->cell.nof_prb/10/sqrtf(cfg->grant.L_prb); srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); } diff --git a/srslte/lib/ue_itf/src/dl_buffer.cc b/srslte/lib/ue_itf/src/dl_buffer.cc index a57f2275b..aed1d5dbf 100644 --- a/srslte/lib/ue_itf/src/dl_buffer.cc +++ b/srslte/lib/ue_itf/src/dl_buffer.cc @@ -81,7 +81,7 @@ bool dl_buffer::recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_t return ret; } -bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, sched_grant *grant) +bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, ul_sched_grant *grant) { if (signal_buffer) { if (!sf_symbols_and_ce_done) { @@ -102,19 +102,12 @@ bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, sched_grant *grant) return false; } - if (srslte_dci_msg_to_ra_ul(&dci_msg, cell.nof_prb, - params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET), - (srslte_ra_pusch_t*) grant->get_grant_ptr())) - { - return false; - } - - return true; + return grant->create_from_dci(&dci_msg, cell, 0, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET)); } } -bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant) +bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, dl_sched_grant *grant) { if (signal_buffer && is_ready()) { INFO("DL Buffer TTI %d: Getting DL grant\n", tti); @@ -145,18 +138,11 @@ 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; - } - - return true; + return grant->create_from_dci(&dci_msg, cell, cfi, tti%10, srslte_ue_dl_get_ncce(&ue_dl)); } } -bool dl_buffer::decode_ack(sched_grant pusch_grant) +bool dl_buffer::decode_ack(ul_sched_grant *grant) { if (signal_buffer && is_ready()) { if (!sf_symbols_and_ce_done) { @@ -166,13 +152,11 @@ bool dl_buffer::decode_ack(sched_grant pusch_grant) sf_symbols_and_ce_done = true; } - srslte_ra_pusch_t *ra_ul = (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr(); - - return srslte_ue_dl_decode_phich(&ue_dl, tti%10, ra_ul->prb_alloc.n_prb[0], ra_ul->n_dmrs); + return srslte_ue_dl_decode_phich(&ue_dl, tti%10, grant->get_I_lowest(), grant->get_n_dmrs()); } } -bool dl_buffer::decode_data(sched_grant pdsch_grant, uint8_t *payload) +bool dl_buffer::decode_data(dl_sched_grant *grant, uint8_t *payload) { if (signal_buffer && is_ready()) { INFO("DL Buffer TTI %d: Decoding PDSCH\n", tti); @@ -184,18 +168,13 @@ bool dl_buffer::decode_data(sched_grant pdsch_grant, uint8_t *payload) sf_symbols_and_ce_done = true; } - srslte_ra_pdsch_t *ra_dl = (srslte_ra_pdsch_t*) pdsch_grant.get_grant_ptr(); - if (srslte_harq_setup_dl(&ue_dl.harq_process[0], ra_dl->mcs, - ra_dl->rv_idx, tti%10, &ra_dl->prb_alloc)) { - fprintf(stderr, "Error configuring HARQ process\n"); - return SRSLTE_ERROR; - } - if (ue_dl.harq_process[0].mcs.mod > 0 && ue_dl.harq_process[0].mcs.tbs >= 0) { - int ret = srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.harq_process[0], ue_dl.sf_symbols, - ue_dl.ce, 0, pdsch_grant.get_rnti(), payload); + grant->get_pdsch_cfg(tti%10, &ue_dl.pdsch_cfg); + if (ue_dl.pdsch_cfg.grant.mcs.mod > 0 && ue_dl.pdsch_cfg.grant.mcs.tbs >= 0) { + int ret = srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.pdsch_cfg, &ue_dl.softbuffer, ue_dl.sf_symbols, + ue_dl.ce, 0, grant->get_rnti(), payload); if (SRSLTE_VERBOSE_ISINFO()) { - srslte_vec_save_file((char*) "pdsch_d", ue_dl.pdsch.d, ue_dl.harq_process[0].nof_re*sizeof(cf_t)); + srslte_vec_save_file((char*) "pdsch_d", ue_dl.pdsch.d, ue_dl.pdsch_cfg.grant.nof_re*sizeof(cf_t)); } if (ret == SRSLTE_SUCCESS) { return true; diff --git a/srslte/lib/ue_itf/src/phy.cc b/srslte/lib/ue_itf/src/phy.cc index 6c564dfb8..6865bb983 100644 --- a/srslte/lib/ue_itf/src/phy.cc +++ b/srslte/lib/ue_itf/src/phy.cc @@ -102,15 +102,10 @@ void phy::set_timeadv(uint32_t ta_cmd) { INFO("Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, time_adv_sec*1e6); } -void phy::rar_ul_grant(uint32_t rba, uint32_t trunc_mcs, bool hopping_flag, sched_grant *grant) +void phy::rar_ul_grant(srslte_dci_rar_grant_t *rar, ul_sched_grant *grant) { uint32_t n_ho = params_db.get_param(phy_params::PUSCH_HOPPING_OFFSET); - srslte_ra_pusch_t *ra_pusch = (srslte_ra_pusch_t*) grant->get_grant_ptr(); - srslte_dci_rar_to_ra_ul(rba, trunc_mcs, hopping_flag, cell.nof_prb, ra_pusch); - srslte_ra_ul_alloc(&ra_pusch->prb_alloc, ra_pusch, n_ho, cell.nof_prb); - if (SRSLTE_VERBOSE_ISINFO()) { - srslte_ra_pusch_fprint(stdout, ra_pusch, cell.nof_prb); - } + grant->create_from_rar(rar, cell, 0, params_db.get_param(phy_params::PUSCH_HOPPING_OFFSET)); } void phy::set_param(phy_params::phy_param_t param, int64_t value) { diff --git a/srslte/lib/ue_itf/src/prach.cc b/srslte/lib/ue_itf/src/prach.cc index 9af219e2c..2bb573a7b 100644 --- a/srslte/lib/ue_itf/src/prach.cc +++ b/srslte/lib/ue_itf/src/prach.cc @@ -51,7 +51,7 @@ void prach::free_cell() free(signal_buffer); } srslte_cfo_free(&cfo_h); - srslte_prach_free(&prach); + srslte_prach_free(&prach_obj); } } @@ -60,7 +60,7 @@ bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_) cell = cell_; params_db = params_db_; preamble_idx = -1; - if (srslte_prach_init(&prach, srslte_symbol_sz(cell.nof_prb), + if (srslte_prach_init(&prach_obj, srslte_symbol_sz(cell.nof_prb), srslte_prach_get_preamble_format(params_db->get_param(phy_params::PRACH_CONFIG_INDEX)), params_db->get_param(phy_params::PRACH_ROOT_SEQ_IDX), params_db->get_param(phy_params::PRACH_HIGH_SPEED_FLAG)?true:false, @@ -68,13 +68,13 @@ bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_) return false; } - len = prach.N_seq + prach.N_cp; + len = prach_obj.N_seq + prach_obj.N_cp; for (uint32_t i=0;i<64;i++) { buffer[i] = (cf_t*) srslte_vec_malloc(len*sizeof(cf_t)); if(!buffer[i]) { return false; } - if(srslte_prach_gen(&prach, i, params_db->get_param(phy_params::PRACH_FREQ_OFFSET), buffer[i])){ + if(srslte_prach_gen(&prach_obj, i, params_db->get_param(phy_params::PRACH_FREQ_OFFSET), buffer[i])){ return false; } } diff --git a/srslte/lib/ue_itf/src/sched_grant.cc b/srslte/lib/ue_itf/src/sched_grant.cc deleted file mode 100644 index ac2c58447..000000000 --- a/srslte/lib/ue_itf/src/sched_grant.cc +++ /dev/null @@ -1,147 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2014 The srsLTE Developers. See the - * COPYRIGHT file at the top-level directory of this distribution. - * - * \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 Lesser 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 Lesser General Public License for more details. - * - * A copy of the GNU Lesser 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 -#include -#include -#include "srslte/srslte.h" - -#include "srslte/ue_itf/sched_grant.h" - -namespace srslte { -namespace ue { - - sched_grant::sched_grant(direction_t direction, uint16_t rnti_) - { - rnti = rnti_; - dir = direction; - } - - /* Returns the RNTI associated with the UL/DL scheduling grant */ - uint16_t sched_grant::get_rnti() { - return rnti; - } - - uint32_t sched_grant::get_rv() { - if (dir == UPLINK) { - return ul_grant.rv_idx; - } else { - return dl_grant.rv_idx; - } - } - - uint32_t sched_grant::get_tbs() { - if (dir == UPLINK) { - return ul_grant.mcs.tbs; - } else { - return dl_grant.mcs.tbs; - } - } - - uint32_t sched_grant::get_ncce() - { - return ncce; - } - - bool srslte::ue::sched_grant::is_sps_release() - { - return false; - } - - void sched_grant::set_ncce(uint32_t ncce_) - { - ncce = ncce_; - } - - uint32_t sched_grant::get_current_tx_nb() - { - return current_tx_nb; - } - - void sched_grant::set_current_tx_nb(uint32_t current_tx_nb_) - { - current_tx_nb = current_tx_nb_; - } - - - void sched_grant::set_rv(uint32_t rv) { - if (dir == UPLINK) { - ul_grant.rv_idx = rv; - } else { - dl_grant.rv_idx = rv; - } - } - - bool sched_grant::get_ndi() { - if (dir == UPLINK) { - return ul_grant.ndi; - } else { - return dl_grant.ndi; - } - } - - void sched_grant::set_ndi(bool value) { - if (dir == UPLINK) { - ul_grant.ndi = value; - } else { - dl_grant.ndi = value; - } - } - - bool sched_grant::get_cqi_request() { - if (dir == UPLINK) { - return ul_grant.ndi; - } else { - return dl_grant.ndi; - } - } - - int sched_grant::get_harq_process() { - if (dir == UPLINK) { - return -1; - } else { - return dl_grant.harq_process; - } - } - - bool sched_grant::is_uplink() { - return dir == UPLINK; - } - - bool sched_grant::is_downlink() { - return dir == DOWNLINK; - } - void* sched_grant::get_grant_ptr() { - if (is_uplink()) { - return (void*) &ul_grant; - } else { - return (void*) &dl_grant; - } - } -} // namespace ue -} // namespace srslte - diff --git a/srslte/lib/ue_itf/src/ul_buffer.cc b/srslte/lib/ue_itf/src/ul_buffer.cc index da8ceac9e..77edf9807 100644 --- a/srslte/lib/ue_itf/src/ul_buffer.cc +++ b/srslte/lib/ue_itf/src/ul_buffer.cc @@ -63,12 +63,12 @@ void ul_buffer::free_cell() { } } -bool ul_buffer::generate_ack(bool ack, sched_grant last_dl_grant) +bool ul_buffer::generate_ack(bool ack, dl_sched_grant *last_dl_grant) { uci_data.uci_ack_len = 1; uci_data.uci_ack = ack?1:0; uci_pending = true; - last_n_cce = last_dl_grant.get_ncce(); + last_n_cce = last_dl_grant->get_ncce(); } bool ul_buffer::generate_ack(bool ack[2]) @@ -89,11 +89,11 @@ bool ul_buffer::uci_ready() { } bool ul_buffer::generate_data() { - sched_grant dummy(sched_grant::DOWNLINK, 0); - return generate_data(dummy, NULL); + ul_sched_grant dummy(0); + return generate_data(&dummy, NULL); } -bool ul_buffer::generate_data(sched_grant pusch_grant, +bool ul_buffer::generate_data(ul_sched_grant *grant, uint8_t *payload) { if (is_ready()) { @@ -115,7 +115,7 @@ bool ul_buffer::generate_data(sched_grant pusch_grant, pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF : pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF; pusch_hopping.hopping_offset = params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET); - pusch_hopping.current_tx_nb = pusch_grant.get_current_tx_nb(); + pusch_hopping.current_tx_nb = grant->get_current_tx_nb(); srslte_pucch_cfg_t pucch_cfg; bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t)); @@ -145,10 +145,12 @@ bool ul_buffer::generate_data(sched_grant pusch_grant, 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); + + grant->to_pusch_cfg(tti%10, cell.cp, &pusch_cfg); + n = srslte_ue_ul_pusch_encode_cfg(&ue_ul, &pusch_cfg, + payload, uci_data, + grant->get_rnti(), + signal_buffer); } else { n = srslte_ue_ul_pucch_encode(&ue_ul, uci_data, tti&10, signal_buffer); } 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 937bce218..241a49d6c 100644 --- a/srslte/lib/ue_itf/test/ue_itf_test_prach.cc +++ b/srslte/lib/ue_itf/test/ue_itf_test_prach.cc @@ -214,8 +214,9 @@ void config_phy() { phy.set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_HOPPING_EN, 0); phy.set_param(srslte::ue::phy_params::PUSCH_RS_SEQUENCE_HOPPING_EN, 0); phy.set_param(srslte::ue::phy_params::PUSCH_RS_CYCLIC_SHIFT, 0); + phy.set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_ASSIGNMENT, 0); phy.set_param(srslte::ue::phy_params::PUSCH_HOPPING_OFFSET, 0); - + phy.set_param(srslte::ue::phy_params::PUCCH_BETA, 10); phy.set_param(srslte::ue::phy_params::PUCCH_DELTA_SHIFT, 1); phy.set_param(srslte::ue::phy_params::PUCCH_CYCLIC_SHIFT, 0); @@ -253,7 +254,7 @@ void run_tti(uint32_t tti) { } } if (state == RAR) { - srslte::ue::sched_grant rar_grant(srslte::ue::sched_grant::DOWNLINK, 2); + srslte::ue::dl_sched_grant rar_grant(2); int ra_tti = phy.get_prach_transmitted_tti(); if (ra_tti > 0) { INFO("PRACH was transmitted at %d\n", ra_tti); @@ -265,7 +266,7 @@ 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_data(rar_grant, payload)) { + if (dl_buffer->decode_data(&rar_grant, payload)) { rar_unpack(payload, &rar_msg); if (!prog_args.continous) { printf("Received RAR for preamble %d\n", rar_msg.RAPID); @@ -283,8 +284,12 @@ void run_tti(uint32_t tti) { phy.set_timeadv_rar(rar_msg.timing_adv_cmd); // Generate Msg3 grant - srslte::ue::sched_grant connreq_grant(srslte::ue::sched_grant::UPLINK, rar_msg.temp_c_rnti); - phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant); + srslte::ue::ul_sched_grant connreq_grant(rar_msg.temp_c_rnti); + srslte_dci_rar_grant_t rar_grant; + rar_grant.rba = rar_msg.rba; + rar_grant.trunc_mcs = rar_msg.mcs; + rar_grant.hopping_flag = rar_msg.hopping_flag; + phy.rar_ul_grant(&rar_grant, &connreq_grant); // Pack Msg3 bits srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs()); @@ -296,7 +301,7 @@ void run_tti(uint32_t tti) { if (ul_buffer) { connreq_grant.set_rv(0); 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; @@ -318,11 +323,15 @@ void run_tti(uint32_t tti) { uint32_t interval_conreq = interval(tti, conreq_tti); if (interval_conreq == 4) { - srslte::ue::sched_grant connreq_grant(srslte::ue::sched_grant::UPLINK, rar_msg.temp_c_rnti); - phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant); + srslte::ue::ul_sched_grant connreq_grant(rar_msg.temp_c_rnti); + srslte_dci_rar_grant_t rar_grant; + rar_grant.rba = rar_msg.rba; + rar_grant.trunc_mcs = rar_msg.mcs; + rar_grant.hopping_flag = rar_msg.hopping_flag; + phy.rar_ul_grant(&rar_grant, &connreq_grant); // Decode PHICH from Connection Request - if (!dl_buffer->decode_ack(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()); @@ -339,7 +348,7 @@ 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_data(connreq_grant, payload); + ul_buffer->generate_data(&connreq_grant, payload); // Save transmission time conreq_tti = ul_buffer->tti; @@ -354,13 +363,13 @@ void run_tti(uint32_t tti) { } } if (state == CONNSETUP) { - srslte::ue::sched_grant conn_setup_grant(srslte::ue::sched_grant::DOWNLINK, rar_msg.temp_c_rnti); + srslte::ue::dl_sched_grant conn_setup_grant(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)) { + if (dl_buffer->decode_data(&conn_setup_grant, payload)) { nof_rx_connsetup++; state = RA; nof_rtx_connsetup=0; @@ -375,7 +384,7 @@ void run_tti(uint32_t 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); + ul_buffer->generate_ack(connsetup_recv, &conn_setup_grant); if (!prog_args.continous) { while(ul_buffer->uci_ready()) { sleep(1); 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 ab041893a..69100d0fe 100644 --- a/srslte/lib/ue_itf/test/ue_itf_test_sib1.cc +++ b/srslte/lib/ue_itf/test/ue_itf_test_sib1.cc @@ -92,7 +92,7 @@ uint8_t payload[1024]; // This is the MAC implementation void run_tti(uint32_t tti) { - srslte::ue::sched_grant grant = srslte::ue::sched_grant(srslte::ue::sched_grant::DOWNLINK, SRSLTE_SIRNTI); + srslte::ue::dl_sched_grant grant(SRSLTE_SIRNTI); INFO("MAC running tti: %d\n", tti); // SIB1 is scheduled in subframe #5 of even frames @@ -106,9 +106,9 @@ void run_tti(uint32_t tti) { total_dci++; // MAC sets RV grant.set_rv(((uint32_t) ceilf((float)3*((phy.tti_to_SFN(tti)/2)%4)/2))%4); - + // Decode packet - if (!buffer->decode_data(grant, payload)) { + if (!buffer->decode_data(&grant, payload)) { total_errors++; } } @@ -141,6 +141,12 @@ int main(int argc, char *argv[]) // Give it time to create thread sleep(1); + // Set default parameters + phy.set_param(srslte::ue::phy_params::PRACH_CONFIG_INDEX, 0); + phy.set_param(srslte::ue::phy_params::PRACH_ROOT_SEQ_IDX, 0); + phy.set_param(srslte::ue::phy_params::PRACH_HIGH_SPEED_FLAG, 0); + phy.set_param(srslte::ue::phy_params::PRACH_ZC_CONFIG, 1); + // Set RX freq and gain phy.get_radio()->set_rx_freq(prog_args.uhd_freq); phy.get_radio()->set_rx_gain(prog_args.uhd_gain); diff --git a/srslte/tutorial_examples/simple_tx.c b/srslte/tutorial_examples/simple_tx.c index 49ba6412a..3ee4729ea 100644 --- a/srslte/tutorial_examples/simple_tx.c +++ b/srslte/tutorial_examples/simple_tx.c @@ -209,12 +209,12 @@ int main(int argc, char **argv) { srslte_modem_table_lte(&modulator, modulation, false); srslte_tcod_t turbocoder; - srslte_tcod_init(&turbocoder, MAX_LONG_CB); + srslte_tcod_init(&turbocoder, SRSLTE_TCOD_MAX_LEN_CB); srslte_dft_precoding_t dft_precod; srslte_dft_precoding_init(&dft_precod, 12); - nbits = srslte_find_cb_index(sf_n_samples/8/srslte_mod_bits_x_symbol(modulation)/3 - 12); + nbits = srslte_cbsegm_cbindex(sf_n_samples/8/srslte_mod_bits_x_symbol(modulation)/3 - 12); uint32_t ncoded_bits = sf_n_samples/8/srslte_mod_bits_x_symbol(modulation); uint8_t *data = malloc(sizeof(uint8_t)*nbits); diff --git a/srslte/tutorial_examples/ue_rx.c b/srslte/tutorial_examples/ue_rx.c index 3ec37ddbe..621668cac 100644 --- a/srslte/tutorial_examples/ue_rx.c +++ b/srslte/tutorial_examples/ue_rx.c @@ -368,8 +368,8 @@ int main(int argc, char **argv) { float rsrp=0.0, rsrq=0.0, snr=0.0; bool decode_pdsch; int pdcch_tx=0; - srslte_ra_pdsch_t old_ra_dl; - bzero(&old_ra_dl, sizeof(srslte_ra_pdsch_t)); + srslte_ra_dl_dci_t old_ra_dl; + bzero(&old_ra_dl, sizeof(srslte_ra_dl_dci_t)); ue_sync.correct_cfo = prog_args.enable_cfo; @@ -418,8 +418,8 @@ int main(int argc, char **argv) { n = srslte_ue_dl_decode_rnti_rv(&ue_dl, &sf_buffer[prog_args.time_offset], data_packed, srslte_ue_sync_get_sfidx(&ue_sync), SRSLTE_SIRNTI, ((int) ceilf((float)3*(((sfn)/2)%4)/2))%4); } - if (memcmp(&ue_dl.ra_dl, &old_ra_dl, sizeof(srslte_ra_pdsch_t))) { - memcpy(&old_ra_dl, &ue_dl.ra_dl, sizeof(srslte_ra_pdsch_t)); + if (memcmp(&ue_dl.ra_dl, &old_ra_dl, sizeof(srslte_ra_dl_dci_t))) { + memcpy(&old_ra_dl, &ue_dl.ra_dl, sizeof(srslte_ra_dl_dci_t)); fflush(stdout);printf("\nCFI:\t%d\n", ue_dl.cfi); printf("Format: %s\n", srslte_dci_format_string(ue_dl.dci_format)); srslte_ra_pdsch_fprint(stdout, &old_ra_dl, cell.nof_prb);