mirror of https://github.com/pvnis/srsRAN_4G.git
PSSCH implementation
parent
4e283ec942
commit
baf0ad5bf4
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2013-2020 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsLTE.
|
||||
*
|
||||
* srsLTE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsLTE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSLTE_PSSCH_H
|
||||
#define SRSLTE_PSSCH_H
|
||||
|
||||
#include "srslte/phy/common/phy_common_sl.h"
|
||||
#include "srslte/phy/dft/dft_precoding.h"
|
||||
#include "srslte/phy/fec/crc.h"
|
||||
#include "srslte/phy/fec/turbocoder.h"
|
||||
#include "srslte/phy/fec/turbodecoder.h"
|
||||
#include "srslte/phy/modem/mod.h"
|
||||
#include "srslte/phy/scrambling/scrambling.h"
|
||||
|
||||
/**
|
||||
* \brief Physical Sidelink shared channel.
|
||||
*
|
||||
* Reference: 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 9.3
|
||||
*/
|
||||
|
||||
// Redundancy version
|
||||
static const uint8_t srslte_pssch_rv[4] = {0, 2, 3, 1};
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
uint32_t prb_start_idx; // PRB start idx to map RE from RIV
|
||||
uint32_t nof_prb; // PSSCH nof_prbs, Length of continuous PRB to map RE (in the pool) from RIV
|
||||
uint32_t N_x_id;
|
||||
uint32_t mcs_idx;
|
||||
uint32_t rv_idx;
|
||||
uint32_t sf_idx; // PSSCH sf_idx
|
||||
} srslte_pssch_cfg_t;
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
|
||||
srslte_cell_sl_t cell;
|
||||
srslte_sl_comm_resource_pool_t sl_comm_resource_pool;
|
||||
srslte_pssch_cfg_t pssch_cfg;
|
||||
|
||||
srslte_cbsegm_t cb_segm;
|
||||
|
||||
uint32_t G;
|
||||
uint32_t E;
|
||||
uint32_t Qm;
|
||||
uint32_t nof_data_symbols;
|
||||
uint32_t nof_tx_symbols;
|
||||
|
||||
uint32_t nof_data_re; // Number of RE considered during the channel mapping
|
||||
uint32_t nof_tx_re; // Number of RE actually transmitted over the air (without last OFDM symbol)
|
||||
uint32_t sl_sch_tb_len;
|
||||
uint32_t scfdma_symbols_len;
|
||||
|
||||
// data
|
||||
uint8_t* b;
|
||||
|
||||
// crc
|
||||
uint8_t* c_r;
|
||||
uint8_t* c_r_bytes;
|
||||
uint8_t* tb_crc_temp;
|
||||
srslte_crc_t tb_crc;
|
||||
uint8_t* cb_crc_temp;
|
||||
srslte_crc_t cb_crc;
|
||||
|
||||
// channel coding
|
||||
uint8_t* d_r;
|
||||
int16_t* d_r_16;
|
||||
srslte_tcod_t tcod;
|
||||
srslte_tdec_t tdec;
|
||||
|
||||
// rate matching
|
||||
uint8_t* e_r;
|
||||
int16_t* e_r_16;
|
||||
uint8_t* buff_b;
|
||||
|
||||
uint8_t* codeword;
|
||||
uint8_t* codeword_bytes;
|
||||
int16_t* llr;
|
||||
|
||||
// interleaving
|
||||
uint8_t* f;
|
||||
uint8_t* f_bytes;
|
||||
int16_t* f_16;
|
||||
uint32_t* interleaver_lut;
|
||||
|
||||
// scrambling
|
||||
srslte_sequence_t scrambling_seq;
|
||||
|
||||
// modulation
|
||||
srslte_mod_t mod_idx;
|
||||
srslte_modem_table_t mod[SRSLTE_MOD_NITEMS];
|
||||
cf_t* symbols;
|
||||
uint8_t* bits_after_demod;
|
||||
uint8_t* bytes_after_demod;
|
||||
|
||||
// dft precoding
|
||||
srslte_dft_precoding_t dft_precoder;
|
||||
cf_t* scfdma_symbols;
|
||||
srslte_dft_precoding_t idft_precoder;
|
||||
|
||||
} srslte_pssch_t;
|
||||
|
||||
SRSLTE_API int
|
||||
srslte_pssch_init(srslte_pssch_t* q, srslte_cell_sl_t cell, srslte_sl_comm_resource_pool_t sl_comm_resource_pool);
|
||||
SRSLTE_API int srslte_pssch_set_cfg(srslte_pssch_t* q, srslte_pssch_cfg_t pssch_cfg);
|
||||
SRSLTE_API int srslte_pssch_encode(srslte_pssch_t* q, uint8_t* input, uint32_t input_len, cf_t* sf_buffer);
|
||||
SRSLTE_API int srslte_pssch_decode(srslte_pssch_t* q, cf_t* equalized_sf_syms, uint8_t* output, uint32_t output_len);
|
||||
SRSLTE_API int srslte_pssch_put(srslte_pssch_t* q, cf_t* sf_buffer, cf_t* symbols);
|
||||
SRSLTE_API int srslte_pssch_get(srslte_pssch_t* q, cf_t* sf_buffer, cf_t* symbols);
|
||||
SRSLTE_API void srslte_pssch_free(srslte_pssch_t* q);
|
||||
|
||||
#endif // SRSLTE_PSSCH_H
|
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2013-2020 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsLTE.
|
||||
*
|
||||
* srsLTE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsLTE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSLTE_RA_SL_H
|
||||
#define SRSLTE_RA_SL_H
|
||||
|
||||
SRSLTE_API int srslte_sl_get_available_pool_prb(uint32_t prb_num, uint32_t prb_start, uint32_t prb_end);
|
||||
|
||||
SRSLTE_API int srslte_pscch_resources(uint32_t prb_num,
|
||||
uint32_t prb_start,
|
||||
uint32_t prb_end,
|
||||
uint8_t* pscch_sf_bitmap,
|
||||
uint32_t period_length,
|
||||
uint32_t n_pscch,
|
||||
uint32_t* m_a,
|
||||
uint32_t* l_b);
|
||||
|
||||
SRSLTE_API uint32_t srslte_ra_sl_type0_to_riv(uint32_t nof_prb, uint32_t prb_start, uint32_t L_crb);
|
||||
SRSLTE_API void srslte_ra_sl_type0_from_riv(uint32_t riv, uint32_t nof_prb, uint32_t* L_crb, uint32_t* prb_start);
|
||||
SRSLTE_API int
|
||||
srslte_ra_sl_pssch_allowed_sf(uint32_t pssch_sf_idx, uint32_t trp_idx, uint32_t duplex_mode, uint32_t tdd_config);
|
||||
SRSLTE_API int srslte_sci_generate_trp_idx(uint32_t duplex_mode, uint32_t tdd_config, uint32_t k_TRP);
|
||||
|
||||
// TS 36.213 table 14.1.1.1.1-3: Time Resource pattern Index mapping for N_TRP = 6
|
||||
static const uint8_t srslte_sl_N_TRP_6_k_1[] = {1, 2, 4, 8, 16, 32};
|
||||
static const uint8_t srslte_sl_N_TRP_6_k_2[] = {3, 5, 6, 9, 10, 12, 17, 18, 20, 24, 33, 34, 36, 40, 48};
|
||||
static const uint8_t srslte_sl_N_TRP_6_k_3[] = {7, 11, 13, 14, 19, 21, 22, 25, 26, 28,
|
||||
35, 37, 38, 41, 42, 44, 49, 50, 52, 56};
|
||||
static const uint8_t srslte_sl_N_TRP_6_k_4[] = {15, 23, 27, 29, 30, 39, 43, 45, 46, 51, 53, 54, 57, 58, 60};
|
||||
static const uint8_t srslte_sl_N_TRP_6_k_5[] = {31, 47, 55, 59, 61, 62};
|
||||
static const uint8_t srslte_sl_N_TRP_6_k_6[] = {63};
|
||||
static const uint8_t srslte_sl_N_TRP_6[][6] = {
|
||||
{0, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0},
|
||||
{1, 0, 1, 0, 0, 0}, {0, 1, 1, 0, 0, 0}, {1, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 0, 0}, {1, 0, 0, 1, 0, 0},
|
||||
{0, 1, 0, 1, 0, 0}, {1, 1, 0, 1, 0, 0}, {0, 0, 1, 1, 0, 0}, {1, 0, 1, 1, 0, 0}, {0, 1, 1, 1, 0, 0},
|
||||
{1, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 1, 0}, {1, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 1, 0}, {1, 1, 0, 0, 1, 0},
|
||||
{0, 0, 1, 0, 1, 0}, {1, 0, 1, 0, 1, 0}, {0, 1, 1, 0, 1, 0}, {1, 1, 1, 0, 1, 0}, {0, 0, 0, 1, 1, 0},
|
||||
{1, 0, 0, 1, 1, 0}, {0, 1, 0, 1, 1, 0}, {1, 1, 0, 1, 1, 0}, {0, 0, 1, 1, 1, 0}, {1, 0, 1, 1, 1, 0},
|
||||
{0, 1, 1, 1, 1, 0}, {1, 1, 1, 1, 1, 0}, {0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 1}, {0, 1, 0, 0, 0, 1},
|
||||
{1, 1, 0, 0, 0, 1}, {0, 0, 1, 0, 0, 1}, {1, 0, 1, 0, 0, 1}, {0, 1, 1, 0, 0, 1}, {1, 1, 1, 0, 0, 1},
|
||||
{0, 0, 0, 1, 0, 1}, {1, 0, 0, 1, 0, 1}, {0, 1, 0, 1, 0, 1}, {1, 1, 0, 1, 0, 1}, {0, 0, 1, 1, 0, 1},
|
||||
{1, 0, 1, 1, 0, 1}, {0, 1, 1, 1, 0, 1}, {1, 1, 1, 1, 0, 1}, {0, 0, 0, 0, 1, 1}, {1, 0, 0, 0, 1, 1},
|
||||
{0, 1, 0, 0, 1, 1}, {1, 1, 0, 0, 1, 1}, {0, 0, 1, 0, 1, 1}, {1, 0, 1, 0, 1, 1}, {0, 1, 1, 0, 1, 1},
|
||||
{1, 1, 1, 0, 1, 1}, {0, 0, 0, 1, 1, 1}, {1, 0, 0, 1, 1, 1}, {0, 1, 0, 1, 1, 1}, {1, 1, 0, 1, 1, 1},
|
||||
{0, 0, 1, 1, 1, 1}, {1, 0, 1, 1, 1, 1}, {0, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1}};
|
||||
|
||||
// TS 36.213 table 14.1.1.1.1-2: Time Resource pattern Index mapping for N_TRP = 7
|
||||
static const uint8_t srslte_sl_N_TRP_7_k_1[] = {1, 2, 4, 8, 16, 32, 64};
|
||||
static const uint8_t srslte_sl_N_TRP_7_k_2[] = {3, 5, 6, 9, 10, 12, 17, 18, 20, 24, 33,
|
||||
34, 36, 40, 48, 65, 66, 68, 72, 80, 96};
|
||||
static const uint8_t srslte_sl_N_TRP_7_k_3[] = {7, 11, 13, 14, 19, 21, 22, 25, 26, 28, 35, 37,
|
||||
38, 41, 42, 44, 49, 50, 52, 56, 67, 69, 70, 73,
|
||||
74, 76, 81, 82, 84, 88, 97, 98, 100, 104, 112};
|
||||
static const uint8_t srslte_sl_N_TRP_7_k_4[] = {15, 23, 27, 29, 30, 39, 43, 45, 46, 51, 53, 54,
|
||||
57, 58, 60, 71, 75, 77, 78, 83, 85, 86, 89, 90,
|
||||
92, 99, 101, 102, 105, 106, 108, 113, 114, 116, 120};
|
||||
static const uint8_t srslte_sl_N_TRP_7_k_5[] = {31, 47, 55, 59, 61, 62, 79, 87, 91, 93, 94,
|
||||
103, 107, 109, 110, 115, 117, 118, 121, 122, 124};
|
||||
static const uint8_t srslte_sl_N_TRP_7_k_6[] = {63, 95, 111, 119, 123, 125, 126};
|
||||
static const uint8_t srslte_sl_N_TRP_7_k_7[] = {127};
|
||||
static const uint8_t srslte_sl_N_TRP_7[][7] = {
|
||||
{0, 0, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0}, {1, 1, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0},
|
||||
{1, 0, 1, 0, 0, 0, 0}, {0, 1, 1, 0, 0, 0, 0}, {1, 1, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0}, {1, 0, 0, 1, 0, 0, 0},
|
||||
{0, 1, 0, 1, 0, 0, 0}, {1, 1, 0, 1, 0, 0, 0}, {0, 0, 1, 1, 0, 0, 0}, {1, 0, 1, 1, 0, 0, 0}, {0, 1, 1, 1, 0, 0, 0},
|
||||
{1, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0}, {1, 0, 0, 0, 1, 0, 0}, {0, 1, 0, 0, 1, 0, 0}, {1, 1, 0, 0, 1, 0, 0},
|
||||
{0, 0, 1, 0, 1, 0, 0}, {1, 0, 1, 0, 1, 0, 0}, {0, 1, 1, 0, 1, 0, 0}, {1, 1, 1, 0, 1, 0, 0}, {0, 0, 0, 1, 1, 0, 0},
|
||||
{1, 0, 0, 1, 1, 0, 0}, {0, 1, 0, 1, 1, 0, 0}, {1, 1, 0, 1, 1, 0, 0}, {0, 0, 1, 1, 1, 0, 0}, {1, 0, 1, 1, 1, 0, 0},
|
||||
{0, 1, 1, 1, 1, 0, 0}, {1, 1, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 1, 0}, {1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 1, 0},
|
||||
{1, 1, 0, 0, 0, 1, 0}, {0, 0, 1, 0, 0, 1, 0}, {1, 0, 1, 0, 0, 1, 0}, {0, 1, 1, 0, 0, 1, 0}, {1, 1, 1, 0, 0, 1, 0},
|
||||
{0, 0, 0, 1, 0, 1, 0}, {1, 0, 0, 1, 0, 1, 0}, {0, 1, 0, 1, 0, 1, 0}, {1, 1, 0, 1, 0, 1, 0}, {0, 0, 1, 1, 0, 1, 0},
|
||||
{1, 0, 1, 1, 0, 1, 0}, {0, 1, 1, 1, 0, 1, 0}, {1, 1, 1, 1, 0, 1, 0}, {0, 0, 0, 0, 1, 1, 0}, {1, 0, 0, 0, 1, 1, 0},
|
||||
{0, 1, 0, 0, 1, 1, 0}, {1, 1, 0, 0, 1, 1, 0}, {0, 0, 1, 0, 1, 1, 0}, {1, 0, 1, 0, 1, 1, 0}, {0, 1, 1, 0, 1, 1, 0},
|
||||
{1, 1, 1, 0, 1, 1, 0}, {0, 0, 0, 1, 1, 1, 0}, {1, 0, 0, 1, 1, 1, 0}, {0, 1, 0, 1, 1, 1, 0}, {1, 1, 0, 1, 1, 1, 0},
|
||||
{0, 0, 1, 1, 1, 1, 0}, {1, 0, 1, 1, 1, 1, 0}, {0, 1, 1, 1, 1, 1, 0}, {1, 1, 1, 1, 1, 1, 0}, {0, 0, 0, 0, 0, 0, 1},
|
||||
{1, 0, 0, 0, 0, 0, 1}, {0, 1, 0, 0, 0, 0, 1}, {1, 1, 0, 0, 0, 0, 1}, {0, 0, 1, 0, 0, 0, 1}, {1, 0, 1, 0, 0, 0, 1},
|
||||
{0, 1, 1, 0, 0, 0, 1}, {1, 1, 1, 0, 0, 0, 1}, {0, 0, 0, 1, 0, 0, 1}, {1, 0, 0, 1, 0, 0, 1}, {0, 1, 0, 1, 0, 0, 1},
|
||||
{1, 1, 0, 1, 0, 0, 1}, {0, 0, 1, 1, 0, 0, 1}, {1, 0, 1, 1, 0, 0, 1}, {0, 1, 1, 1, 0, 0, 1}, {1, 1, 1, 1, 0, 0, 1},
|
||||
{0, 0, 0, 0, 1, 0, 1}, {1, 0, 0, 0, 1, 0, 1}, {0, 1, 0, 0, 1, 0, 1}, {1, 1, 0, 0, 1, 0, 1}, {0, 0, 1, 0, 1, 0, 1},
|
||||
{1, 0, 1, 0, 1, 0, 1}, {0, 1, 1, 0, 1, 0, 1}, {1, 1, 1, 0, 1, 0, 1}, {0, 0, 0, 1, 1, 0, 1}, {1, 0, 0, 1, 1, 0, 1},
|
||||
{0, 1, 0, 1, 1, 0, 1}, {1, 1, 0, 1, 1, 0, 1}, {0, 0, 1, 1, 1, 0, 1}, {1, 0, 1, 1, 1, 0, 1}, {0, 1, 1, 1, 1, 0, 1},
|
||||
{1, 1, 1, 1, 1, 0, 1}, {0, 0, 0, 0, 0, 1, 1}, {1, 0, 0, 0, 0, 1, 1}, {0, 1, 0, 0, 0, 1, 1}, {1, 1, 0, 0, 0, 1, 1},
|
||||
{0, 0, 1, 0, 0, 1, 1}, {1, 0, 1, 0, 0, 1, 1}, {0, 1, 1, 0, 0, 1, 1}, {1, 1, 1, 0, 0, 1, 1}, {0, 0, 0, 1, 0, 1, 1},
|
||||
{1, 0, 0, 1, 0, 1, 1}, {0, 1, 0, 1, 0, 1, 1}, {1, 1, 0, 1, 0, 1, 1}, {0, 0, 1, 1, 0, 1, 1}, {1, 0, 1, 1, 0, 1, 1},
|
||||
{0, 1, 1, 1, 0, 1, 1}, {1, 1, 1, 1, 0, 1, 1}, {0, 0, 0, 0, 1, 1, 1}, {1, 0, 0, 0, 1, 1, 1}, {0, 1, 0, 0, 1, 1, 1},
|
||||
{1, 1, 0, 0, 1, 1, 1}, {0, 0, 1, 0, 1, 1, 1}, {1, 0, 1, 0, 1, 1, 1}, {0, 1, 1, 0, 1, 1, 1}, {1, 1, 1, 0, 1, 1, 1},
|
||||
{0, 0, 0, 1, 1, 1, 1}, {1, 0, 0, 1, 1, 1, 1}, {0, 1, 0, 1, 1, 1, 1}, {1, 1, 0, 1, 1, 1, 1}, {0, 0, 1, 1, 1, 1, 1},
|
||||
{1, 0, 1, 1, 1, 1, 1}, {0, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1}};
|
||||
|
||||
// TS 36.213 table 14.1.1.1.1-1: Time Resource pattern Index mapping for N_TRP = 8
|
||||
static const uint8_t srslte_sl_N_TRP_8_k_1[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
static const uint8_t srslte_sl_N_TRP_8_k_2[] = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35};
|
||||
static const uint8_t srslte_sl_N_TRP_8_k_4[] = {
|
||||
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
|
||||
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
|
||||
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105};
|
||||
static const uint8_t srslte_sl_N_TRP_8_k_8[] = {106};
|
||||
static const uint8_t srslte_sl_N_TRP_8[][8] = {
|
||||
{1, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1},
|
||||
{1, 1, 0, 0, 0, 0, 0, 0}, {1, 0, 1, 0, 0, 0, 0, 0}, {0, 1, 1, 0, 0, 0, 0, 0}, {1, 0, 0, 1, 0, 0, 0, 0},
|
||||
{0, 1, 0, 1, 0, 0, 0, 0}, {0, 0, 1, 1, 0, 0, 0, 0}, {1, 0, 0, 0, 1, 0, 0, 0}, {0, 1, 0, 0, 1, 0, 0, 0},
|
||||
{0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0}, {1, 0, 0, 0, 0, 1, 0, 0}, {0, 1, 0, 0, 0, 1, 0, 0},
|
||||
{0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 1, 0, 1, 0, 0}, {0, 0, 0, 0, 1, 1, 0, 0}, {1, 0, 0, 0, 0, 0, 1, 0},
|
||||
{0, 1, 0, 0, 0, 0, 1, 0}, {0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 1, 0, 0, 1, 0}, {0, 0, 0, 0, 1, 0, 1, 0},
|
||||
{0, 0, 0, 0, 0, 1, 1, 0}, {1, 0, 0, 0, 0, 0, 0, 1}, {0, 1, 0, 0, 0, 0, 0, 1}, {0, 0, 1, 0, 0, 0, 0, 1},
|
||||
{0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 0, 0, 1, 0, 0, 1}, {0, 0, 0, 0, 0, 1, 0, 1}, {0, 0, 0, 0, 0, 0, 1, 1},
|
||||
{1, 1, 1, 1, 0, 0, 0, 0}, {1, 1, 1, 0, 1, 0, 0, 0}, {1, 1, 0, 1, 1, 0, 0, 0}, {1, 0, 1, 1, 1, 0, 0, 0},
|
||||
{0, 1, 1, 1, 1, 0, 0, 0}, {1, 1, 1, 0, 0, 1, 0, 0}, {1, 1, 0, 1, 0, 1, 0, 0}, {1, 0, 1, 1, 0, 1, 0, 0},
|
||||
{0, 1, 1, 1, 0, 1, 0, 0}, {1, 1, 0, 0, 1, 1, 0, 0}, {1, 0, 1, 0, 1, 1, 0, 0}, {0, 1, 1, 0, 1, 1, 0, 0},
|
||||
{1, 0, 0, 1, 1, 1, 0, 0}, {0, 1, 0, 1, 1, 1, 0, 0}, {0, 0, 1, 1, 1, 1, 0, 0}, {1, 1, 1, 0, 0, 0, 1, 0},
|
||||
{1, 1, 0, 1, 0, 0, 1, 0}, {1, 0, 1, 1, 0, 0, 1, 0}, {0, 1, 1, 1, 0, 0, 1, 0}, {1, 1, 0, 0, 1, 0, 1, 0},
|
||||
{1, 0, 1, 0, 1, 0, 1, 0}, {0, 1, 1, 0, 1, 0, 1, 0}, {1, 0, 0, 1, 1, 0, 1, 0}, {0, 1, 0, 1, 1, 0, 1, 0},
|
||||
{0, 0, 1, 1, 1, 0, 1, 0}, {1, 1, 0, 0, 0, 1, 1, 0}, {1, 0, 1, 0, 0, 1, 1, 0}, {0, 1, 1, 0, 0, 1, 1, 0},
|
||||
{1, 0, 0, 1, 0, 1, 1, 0}, {0, 1, 0, 1, 0, 1, 1, 0}, {0, 0, 1, 1, 0, 1, 1, 0}, {1, 0, 0, 0, 1, 1, 1, 0},
|
||||
{0, 1, 0, 0, 1, 1, 1, 0}, {0, 0, 1, 0, 1, 1, 1, 0}, {0, 0, 0, 1, 1, 1, 1, 0}, {1, 1, 1, 0, 0, 0, 0, 1},
|
||||
{1, 1, 0, 1, 0, 0, 0, 1}, {1, 0, 1, 1, 0, 0, 0, 1}, {0, 1, 1, 1, 0, 0, 0, 1}, {1, 1, 0, 0, 1, 0, 0, 1},
|
||||
{1, 0, 1, 0, 1, 0, 0, 1}, {0, 1, 1, 0, 1, 0, 0, 1}, {1, 0, 0, 1, 1, 0, 0, 1}, {0, 1, 0, 1, 1, 0, 0, 1},
|
||||
{0, 0, 1, 1, 1, 0, 0, 1}, {1, 1, 0, 0, 0, 1, 0, 1}, {1, 0, 1, 0, 0, 1, 0, 1}, {0, 1, 1, 0, 0, 1, 0, 1},
|
||||
{1, 0, 0, 1, 0, 1, 0, 1}, {0, 1, 0, 1, 0, 1, 0, 1}, {0, 0, 1, 1, 0, 1, 0, 1}, {1, 0, 0, 0, 1, 1, 0, 1},
|
||||
{0, 1, 0, 0, 1, 1, 0, 1}, {0, 0, 1, 0, 1, 1, 0, 1}, {0, 0, 0, 1, 1, 1, 0, 1}, {1, 1, 0, 0, 0, 0, 1, 1},
|
||||
{1, 0, 1, 0, 0, 0, 1, 1}, {0, 1, 1, 0, 0, 0, 1, 1}, {1, 0, 0, 1, 0, 0, 1, 1}, {0, 1, 0, 1, 0, 0, 1, 1},
|
||||
{0, 0, 1, 1, 0, 0, 1, 1}, {1, 0, 0, 0, 1, 0, 1, 1}, {0, 1, 0, 0, 1, 0, 1, 1}, {0, 0, 1, 0, 1, 0, 1, 1},
|
||||
{0, 0, 0, 1, 1, 0, 1, 1}, {1, 0, 0, 0, 0, 1, 1, 1}, {0, 1, 0, 0, 0, 1, 1, 1}, {0, 0, 1, 0, 0, 1, 1, 1},
|
||||
{0, 0, 0, 1, 0, 1, 1, 1}, {0, 0, 0, 0, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}};
|
||||
|
||||
#endif // SRSLTE_RA_SL_H
|
@ -0,0 +1,666 @@
|
||||
/*
|
||||
* Copyright 2013-2020 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsLTE.
|
||||
*
|
||||
* srsLTE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsLTE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "srslte/phy/fec/rm_turbo.h"
|
||||
#include "srslte/phy/modem/demod_soft.h"
|
||||
#include "srslte/phy/phch/pssch.h"
|
||||
#include "srslte/phy/phch/ra.h"
|
||||
#include "srslte/phy/phch/sch.h"
|
||||
#include "srslte/phy/utils/bit.h"
|
||||
#include "srslte/phy/utils/debug.h"
|
||||
#include "srslte/phy/utils/vector.h"
|
||||
|
||||
int srslte_pssch_init(srslte_pssch_t* q, srslte_cell_sl_t cell, srslte_sl_comm_resource_pool_t sl_comm_resource_pool)
|
||||
{
|
||||
if (q == NULL) {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
q->cell = cell;
|
||||
q->sl_comm_resource_pool = sl_comm_resource_pool;
|
||||
|
||||
if (cell.tm == SRSLTE_SIDELINK_TM1 || cell.tm == SRSLTE_SIDELINK_TM2) {
|
||||
if (cell.cp == SRSLTE_CP_NORM) {
|
||||
q->nof_data_symbols = SRSLTE_PSSCH_TM12_NUM_DATA_SYMBOLS;
|
||||
} else {
|
||||
q->nof_data_symbols = SRSLTE_PSSCH_TM12_NUM_DATA_SYMBOLS_CP_EXT;
|
||||
}
|
||||
} else if (cell.tm == SRSLTE_SIDELINK_TM3 || cell.tm == SRSLTE_SIDELINK_TM4) {
|
||||
if (cell.cp == SRSLTE_CP_NORM) {
|
||||
q->nof_data_symbols = SRSLTE_PSSCH_TM34_NUM_DATA_SYMBOLS;
|
||||
} else {
|
||||
ERROR("Invalid CP for PSSCH, SL TM 3/4\n");
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
} else {
|
||||
ERROR("Invalid SL TM\n");
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Transport Block
|
||||
q->b = srslte_vec_u8_malloc(SRSLTE_SL_SCH_MAX_TB_LEN + SRSLTE_PSSCH_CRC_LEN);
|
||||
if (!q->b) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Transport Block CRC
|
||||
if (srslte_crc_init(&q->tb_crc, SRSLTE_LTE_CRC24A, SRSLTE_PSSCH_CRC_LEN)) {
|
||||
ERROR("Error Transport Block CRC init\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->tb_crc_temp = srslte_vec_u8_malloc(SRSLTE_PSSCH_CRC_LEN);
|
||||
if (!q->tb_crc_temp) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Code Block Segmentation
|
||||
q->c_r = srslte_vec_u8_malloc(SRSLTE_TCOD_MAX_LEN_CB);
|
||||
if (!q->c_r) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->f_16 = srslte_vec_i16_malloc(SRSLTE_MAX_CODEWORD_LEN);
|
||||
if (!q->f_16) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->c_r_bytes = srslte_vec_u8_malloc(SRSLTE_TCOD_MAX_LEN_CB / 8);
|
||||
if (!q->c_r_bytes) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Code Block CRC
|
||||
if (srslte_crc_init(&q->cb_crc, SRSLTE_LTE_CRC24B, SRSLTE_PSSCH_CRC_LEN)) {
|
||||
ERROR("Error Code Block CRC init\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->cb_crc_temp = srslte_vec_u8_malloc(SRSLTE_PSSCH_CRC_LEN);
|
||||
if (!q->cb_crc_temp) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Channel Coding
|
||||
srslte_tcod_init(&q->tcod, SRSLTE_TCOD_MAX_LEN_CB);
|
||||
q->d_r = srslte_vec_u8_malloc(SRSLTE_PSSCH_MAX_CODED_BITS);
|
||||
if (!q->d_r) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_tdec_init(&q->tdec, SRSLTE_TCOD_MAX_LEN_CB);
|
||||
srslte_tdec_force_not_sb(&q->tdec);
|
||||
q->d_r_16 = srslte_vec_i16_malloc(SRSLTE_PSSCH_MAX_CODED_BITS);
|
||||
if (!q->d_r_16) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Rate Matching
|
||||
q->e_r = srslte_vec_u8_malloc(SRSLTE_MAX_CODEWORD_LEN);
|
||||
if (!q->e_r) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->buff_b = srslte_vec_u8_malloc(SRSLTE_PSSCH_MAX_CODED_BITS);
|
||||
if (!q->buff_b) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_vec_u8_zero(q->buff_b, SRSLTE_PSSCH_MAX_CODED_BITS);
|
||||
q->e_r_16 = srslte_vec_i16_malloc(SRSLTE_MAX_CODEWORD_LEN);
|
||||
if (!q->e_r_16) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_rm_turbo_gentables();
|
||||
|
||||
// Code Block Concatenation
|
||||
q->f = srslte_vec_u8_malloc(SRSLTE_MAX_CODEWORD_LEN);
|
||||
if (!q->f) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Interleaving
|
||||
q->f_bytes = srslte_vec_u8_malloc(SRSLTE_MAX_CODEWORD_LEN / 8);
|
||||
if (!q->f_bytes) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->interleaver_lut = srslte_vec_u32_malloc(SRSLTE_MAX_CODEWORD_LEN);
|
||||
if (!q->interleaver_lut) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_vec_u32_zero(q->interleaver_lut, SRSLTE_MAX_CODEWORD_LEN);
|
||||
|
||||
// Scrambling
|
||||
q->codeword = srslte_vec_u8_malloc(SRSLTE_MAX_CODEWORD_LEN);
|
||||
if (!q->codeword) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->codeword_bytes = srslte_vec_u8_malloc(SRSLTE_MAX_CODEWORD_LEN / 8);
|
||||
if (!q->codeword_bytes) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Modulation
|
||||
q->symbols = srslte_vec_cf_malloc(SRSLTE_MAX_CODEWORD_LEN);
|
||||
if (!q->symbols) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_vec_cf_zero(q->symbols, SRSLTE_MAX_CODEWORD_LEN);
|
||||
|
||||
q->bits_after_demod = srslte_vec_u8_malloc(SRSLTE_MAX_CODEWORD_LEN);
|
||||
if (!q->bits_after_demod) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->bytes_after_demod = srslte_vec_u8_malloc(SRSLTE_MAX_CODEWORD_LEN / 8);
|
||||
if (!q->bytes_after_demod) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
for (int i = 0; i < SRSLTE_MOD_NITEMS; i++) {
|
||||
if (srslte_modem_table_lte(&q->mod[i], (srslte_mod_t)i)) {
|
||||
ERROR("Error initiating modem tables\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Demodulation
|
||||
q->llr = srslte_vec_i16_malloc(SRSLTE_MAX_CODEWORD_LEN);
|
||||
if (!q->llr) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Transform Precoding
|
||||
q->scfdma_symbols = srslte_vec_cf_malloc(q->nof_data_symbols * SRSLTE_NRE * SRSLTE_MAX_PRB);
|
||||
if (!q->scfdma_symbols) {
|
||||
ERROR("Error allocating memory\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if (srslte_dft_precoding_init(&q->dft_precoder, SRSLTE_MAX_PRB, true)) {
|
||||
ERROR("Error DFT precoder init\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if (srslte_dft_precoding_init(&q->idft_precoder, SRSLTE_MAX_PRB, false)) {
|
||||
ERROR("Error in DFT precoder init\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int srslte_pssch_set_cfg(srslte_pssch_t* q, srslte_pssch_cfg_t pssch_cfg)
|
||||
{
|
||||
if (q == NULL) {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
q->pssch_cfg = pssch_cfg;
|
||||
|
||||
q->mod_idx = srslte_ra_ul_mod_from_mcs(pssch_cfg.mcs_idx);
|
||||
q->Qm = srslte_mod_bits_x_symbol(q->mod_idx);
|
||||
q->sl_sch_tb_len =
|
||||
srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(pssch_cfg.mcs_idx, false, true), pssch_cfg.nof_prb);
|
||||
|
||||
if (q->cell.tm == SRSLTE_SIDELINK_TM1 || q->cell.tm == SRSLTE_SIDELINK_TM2) {
|
||||
q->nof_data_symbols = SRSLTE_PSSCH_TM12_NUM_DATA_SYMBOLS;
|
||||
|
||||
if (q->cell.cp == SRSLTE_CP_EXT) {
|
||||
q->nof_data_symbols = SRSLTE_PSSCH_TM12_NUM_DATA_SYMBOLS_CP_EXT;
|
||||
}
|
||||
} else if (q->cell.tm == SRSLTE_SIDELINK_TM3 || q->cell.tm == SRSLTE_SIDELINK_TM4) {
|
||||
q->nof_data_symbols = SRSLTE_PSSCH_TM34_NUM_DATA_SYMBOLS;
|
||||
} else {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
q->nof_tx_symbols = q->nof_data_symbols - 1; // Last OFDM symbol is used in channel processing but not transmitted
|
||||
q->nof_tx_re = q->nof_tx_symbols * SRSLTE_NRE * pssch_cfg.nof_prb;
|
||||
q->nof_data_re = q->nof_data_symbols * SRSLTE_NRE * pssch_cfg.nof_prb;
|
||||
|
||||
q->E = q->nof_data_re * q->Qm;
|
||||
q->G = srslte_mod_bits_x_symbol(srslte_ra_ul_mod_from_mcs(pssch_cfg.mcs_idx)) * q->nof_data_re;
|
||||
q->scfdma_symbols_len = q->G / q->Qm;
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int srslte_pssch_encode(srslte_pssch_t* q, uint8_t* input, uint32_t input_len, cf_t* sf_buffer)
|
||||
{
|
||||
if (!input || input_len > q->sl_sch_tb_len) {
|
||||
ERROR("Can't encode PSSCH, input too long (%d > %d)\n", input_len, q->sl_sch_tb_len);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
srslte_cbsegm(&q->cb_segm, q->sl_sch_tb_len);
|
||||
uint32_t L = SRSLTE_PSSCH_CRC_LEN;
|
||||
if (q->cb_segm.C == 1) {
|
||||
L = 0;
|
||||
}
|
||||
|
||||
uint32_t K_r = 0;
|
||||
uint32_t E_r = 0;
|
||||
uint32_t s = 0;
|
||||
q->G = 0;
|
||||
uint32_t Gp = q->E / q->Qm;
|
||||
uint32_t gamma = Gp % q->cb_segm.C;
|
||||
|
||||
// Copy into codeword buffer
|
||||
memcpy(q->b, input, sizeof(uint8_t) * input_len);
|
||||
|
||||
// Transport block CRC attachment
|
||||
srslte_crc_attach(&q->tb_crc, q->b, q->sl_sch_tb_len);
|
||||
|
||||
for (int r = 0; r < q->cb_segm.C; r++) {
|
||||
|
||||
// Code block segmentation
|
||||
if (r < q->cb_segm.C2) {
|
||||
K_r = q->cb_segm.K2;
|
||||
} else {
|
||||
K_r = q->cb_segm.K1;
|
||||
}
|
||||
|
||||
if (r <= (q->cb_segm.C - gamma - 1)) {
|
||||
E_r = q->Qm * (Gp / q->cb_segm.C);
|
||||
} else {
|
||||
E_r = q->Qm * ((uint32_t)ceilf((float)Gp / q->cb_segm.C));
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
memset(q->c_r, SRSLTE_TX_NULL, sizeof(uint8_t) * q->cb_segm.F);
|
||||
memcpy(&q->c_r[q->cb_segm.F], q->b, sizeof(uint8_t) * (K_r - L));
|
||||
s += (K_r - L - q->cb_segm.F);
|
||||
} else {
|
||||
memcpy(q->c_r, &q->b[s], sizeof(uint8_t) * (K_r - L));
|
||||
s += (K_r - L);
|
||||
}
|
||||
|
||||
// Code block CRC attachment
|
||||
if (q->cb_segm.C > 1) {
|
||||
if (r == 0) {
|
||||
srslte_vec_u8_zero(q->c_r, q->cb_segm.F);
|
||||
}
|
||||
srslte_crc_attach(&q->cb_crc, q->c_r, (int)(K_r - L));
|
||||
if (r == 0) {
|
||||
memset(q->c_r, SRSLTE_TX_NULL, sizeof(uint8_t) * q->cb_segm.F);
|
||||
}
|
||||
}
|
||||
|
||||
// Channel coding
|
||||
srslte_tcod_encode(&q->tcod, q->c_r, q->d_r, K_r);
|
||||
|
||||
// Rate matching
|
||||
srslte_vec_u8_zero(q->buff_b, SRSLTE_PSSCH_MAX_CODED_BITS);
|
||||
srslte_rm_turbo_tx(q->buff_b, SRSLTE_PSSCH_MAX_CODED_BITS, q->d_r, 3 * K_r + SRSLTE_TCOD_TOTALTAIL, q->e_r, E_r, 0);
|
||||
|
||||
if (q->pssch_cfg.rv_idx > 0) {
|
||||
srslte_rm_turbo_tx(q->buff_b,
|
||||
SRSLTE_PSSCH_MAX_CODED_BITS,
|
||||
q->d_r,
|
||||
3 * K_r + SRSLTE_TCOD_TOTALTAIL,
|
||||
q->e_r,
|
||||
E_r,
|
||||
srslte_pssch_rv[q->pssch_cfg.rv_idx]);
|
||||
}
|
||||
|
||||
// Code block concatenation
|
||||
memcpy(&q->f[q->G], q->e_r, sizeof(uint8_t) * E_r);
|
||||
q->G += E_r;
|
||||
}
|
||||
|
||||
// Interleaving
|
||||
srslte_bit_pack_vector(q->f, q->f_bytes, q->G);
|
||||
srslte_sl_ulsch_interleave(q->f_bytes, q->Qm, q->G / q->Qm, q->nof_data_symbols, q->codeword_bytes);
|
||||
srslte_bit_unpack_vector(q->codeword_bytes, q->codeword, q->G);
|
||||
|
||||
// Scrambling follows 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 9.3.1
|
||||
srslte_sequence_LTE_pr(
|
||||
&q->scrambling_seq, q->G, q->pssch_cfg.N_x_id * 16384 + (q->pssch_cfg.sf_idx % 10) * 512 + 510);
|
||||
srslte_scrambling_b(&q->scrambling_seq, q->codeword);
|
||||
|
||||
// Modulation
|
||||
srslte_mod_modulate(&q->mod[q->mod_idx], q->codeword, q->symbols, q->G);
|
||||
|
||||
// Layer Mapping
|
||||
// Voided: Single layer
|
||||
// 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 9.3.3
|
||||
|
||||
// Transform Precoding
|
||||
srslte_dft_precoding(&q->dft_precoder, q->symbols, q->scfdma_symbols, q->pssch_cfg.nof_prb, q->nof_data_symbols);
|
||||
|
||||
// Precoding
|
||||
// Voided: Single antenna port
|
||||
// 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 9.3.5
|
||||
|
||||
// RE mapping
|
||||
if (q->nof_tx_re != srslte_pssch_put(q, sf_buffer, q->scfdma_symbols)) {
|
||||
ERROR("There was an error mapping the PSSCH symbols\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int srslte_pssch_decode(srslte_pssch_t* q, cf_t* equalized_sf_syms, uint8_t* output, uint32_t output_len)
|
||||
{
|
||||
if (output_len < q->sl_sch_tb_len) {
|
||||
ERROR("Can't decode PSSCH, provided buffer too small (%d < %d)\n", output_len, q->sl_sch_tb_len);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// RE extraction
|
||||
if (q->nof_tx_re != srslte_pssch_get(q, equalized_sf_syms, q->scfdma_symbols)) {
|
||||
ERROR("There was an error getting the PSSCH symbols\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Precoding
|
||||
// Voided: Single antenna port
|
||||
// 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 9.3.5
|
||||
|
||||
// Transform Predecoding
|
||||
if (srslte_dft_precoding(
|
||||
&q->idft_precoder, q->scfdma_symbols, q->symbols, q->pssch_cfg.nof_prb, q->nof_data_symbols) !=
|
||||
SRSLTE_SUCCESS) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Layer Mapping
|
||||
// Voided: Single layer
|
||||
// 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 9.3.3
|
||||
|
||||
// Demodulation
|
||||
srslte_demod_soft_demodulate_s(q->Qm / 2, q->symbols, q->llr, q->G / q->Qm);
|
||||
|
||||
// Descramble follows 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 9.3.1
|
||||
srslte_sequence_LTE_pr(
|
||||
&q->scrambling_seq, q->G, q->pssch_cfg.N_x_id * 16384 + (q->pssch_cfg.sf_idx % 10) * 512 + 510);
|
||||
srslte_scrambling_s(&q->scrambling_seq, q->llr);
|
||||
|
||||
srslte_cbsegm(&q->cb_segm, q->sl_sch_tb_len);
|
||||
uint32_t L = SRSLTE_PSSCH_CRC_LEN;
|
||||
if (q->cb_segm.C == 1) {
|
||||
L = 0;
|
||||
}
|
||||
|
||||
uint32_t B = 0;
|
||||
uint32_t K_r = 0;
|
||||
uint32_t E_r = 0;
|
||||
uint32_t s = 0;
|
||||
uint32_t Gp = q->E / q->Qm;
|
||||
uint32_t gamma = Gp % q->cb_segm.C;
|
||||
|
||||
// Deinterleaving
|
||||
srslte_sl_ulsch_deinterleave(q->llr, q->Qm, q->G / q->Qm, q->nof_data_symbols, q->f_16, q->interleaver_lut);
|
||||
|
||||
for (int r = 0; r < q->cb_segm.C; r++) {
|
||||
// Code block segmentation
|
||||
if (r < q->cb_segm.C2) {
|
||||
K_r = q->cb_segm.K2;
|
||||
} else {
|
||||
K_r = q->cb_segm.K1;
|
||||
}
|
||||
|
||||
if (r <= (q->cb_segm.C - gamma - 1)) {
|
||||
E_r = q->Qm * (Gp / q->cb_segm.C);
|
||||
} else {
|
||||
E_r = q->Qm * ((uint32_t)ceilf((float)Gp / q->cb_segm.C));
|
||||
}
|
||||
|
||||
memcpy(q->e_r_16, &q->f_16[s], sizeof(int16_t) * E_r);
|
||||
s += E_r;
|
||||
|
||||
// Rate matching
|
||||
uint32_t cb_len_idx = r < q->cb_segm.C1 ? q->cb_segm.K1_idx : q->cb_segm.K2_idx;
|
||||
srslte_vec_i16_zero(q->d_r_16, SRSLTE_PSSCH_MAX_CODED_BITS);
|
||||
srslte_rm_turbo_rx_lut_(q->e_r_16, q->d_r_16, E_r, cb_len_idx, srslte_pssch_rv[q->pssch_cfg.rv_idx], false);
|
||||
|
||||
// Channel decoding
|
||||
srslte_tdec_new_cb(&q->tdec, K_r);
|
||||
srslte_tdec_run_all(&q->tdec, q->d_r_16, q->c_r_bytes, 3, K_r);
|
||||
srslte_bit_unpack_vector(q->c_r_bytes, q->c_r, K_r);
|
||||
|
||||
if (q->cb_segm.C > 1) {
|
||||
|
||||
// Copy received crc to temp
|
||||
memcpy(q->cb_crc_temp, &q->c_r[(K_r - L)], sizeof(uint8_t) * L);
|
||||
|
||||
// Re-attach crc
|
||||
srslte_crc_attach(&q->cb_crc, q->c_r, (int)(K_r - L));
|
||||
|
||||
// CRC check
|
||||
if (srslte_bit_diff(q->cb_crc_temp, &q->c_r[(K_r - L)], L) != 0) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Code Block Concatenation, dettach CRC and remove filler bits
|
||||
if (r == 0) {
|
||||
memcpy(q->b, &q->c_r[q->cb_segm.F], sizeof(uint8_t) * (K_r - L - q->cb_segm.F));
|
||||
B += (K_r - L - q->cb_segm.F);
|
||||
} else {
|
||||
memcpy(&q->b[B], q->c_r, sizeof(uint8_t) * (K_r - L));
|
||||
B += (K_r - L);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy received crc to temp
|
||||
memcpy(q->tb_crc_temp, &q->b[B - SRSLTE_PSSCH_CRC_LEN], sizeof(uint8_t) * SRSLTE_PSSCH_CRC_LEN);
|
||||
|
||||
// Re-attach crc
|
||||
srslte_crc_attach(&q->tb_crc, q->b, (int)(B - SRSLTE_PSSCH_CRC_LEN));
|
||||
|
||||
// CRC check
|
||||
if (srslte_bit_diff(q->tb_crc_temp, &q->b[(B - SRSLTE_PSSCH_CRC_LEN)], SRSLTE_PSSCH_CRC_LEN) != 0) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Remove CRC and copy to output buffer
|
||||
memcpy(output, q->b, sizeof(uint8_t) * q->sl_sch_tb_len);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int srslte_pssch_put(srslte_pssch_t* q, cf_t* sf_buffer, cf_t* symbols)
|
||||
{
|
||||
uint32_t sample_pos = 0;
|
||||
uint32_t k = q->pssch_cfg.prb_start_idx * SRSLTE_NRE;
|
||||
for (int i = 0; i < srslte_sl_get_num_symbols(q->cell.tm, q->cell.cp); i++) {
|
||||
if (srslte_pssch_is_symbol(SRSLTE_SIDELINK_DATA_SYMBOL, q->cell.tm, i, q->cell.cp)) {
|
||||
|
||||
if (q->cell.tm == SRSLTE_SIDELINK_TM1 || q->cell.tm == SRSLTE_SIDELINK_TM2) {
|
||||
if (q->pssch_cfg.nof_prb <= q->sl_comm_resource_pool.prb_num) {
|
||||
k = q->pssch_cfg.prb_start_idx * SRSLTE_NRE;
|
||||
memcpy(&sf_buffer[k + i * q->cell.nof_prb * SRSLTE_NRE],
|
||||
&symbols[sample_pos],
|
||||
sizeof(cf_t) * (SRSLTE_NRE * q->pssch_cfg.nof_prb));
|
||||
sample_pos += (SRSLTE_NRE * q->pssch_cfg.nof_prb);
|
||||
} else {
|
||||
// First band
|
||||
k = q->pssch_cfg.prb_start_idx * SRSLTE_NRE;
|
||||
memcpy(&sf_buffer[k + i * q->cell.nof_prb * SRSLTE_NRE],
|
||||
&symbols[sample_pos],
|
||||
sizeof(cf_t) * (SRSLTE_NRE * q->sl_comm_resource_pool.prb_num));
|
||||
sample_pos += (SRSLTE_NRE * q->sl_comm_resource_pool.prb_num);
|
||||
|
||||
// Second band
|
||||
if ((q->sl_comm_resource_pool.prb_num * 2) >
|
||||
(q->sl_comm_resource_pool.prb_end - q->sl_comm_resource_pool.prb_start + 1)) {
|
||||
k = (q->sl_comm_resource_pool.prb_end + 1 - q->sl_comm_resource_pool.prb_num + 1) * SRSLTE_NRE;
|
||||
} else {
|
||||
k = (q->sl_comm_resource_pool.prb_end + 1 - q->sl_comm_resource_pool.prb_num) * SRSLTE_NRE;
|
||||
}
|
||||
memcpy(&sf_buffer[k + i * q->cell.nof_prb * SRSLTE_NRE],
|
||||
&symbols[sample_pos],
|
||||
sizeof(cf_t) * (SRSLTE_NRE * (q->pssch_cfg.nof_prb - q->sl_comm_resource_pool.prb_num)));
|
||||
sample_pos += (SRSLTE_NRE * (q->pssch_cfg.nof_prb - q->sl_comm_resource_pool.prb_num));
|
||||
}
|
||||
} else if (q->cell.tm == SRSLTE_SIDELINK_TM3 || q->cell.tm == SRSLTE_SIDELINK_TM4) {
|
||||
memcpy(&sf_buffer[k + i * q->cell.nof_prb * SRSLTE_NRE],
|
||||
&symbols[sample_pos],
|
||||
sizeof(cf_t) * (SRSLTE_NRE * q->pssch_cfg.nof_prb));
|
||||
sample_pos += (SRSLTE_NRE * q->pssch_cfg.nof_prb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sample_pos;
|
||||
}
|
||||
|
||||
int srslte_pssch_get(srslte_pssch_t* q, cf_t* sf_buffer, cf_t* symbols)
|
||||
{
|
||||
uint32_t sample_pos = 0;
|
||||
uint32_t k = q->pssch_cfg.prb_start_idx * SRSLTE_NRE;
|
||||
for (int i = 0; i < srslte_sl_get_num_symbols(q->cell.tm, q->cell.cp); i++) {
|
||||
if (srslte_pssch_is_symbol(SRSLTE_SIDELINK_DATA_SYMBOL, q->cell.tm, i, q->cell.cp)) {
|
||||
if (q->cell.tm == SRSLTE_SIDELINK_TM1 || q->cell.tm == SRSLTE_SIDELINK_TM2) {
|
||||
if (q->pssch_cfg.nof_prb <= q->sl_comm_resource_pool.prb_num) {
|
||||
k = q->pssch_cfg.prb_start_idx * SRSLTE_NRE;
|
||||
memcpy(&symbols[sample_pos],
|
||||
&sf_buffer[k + i * q->cell.nof_prb * SRSLTE_NRE],
|
||||
sizeof(cf_t) * (SRSLTE_NRE * q->pssch_cfg.nof_prb));
|
||||
sample_pos += (SRSLTE_NRE * q->pssch_cfg.nof_prb);
|
||||
} else {
|
||||
// First band
|
||||
k = q->pssch_cfg.prb_start_idx * SRSLTE_NRE;
|
||||
memcpy(&symbols[sample_pos],
|
||||
&sf_buffer[k + i * q->cell.nof_prb * SRSLTE_NRE],
|
||||
sizeof(cf_t) * (SRSLTE_NRE * q->sl_comm_resource_pool.prb_num));
|
||||
sample_pos += (SRSLTE_NRE * q->sl_comm_resource_pool.prb_num);
|
||||
|
||||
// Second band
|
||||
if ((q->sl_comm_resource_pool.prb_num * 2) >
|
||||
(q->sl_comm_resource_pool.prb_end - q->sl_comm_resource_pool.prb_start + 1)) {
|
||||
k = (q->sl_comm_resource_pool.prb_end + 1 - q->sl_comm_resource_pool.prb_num + 1) * SRSLTE_NRE;
|
||||
} else {
|
||||
k = (q->sl_comm_resource_pool.prb_end + 1 - q->sl_comm_resource_pool.prb_num) * SRSLTE_NRE;
|
||||
}
|
||||
memcpy(&symbols[sample_pos],
|
||||
&sf_buffer[k + i * q->cell.nof_prb * SRSLTE_NRE],
|
||||
sizeof(cf_t) * (SRSLTE_NRE * (q->pssch_cfg.nof_prb - q->sl_comm_resource_pool.prb_num)));
|
||||
sample_pos += (SRSLTE_NRE * (q->pssch_cfg.nof_prb - q->sl_comm_resource_pool.prb_num));
|
||||
}
|
||||
} else if (q->cell.tm == SRSLTE_SIDELINK_TM3 || q->cell.tm == SRSLTE_SIDELINK_TM4) {
|
||||
memcpy(&symbols[sample_pos],
|
||||
&sf_buffer[k + i * q->cell.nof_prb * SRSLTE_NRE],
|
||||
sizeof(cf_t) * (SRSLTE_NRE * q->pssch_cfg.nof_prb));
|
||||
sample_pos += (SRSLTE_NRE * q->pssch_cfg.nof_prb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sample_pos;
|
||||
}
|
||||
|
||||
void srslte_pssch_free(srslte_pssch_t* q)
|
||||
{
|
||||
if (q) {
|
||||
srslte_dft_precoding_free(&q->dft_precoder);
|
||||
srslte_dft_precoding_free(&q->idft_precoder);
|
||||
srslte_tcod_free(&q->tcod);
|
||||
srslte_tdec_free(&q->tdec);
|
||||
srslte_sequence_free(&q->scrambling_seq);
|
||||
srslte_rm_turbo_free_tables();
|
||||
|
||||
for (int i = 0; i < SRSLTE_MOD_NITEMS; i++) {
|
||||
srslte_modem_table_free(&q->mod[i]);
|
||||
}
|
||||
|
||||
if (q->b) {
|
||||
free(q->b);
|
||||
}
|
||||
if (q->tb_crc_temp) {
|
||||
free(q->tb_crc_temp);
|
||||
}
|
||||
if (q->cb_crc_temp) {
|
||||
free(q->cb_crc_temp);
|
||||
}
|
||||
if (q->c_r) {
|
||||
free(q->c_r);
|
||||
}
|
||||
if (q->c_r_bytes) {
|
||||
free(q->c_r_bytes);
|
||||
}
|
||||
if (q->d_r) {
|
||||
free(q->d_r);
|
||||
}
|
||||
if (q->d_r_16) {
|
||||
free(q->d_r_16);
|
||||
}
|
||||
if (q->e_r) {
|
||||
free(q->e_r);
|
||||
}
|
||||
if (q->e_r_16) {
|
||||
free(q->e_r_16);
|
||||
}
|
||||
if (q->buff_b) {
|
||||
free(q->buff_b);
|
||||
}
|
||||
if (q->f) {
|
||||
free(q->f);
|
||||
}
|
||||
if (q->f_16) {
|
||||
free(q->f_16);
|
||||
}
|
||||
if (q->f_bytes) {
|
||||
free(q->f_bytes);
|
||||
}
|
||||
if (q->codeword) {
|
||||
free(q->codeword);
|
||||
}
|
||||
if (q->codeword_bytes) {
|
||||
free(q->codeword_bytes);
|
||||
}
|
||||
if (q->llr) {
|
||||
free(q->llr);
|
||||
}
|
||||
if (q->interleaver_lut) {
|
||||
free(q->interleaver_lut);
|
||||
}
|
||||
if (q->symbols) {
|
||||
free(q->symbols);
|
||||
}
|
||||
if (q->scfdma_symbols) {
|
||||
free(q->scfdma_symbols);
|
||||
}
|
||||
if (q->bits_after_demod) {
|
||||
free(q->bits_after_demod);
|
||||
}
|
||||
if (q->bytes_after_demod) {
|
||||
free(q->bytes_after_demod);
|
||||
}
|
||||
|
||||
bzero(q, sizeof(srslte_pssch_t));
|
||||
}
|
||||
}
|
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright 2013-2020 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsLTE.
|
||||
*
|
||||
* srsLTE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsLTE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "srslte/phy/common/phy_common_sl.h"
|
||||
#include "srslte/phy/phch/ra.h"
|
||||
#include "srslte/phy/phch/ra_sl.h"
|
||||
#include "srslte/phy/utils/random.h"
|
||||
|
||||
int srslte_sl_get_available_pool_prb(uint32_t prb_num, uint32_t prb_start, uint32_t prb_end)
|
||||
{
|
||||
if ((prb_num * 2) <= (prb_end - prb_start + 1)) {
|
||||
return prb_num * 2;
|
||||
} else {
|
||||
return prb_num * 2 - 1;
|
||||
}
|
||||
}
|
||||
|
||||
int srslte_pscch_resources(uint32_t prb_num,
|
||||
uint32_t prb_start,
|
||||
uint32_t prb_end,
|
||||
uint8_t* pscch_sf_bitmap,
|
||||
uint32_t period_length,
|
||||
uint32_t n_pscch,
|
||||
uint32_t* m_a,
|
||||
uint32_t* l_b)
|
||||
{
|
||||
uint8_t M = srslte_sl_get_available_pool_prb(prb_num, prb_start, prb_end);
|
||||
uint32_t L = 0;
|
||||
for (uint32_t i = 0; i < period_length; i++) {
|
||||
if (pscch_sf_bitmap[i] == 1) {
|
||||
L++;
|
||||
}
|
||||
}
|
||||
|
||||
if (L == 0) {
|
||||
// ERROR("Invalid PSCCH subframe bitmap");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
n_pscch = n_pscch % (L * M / 2);
|
||||
|
||||
uint32_t a1 = n_pscch / L; // RB index A
|
||||
uint32_t b1 = n_pscch % L; // SF index A
|
||||
uint32_t a2 = a1 + M / 2; // RB index B
|
||||
uint32_t b2 = (n_pscch + 1 + (a1 % (L - 1))) % L; // SF index B
|
||||
|
||||
m_a[0] = a1 + prb_start; // PRB 1
|
||||
m_a[1] = a2 + (prb_end + 1 - M); // PRB 2
|
||||
|
||||
uint32_t k = 0;
|
||||
for (uint32_t i = 0; i < period_length; i++) {
|
||||
if (pscch_sf_bitmap[i] == 1) {
|
||||
k++;
|
||||
if (k == (b1 + 1)) {
|
||||
l_b[0] = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
k = 0;
|
||||
for (uint32_t i = 0; i < period_length; i++) {
|
||||
if (pscch_sf_bitmap[i] == 1) {
|
||||
k++;
|
||||
if (k == (b2 + 1)) {
|
||||
l_b[1] = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
// 3GPP TS 36.213 Section 8.1.1. Uplink resource allocation type 0
|
||||
uint32_t srslte_ra_sl_type0_to_riv(uint32_t nof_prb, uint32_t prb_start, uint32_t L_crb)
|
||||
{
|
||||
return srslte_ra_type2_to_riv(L_crb, prb_start, nof_prb);
|
||||
}
|
||||
|
||||
// 3GPP TS 36.213 Section 8.1.1. Uplink resource allocation type 0
|
||||
void srslte_ra_sl_type0_from_riv(uint32_t riv, uint32_t nof_prb, uint32_t* L_crb, uint32_t* prb_start)
|
||||
{
|
||||
srslte_ra_type2_from_riv(riv, L_crb, prb_start, nof_prb, nof_prb);
|
||||
}
|
||||
|
||||
int srslte_ra_sl_pssch_allowed_sf(uint32_t pssch_sf_idx, uint32_t trp_idx, uint32_t duplex_mode, uint32_t tdd_config)
|
||||
{
|
||||
if (duplex_mode == SRSLTE_SL_DUPLEX_MODE_FDD) {
|
||||
return srslte_sl_N_TRP_8[trp_idx][pssch_sf_idx % 8];
|
||||
}
|
||||
switch (tdd_config) {
|
||||
// N_TRP = 6
|
||||
case 3:
|
||||
case 6:
|
||||
return srslte_sl_N_TRP_6[trp_idx][pssch_sf_idx % 6];
|
||||
// N_TRP = 7
|
||||
case 0:
|
||||
return srslte_sl_N_TRP_7[trp_idx][pssch_sf_idx % 7];
|
||||
// N_TRP = 8
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 5:
|
||||
return srslte_sl_N_TRP_8[trp_idx][pssch_sf_idx % 8];
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int srslte_sci_generate_trp_idx(uint32_t duplex_mode, uint32_t tdd_config, uint32_t k_TRP)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
srslte_random_t random = srslte_random_init(tv.tv_usec);
|
||||
|
||||
// N_TRP = 8
|
||||
if (duplex_mode == SRSLTE_SL_DUPLEX_MODE_FDD || tdd_config == 1 || tdd_config == 2 || tdd_config == 4 ||
|
||||
tdd_config == 5) {
|
||||
switch (k_TRP) {
|
||||
case 1:
|
||||
return srslte_sl_N_TRP_8_k_1[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_8_k_1) - 1)];
|
||||
case 2:
|
||||
return srslte_sl_N_TRP_8_k_2[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_8_k_2) - 1)];
|
||||
case 4:
|
||||
return srslte_sl_N_TRP_8_k_4[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_8_k_4) - 1)];
|
||||
case 8:
|
||||
return srslte_sl_N_TRP_8_k_8[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_8_k_8) - 1)];
|
||||
default:
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
// N_TRP = 7
|
||||
} else if (tdd_config == 0) {
|
||||
switch (k_TRP) {
|
||||
case 1:
|
||||
return srslte_sl_N_TRP_7_k_1[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_7_k_1) - 1)];
|
||||
case 2:
|
||||
return srslte_sl_N_TRP_7_k_2[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_7_k_2) - 1)];
|
||||
case 3:
|
||||
return srslte_sl_N_TRP_7_k_3[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_7_k_3) - 1)];
|
||||
case 4:
|
||||
return srslte_sl_N_TRP_7_k_4[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_7_k_4) - 1)];
|
||||
case 5:
|
||||
return srslte_sl_N_TRP_7_k_5[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_7_k_5) - 1)];
|
||||
case 6:
|
||||
return srslte_sl_N_TRP_7_k_6[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_7_k_6) - 1)];
|
||||
case 7:
|
||||
return srslte_sl_N_TRP_7_k_7[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_7_k_7) - 1)];
|
||||
default:
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
// N_TRP = 6
|
||||
} else if (tdd_config == 3 || tdd_config == 6) {
|
||||
switch (k_TRP) {
|
||||
case 1:
|
||||
return srslte_sl_N_TRP_6_k_1[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_6_k_1) - 1)];
|
||||
case 2:
|
||||
return srslte_sl_N_TRP_6_k_2[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_6_k_2) - 1)];
|
||||
case 3:
|
||||
return srslte_sl_N_TRP_6_k_3[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_6_k_3) - 1)];
|
||||
case 4:
|
||||
return srslte_sl_N_TRP_6_k_4[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_6_k_4) - 1)];
|
||||
case 5:
|
||||
return srslte_sl_N_TRP_6_k_5[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_6_k_5) - 1)];
|
||||
case 6:
|
||||
return srslte_sl_N_TRP_6_k_6[srslte_random_uniform_int_dist(random, 0, sizeof(srslte_sl_N_TRP_6_k_6) - 1)];
|
||||
default:
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 2013-2020 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsLTE.
|
||||
*
|
||||
* srsLTE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsLTE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "srslte/phy/phch/pssch.h"
|
||||
#include "srslte/phy/utils/debug.h"
|
||||
#include "srslte/phy/utils/random.h"
|
||||
#include "srslte/phy/utils/vector.h"
|
||||
|
||||
srslte_cell_sl_t cell = {.nof_prb = 6, .N_sl_id = 0, .tm = SRSLTE_SIDELINK_TM2, .cp = SRSLTE_CP_NORM};
|
||||
|
||||
uint32_t mcs_idx = 4;
|
||||
uint32_t prb_start_idx = 0;
|
||||
|
||||
void usage(char* prog)
|
||||
{
|
||||
printf("Usage: %s [emptv]\n", prog);
|
||||
printf("\t-p nof_prb [Default %d]\n", cell.nof_prb);
|
||||
printf("\t-m mcs_idx [Default %d]\n", mcs_idx);
|
||||
printf("\t-e extended CP [Default normal]\n");
|
||||
printf("\t-t Sidelink transmission mode {1,2,3,4} [Default %d]\n", (cell.tm + 1));
|
||||
printf("\t-v [set srslte_verbose to debug, default none]\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, char** argv)
|
||||
{
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "emptv")) != -1) {
|
||||
switch (opt) {
|
||||
case 'e':
|
||||
cell.cp = SRSLTE_CP_EXT;
|
||||
break;
|
||||
case 'm':
|
||||
mcs_idx = (uint32_t)strtol(argv[optind], NULL, 10);
|
||||
break;
|
||||
case 'p':
|
||||
cell.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10);
|
||||
break;
|
||||
case 't':
|
||||
if (srslte_sl_tm_to_cell_sl_tm_t(&cell, strtol(argv[optind], NULL, 10)) != SRSLTE_SUCCESS) {
|
||||
usage(argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
srslte_verbose++;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
if (SRSLTE_CP_ISEXT(cell.cp) && cell.tm >= SRSLTE_SIDELINK_TM3) {
|
||||
ERROR("Selected TM does not support extended CP");
|
||||
usage(argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
uint32_t ret = SRSLTE_ERROR;
|
||||
|
||||
parse_args(argc, argv);
|
||||
|
||||
srslte_sl_comm_resource_pool_t sl_comm_resource_pool;
|
||||
if (srslte_sl_comm_resource_pool_get_default_config(&sl_comm_resource_pool, cell) != SRSLTE_SUCCESS) {
|
||||
ERROR("Error initializing sl_comm_resource_pool\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
srslte_pssch_t pssch;
|
||||
if (srslte_pssch_init(&pssch, cell, sl_comm_resource_pool) != SRSLTE_SUCCESS) {
|
||||
ERROR("Error initializing PSSCH\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// FIXME: Due to srslte_dft_precoding, many values give error
|
||||
uint32_t nof_prb_pssch = cell.nof_prb;
|
||||
while (srslte_dft_precoding_valid_prb(nof_prb_pssch) == false) {
|
||||
nof_prb_pssch--;
|
||||
if (nof_prb_pssch == 0) {
|
||||
ERROR("Invalid parameters");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t N_x_id = 255;
|
||||
uint32_t sf_n_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
|
||||
cf_t* sf_buffer = srslte_vec_cf_malloc(sf_n_re);
|
||||
|
||||
// Transport block buffer
|
||||
uint8_t tb[SRSLTE_SL_SCH_MAX_TB_LEN] = {};
|
||||
|
||||
// Rx transport block buffer
|
||||
uint8_t tb_rx[SRSLTE_SL_SCH_MAX_TB_LEN] = {};
|
||||
|
||||
srslte_pssch_cfg_t pssch_cfg = {prb_start_idx, nof_prb_pssch, N_x_id, mcs_idx, 0, 0};
|
||||
if (srslte_pssch_set_cfg(&pssch, pssch_cfg) != SRSLTE_SUCCESS) {
|
||||
ERROR("Error configuring PSSCH\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// Randomize data to fill the transport block
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
srslte_random_t random = srslte_random_init(tv.tv_usec);
|
||||
for (int i = 0; i < pssch.sl_sch_tb_len; i++) {
|
||||
tb[i] = srslte_random_uniform_int_dist(random, 0, 1);
|
||||
}
|
||||
|
||||
// PSSCH encoding
|
||||
if (srslte_pssch_encode(&pssch, tb, pssch.sl_sch_tb_len, sf_buffer) != SRSLTE_SUCCESS) {
|
||||
ERROR("Error encoding PSSCH\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// PSSCH decoding
|
||||
if (srslte_pssch_decode(&pssch, sf_buffer, tb_rx, pssch.sl_sch_tb_len) != SRSLTE_SUCCESS) {
|
||||
ERROR("Error decoding PSSCH\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (memcmp(tb_rx, tb, pssch.sl_sch_tb_len) == 0) {
|
||||
ret = SRSLTE_SUCCESS;
|
||||
} else {
|
||||
ret = SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
clean_exit:
|
||||
free(sf_buffer);
|
||||
srslte_pssch_free(&pssch);
|
||||
|
||||
printf("%s", ret == SRSLTE_SUCCESS ? "SUCCESS\n" : "FAILED\n");
|
||||
return ret;
|
||||
}
|
Loading…
Reference in New Issue