PSSCH implementation

master
luis_pereira87 5 years ago committed by Andre Puschmann
parent 4e283ec942
commit baf0ad5bf4

@ -32,6 +32,8 @@
#include "srslte/phy/common/phy_common_sl.h"
#include "srslte/phy/dft/ofdm.h"
#include "srslte/phy/phch/pscch.h"
#include "srslte/phy/phch/pssch.h"
#include "srslte/phy/phch/ra_sl.h"
#include "srslte/phy/phch/sci.h"
#include "srslte/phy/rf/rf.h"
#include "srslte/phy/ue/ue_sync.h"
@ -50,7 +52,8 @@ srslte_cell_sl_t cell_sl = {.nof_prb = 50, .tm = SRSLTE_SIDELINK_TM4, .c
bool use_standard_lte_rates = false;
bool disable_plots = false;
srslte_pscch_t pscch; // Defined global for plotting thread
static srslte_pscch_t pscch = {}; // Defined global for plotting thread
static srslte_pssch_t pssch = {};
#ifdef ENABLE_GUI
#include "srsgui/srsgui.h"
@ -241,6 +244,22 @@ int main(int argc, char** argv)
return SRSLTE_ERROR;
}
if (srslte_pssch_init(&pssch, cell_sl, sl_comm_resource_pool) != SRSLTE_SUCCESS) {
ERROR("Error initializing PSSCH\n");
return SRSLTE_ERROR;
}
srslte_chest_sl_cfg_t pssch_chest_sl_cfg;
srslte_chest_sl_t pssch_chest;
if (srslte_chest_sl_init(&pssch_chest, SRSLTE_SIDELINK_PSSCH, cell_sl, sl_comm_resource_pool) != SRSLTE_SUCCESS) {
ERROR("Error in chest PSSCH init\n");
return SRSLTE_ERROR;
}
uint32_t num_decoded_tb = 0;
uint8_t tb[SRSLTE_SL_SCH_MAX_TB_LEN] = {};
uint32_t pssch_sf_idx = 0;
srslte_ue_sync_t sync;
if (srslte_ue_sync_init_multi_decim_mode(
&sync, SRSLTE_MAX_PRB, false, srslte_rf_recv_wrapper, nof_rx_antennas, (void*)&rf, 1.0, SYNC_MODE_GNSS)) {
@ -289,6 +308,8 @@ int main(int argc, char** argv)
ts_rx.frac_secs,
srslte_ue_sync_get_sfn(&sync),
srslte_ue_sync_get_sfidx(&sync));
pssch_sf_idx = (srslte_ue_sync_get_sfn(&sync) * 10) + srslte_ue_sync_get_sfidx(&sync);
}
// do FFT
@ -318,6 +339,47 @@ int main(int argc, char** argv)
sem_post(&plot_sem);
}
#endif
// Decode PSSCH
uint32_t sub_channel_start_idx = 0;
uint32_t L_subCH = 0;
srslte_ra_sl_type0_from_riv(
sci.riv, sl_comm_resource_pool.num_sub_channel, &L_subCH, &sub_channel_start_idx);
// 3GPP TS 36.213 Section 14.1.1.4C
uint32_t pssch_prb_start_idx = (sub_channel_idx * sl_comm_resource_pool.size_sub_channel) +
pscch.pscch_nof_prb + sl_comm_resource_pool.start_prb_sub_channel;
uint32_t nof_prb_pssch = ((L_subCH + sub_channel_idx) * sl_comm_resource_pool.size_sub_channel) -
pssch_prb_start_idx + sl_comm_resource_pool.start_prb_sub_channel;
uint32_t N_x_id = 0;
for (int j = 0; j < SRSLTE_SCI_CRC_LEN; j++) {
N_x_id += pscch.sci_crc[j] * exp2(SRSLTE_SCI_CRC_LEN - 1 - j);
}
uint32_t rv_idx = 0;
if (sci.retransmission == true) {
rv_idx = 1;
}
// PSSCH Channel estimation
pssch_chest_sl_cfg.N_x_id = N_x_id;
pssch_chest_sl_cfg.sf_idx = pssch_sf_idx;
pssch_chest_sl_cfg.prb_start_idx = pssch_prb_start_idx;
pssch_chest_sl_cfg.nof_prb = nof_prb_pssch;
srslte_chest_sl_set_cfg(&pssch_chest, pssch_chest_sl_cfg);
srslte_chest_sl_ls_estimate_equalize(&pssch_chest, sf_buffer[0], equalized_sf_buffer);
srslte_pssch_cfg_t pssch_cfg = {
pssch_prb_start_idx, nof_prb_pssch, N_x_id, sci.mcs_idx, rv_idx, pssch_sf_idx};
if (srslte_pssch_set_cfg(&pssch, pssch_cfg) == SRSLTE_SUCCESS) {
if (srslte_pssch_decode(&pssch, equalized_sf_buffer, tb, SRSLTE_SL_SCH_MAX_TB_LEN) == SRSLTE_SUCCESS) {
srslte_vec_fprint_byte(stdout, tb, pssch.sl_sch_tb_len);
num_decoded_tb++;
printf("PSSCH num_decoded_tb: %d\n", num_decoded_tb);
}
}
}
}
if (SRSLTE_VERBOSE_ISDEBUG()) {
@ -333,7 +395,7 @@ int main(int argc, char** argv)
}
}
}
pssch_sf_idx++;
subframe_count++;
}

@ -57,6 +57,7 @@ typedef struct SRSLTE_API {
srslte_cp_t cp;
} srslte_cell_sl_t;
#define SRSLTE_SL_MAX_PERIOD_LENGTH 320 // SL-PeriodComm-r12 3GPP TS 36.331 Section 6.3.8
// SL-CommResourcePool: 3GPP TS 36.331 version 15.6.0 Release 15 Section 6.3.8
typedef struct SRSLTE_API {
uint32_t period_length;
@ -65,10 +66,16 @@ typedef struct SRSLTE_API {
uint32_t prb_start;
uint32_t prb_end;
uint8_t pscch_sf_bitmap[SRSLTE_SL_MAX_PERIOD_LENGTH];
uint8_t pssch_sf_bitmap[SRSLTE_SL_MAX_PERIOD_LENGTH];
uint32_t size_sub_channel; // sizeSubchannel-r14
uint32_t num_sub_channel; // numSubchannel-r14
uint32_t start_prb_sub_channel; // startRB-Subchannel-r14 offset
bool adjacency_pscch_pssch; // adjacencyPSCCH-PSSCH-r14
uint32_t sf_bitmap_tm34_len;
uint8_t sf_bitmap_tm34[SRSLTE_SL_MAX_PERIOD_LENGTH]; // sl_Subframe_r14: 3GPP 36.331 Section 6.3.8
} srslte_sl_comm_resource_pool_t;
typedef enum SRSLTE_API {
@ -81,6 +88,10 @@ typedef enum SRSLTE_API {
#define SRSLTE_SL_DUPLEX_MODE_FDD (1)
#define SRSLTE_SL_DUPLEX_MODE_TDD (2)
#define SRSLTE_SLSS_SIDE_PEAK_OFFSET (0.005f)
#define SRSLTE_SLSS_SIDE_PEAK_THRESHOLD_HIGH (0.49f) // square(0.7), max 70% of main peak
#define SRSLTE_SLSS_SIDE_PEAK_THRESHOLD_LOW (0.09f) // square(0.3), min 30% of main peak
#define SRSLTE_PSBCH_NOF_PRB (6)
#define SRSLTE_PSCCH_TM34_NOF_PRB (2)
@ -124,9 +135,11 @@ typedef enum SRSLTE_API {
(SRSLTE_NRE * SRSLTE_PSCCH_TM34_NUM_DATA_SYMBOLS * SRSLTE_PSCCH_TM34_NOF_PRB * SRSLTE_PSCCH_QM)
#define SRSLTE_PSCCH_MAX_CODED_BITS SRSLTE_MAX(SRSLTE_PSCCH_TM12_NOF_CODED_BITS, SRSLTE_PSCCH_TM34_NOF_CODED_BITS)
#define SRSLTE_PSSCH_MAX_QM 6
#define SRSLTE_PSSCH_CRC_LEN 24
#define SRSLTE_MAX_CODEWORD_LEN 168000 // 12 subcarriers * 100 PRB * 14 symbols * 10 bits, assuming 1024QAM
#define SRSLTE_SL_SCH_MAX_TB_LEN 1000000 // Must be checked in 3GPP
#define SRSLTE_PSSCH_MAX_CODED_BITS (3 * SRSLTE_TCOD_MAX_LEN_CB + SRSLTE_TCOD_TOTALTAIL)
#define SRSLTE_PSSCH_TM12_NUM_DATA_SYMBOLS (12) // PSSCH is in 12 OFDM symbols (but only 11 are tx'ed)
#define SRSLTE_PSSCH_TM12_NUM_DMRS_SYMBOLS (2) // PSSCH has 2 DMRS symbols in TM1 and TM2
@ -142,6 +155,14 @@ typedef enum SRSLTE_API {
SRSLTE_API int srslte_sl_group_hopping_f_gh(uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME * 2], uint32_t N_x_id);
#define SRSLTE_PSCCH_MAX_NUM_DATA_SYMBOLS (SRSLTE_PSCCH_TM12_NUM_DATA_SYMBOLS)
SRSLTE_API bool srslte_slss_side_peak_pos_is_valid(uint32_t side_peak_pos,
uint32_t main_peak_pos,
uint32_t side_peak_delta_a,
uint32_t side_peak_delta_b);
SRSLTE_API bool srslte_slss_side_peak_value_is_valid(float side_peak_value, float threshold_low, float threshold_high);
SRSLTE_API int srslte_sl_tm_to_cell_sl_tm_t(srslte_cell_sl_t* q, uint32_t tm);
SRSLTE_API int srslte_sl_get_num_symbols(srslte_sl_tm_t tm, srslte_cp_t cp);
SRSLTE_API bool srslte_psbch_is_symbol(srslte_sl_symbol_t type, srslte_sl_tm_t tm, uint32_t i, srslte_cp_t cp);
SRSLTE_API bool srslte_pscch_is_symbol(srslte_sl_symbol_t type, srslte_sl_tm_t tm, uint32_t i, srslte_cp_t cp);

@ -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

@ -95,6 +95,8 @@ SRSLTE_API void* srslte_vec_realloc(void* ptr, uint32_t old_size, uint32_t new_s
SRSLTE_API void srslte_vec_cf_zero(cf_t* ptr, uint32_t nsamples);
SRSLTE_API void srslte_vec_f_zero(float* ptr, uint32_t nsamples);
SRSLTE_API void srslte_vec_u8_zero(uint8_t* ptr, uint32_t nsamples);
SRSLTE_API void srslte_vec_i16_zero(int16_t* ptr, uint32_t nsamples);
SRSLTE_API void srslte_vec_u32_zero(uint32_t* ptr, uint32_t nsamples);
/* Copy memory */
SRSLTE_API void srs_vec_cf_copy(cf_t* dst, const cf_t* src, uint32_t len);

@ -24,6 +24,7 @@
#include "srslte/phy/common/phy_common_sl.h"
#include "srslte/phy/common/sequence.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
int srslte_sl_group_hopping_f_gh(uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME * 2], uint32_t N_x_id)
{
@ -45,6 +46,50 @@ int srslte_sl_group_hopping_f_gh(uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME * 2], uint3
return SRSLTE_SUCCESS;
}
bool srslte_slss_side_peak_pos_is_valid(uint32_t side_peak_pos,
uint32_t main_peak_pos,
uint32_t side_peak_delta_a,
uint32_t side_peak_delta_b)
{
if ((side_peak_pos >= (main_peak_pos - side_peak_delta_b)) &&
(side_peak_pos <= (main_peak_pos - side_peak_delta_a))) {
return true;
} else if ((side_peak_pos >= (main_peak_pos + side_peak_delta_a)) &&
(side_peak_pos <= (main_peak_pos + side_peak_delta_b))) {
return true;
}
return false;
}
bool srslte_slss_side_peak_value_is_valid(float side_peak_value, float threshold_low, float threshold_high)
{
if ((side_peak_value >= threshold_low) && (side_peak_value <= threshold_high)) {
return true;
}
return false;
}
int srslte_sl_tm_to_cell_sl_tm_t(srslte_cell_sl_t* q, uint32_t tm)
{
switch (tm) {
case 1:
q->tm = SRSLTE_SIDELINK_TM1;
break;
case 2:
q->tm = SRSLTE_SIDELINK_TM2;
break;
case 3:
q->tm = SRSLTE_SIDELINK_TM3;
break;
case 4:
q->tm = SRSLTE_SIDELINK_TM4;
break;
default:
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
int srslte_sl_get_num_symbols(srslte_sl_tm_t tm, srslte_cp_t cp)
{
if (tm == SRSLTE_SIDELINK_TM1 || tm == SRSLTE_SIDELINK_TM2) {
@ -279,11 +324,23 @@ int srslte_sl_comm_resource_pool_get_default_config(srslte_sl_comm_resource_pool
q->prb_start = 0;
q->prb_end = cell.nof_prb - 1;
// 0110000000000000000000000000000000000000
bzero(q->pscch_sf_bitmap, SRSLTE_SL_MAX_PERIOD_LENGTH);
memset(&q->pscch_sf_bitmap[1], 1, 2);
// 0001111111111111111111111111111111111111
bzero(q->pssch_sf_bitmap, SRSLTE_SL_MAX_PERIOD_LENGTH);
memset(&q->pssch_sf_bitmap[3], 1, 37);
q->size_sub_channel = 10;
q->num_sub_channel = 5;
q->start_prb_sub_channel = 0;
q->adjacency_pscch_pssch = true;
q->sf_bitmap_tm34_len = 10;
bzero(q->sf_bitmap_tm34, SRSLTE_SL_MAX_PERIOD_LENGTH);
memset(q->sf_bitmap_tm34, 1, q->sf_bitmap_tm34_len);
if (cell.tm == SRSLTE_SIDELINK_TM4) {
switch (cell.nof_prb) {
case 6:

@ -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;
}

@ -88,43 +88,72 @@ add_test(pscch_test_tm4_p50 pscch_test -p 50 -t 4)
add_test(pscch_test_tm4_p75 pscch_test -p 75 -t 4)
add_test(pscch_test_tm4_p100 pscch_test -p 100 -t 4)
add_executable(pscch_file_test pscch_file_test.c)
target_link_libraries(pscch_file_test srslte_phy)
########################################################################
# PSSCH TEST
########################################################################
add_executable(pssch_test pssch_test.c)
target_link_libraries(pssch_test srslte_phy)
# TM2 self tests
add_test(pssch_test_tm2_p6 pssch_test -p 6 -m 2)
add_test(pssch_test_tm2_p15 pssch_test -p 15 -m 6)
add_test(pssch_test_tm2_p25 pssch_test -p 25 -m 7)
add_test(pssch_test_tm2_p50 pssch_test -p 50 -m 9)
add_test(pssch_test_tm2_p50_ext pssch_test -p 50 -m 9 -e)
add_test(pssch_test_tm2_p75 pssch_test -p 75 -m 17)
add_test(pssch_test_tm2_p100 pssch_test -p 100 -m 21)
add_test(pssch_test_tm2_p100_ext pssch_test -p 100 -m 21 -e)
# TM4 self tests
add_test(pssch_test_tm4_p6 pssch_test -p 6 -t 4 -m 2)
add_test(pssch_test_tm4_p15 pssch_test -p 15 -t 4 -m 6)
add_test(pssch_test_tm4_p25 pssch_test -p 25 -t 4 -m 7)
add_test(pssch_test_tm4_p50 pssch_test -p 50 -t 4 -m 9)
add_test(pssch_test_tm4_p75 pssch_test -p 75 -t 4 -m 17)
add_test(pssch_test_tm4_p100 pssch_test -p 100 -t 4 -m 21)
########################################################################
# PSCCH AND PSSCH FILE TEST
########################################################################
add_executable(pssch_pscch_file_test pssch_pscch_file_test.c)
target_link_libraries(pssch_pscch_file_test srslte_phy)
# TM2 file tests
add_test(pscch_file_test_ideal_tm2_p100 pscch_file_test -p 100 -t 2 -d -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_ideal_tm2_p100_c335_s30.72e6.dat)
set_property(TEST pscch_file_test_ideal_tm2_p100 PROPERTY PASS_REGULAR_EXPRESSION "num_decoded_sci=2")
add_test(pssch_pscch_file_test_ideal_tm2_p100 pssch_pscch_file_test -p 100 -d -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_ideal_tm2_p100_c335_s30.72e6.dat)
set_property(TEST pssch_pscch_file_test_ideal_tm2_p100 PROPERTY PASS_REGULAR_EXPRESSION "num_decoded_sci=2 num_decoded_tb=1")
# TM4 file tests
add_test(pscch_file_test_ideal_tm4_p100 pscch_file_test -p 100 -t 4 -s 10 -n 10 -d -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_ideal_tm4_p100_c335_size10_num10_cshift0_s30.72e6.dat)
set_property(TEST pscch_file_test_ideal_tm4_p100 PROPERTY PASS_REGULAR_EXPRESSION "num_decoded_sci=1")
add_test(pssch_pscch_file_test_ideal_tm4_p100 pssch_pscch_file_test -p 100 -t 4 -s 10 -n 10 -d -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_ideal_tm4_p100_c335_size10_num10_cshift0_s30.72e6.dat)
set_property(TEST pssch_pscch_file_test_ideal_tm4_p100 PROPERTY PASS_REGULAR_EXPRESSION "num_decoded_sci=1 num_decoded_tb=1")
add_test(pscch_test_tm4_p50_qc pscch_file_test -p 50 -t 4 -d -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_qc9150_f5.92e9_s15.36e6_50prb_20offset.dat)
set_property(TEST pscch_test_tm4_p50_qc PROPERTY PASS_REGULAR_EXPRESSION "num_decoded_sci=1")
add_test(pssch_pscch_test_tm4_p50_qc pssch_pscch_file_test -p 50 -t 4 -d -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_qc9150_f5.92e9_s15.36e6_50prb_20offset.dat)
set_property(TEST pssch_pscch_test_tm4_p50_qc PROPERTY PASS_REGULAR_EXPRESSION "num_decoded_sci=1 num_decoded_tb=1")
# Capture has a SFO offset of ~64 samples, but offsetting by 20 is sufficiant to decode it
add_test(pscch_test_tm4_p50_cmw pscch_file_test -p 50 -t 4 -o 20 -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_cmw500_f5.92e9_s11.52e6_50prb_0offset_1ms.dat)
set_property(TEST pscch_test_tm4_p50_cmw PROPERTY PASS_REGULAR_EXPRESSION "num_decoded_sci=1")
# Capture has a SFO offset of ~64 samples, but offsetting by 20 is enough to decode it
add_test(pssch_pscch_test_tm4_p50_cmw pssch_pscch_file_test -p 50 -t 4 -o 20 -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_cmw500_f5.92e9_s11.52e6_50prb_0offset_1ms.dat)
set_property(TEST pssch_pscch_test_tm4_p50_cmw PROPERTY PASS_REGULAR_EXPRESSION "num_decoded_sci=1 num_decoded_tb=1")
# With PHY retransmission (3 TTI offset)
add_test(pscch_test_tm4_p50_huawei pscch_file_test -p 50 -t 4 -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_huawei_s11.52e6_50prb_10prb_offset_with_retx.dat)
set_property(TEST pscch_test_tm4_p50_huawei PROPERTY PASS_REGULAR_EXPRESSION "num_decoded_sci=2")
add_test(pssch_pscch_test_tm4_p50_huawei pssch_pscch_file_test -p 50 -t 4 -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_huawei_s11.52e6_50prb_10prb_offset_with_retx.dat)
set_property(TEST pssch_pscch_test_tm4_p50_huawei PROPERTY PASS_REGULAR_EXPRESSION "num_decoded_sci=2 num_decoded_tb=2")
# With PHY ReTx (0 TTI offset?)
add_test(pscch_test_tm4_p50_uxm1 pscch_file_test -p 50 -d -t 4 -s 5 -n 10 -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_uxm_s15.36e6_50prb_0prb_offset_mcs12.dat)
set_property(TEST pscch_test_tm4_p50_uxm1 PROPERTY PASS_REGULAR_EXPRESSION "mcs=12.*num_decoded_sci=2")
add_test(pssch_pscch_test_tm4_p50_uxm1 pssch_pscch_file_test -p 50 -d -t 4 -s 5 -n 10 -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_uxm_s15.36e6_50prb_0prb_offset_mcs12.dat)
set_property(TEST pssch_pscch_test_tm4_p50_uxm1 PROPERTY PASS_REGULAR_EXPRESSION "mcs=12.*num_decoded_sci=2 num_decoded_tb=2")
# 100 PRB startOffset 1 MCS12 MAC padding
add_test(pscch_test_tm4_p100_uxm2 pscch_file_test -p 100 -t 4 -s 10 -n 10 -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_uxm_s23.04e6_100prb_1prb_offset_mcs12_padding.dat)
set_property(TEST pscch_test_tm4_p100_uxm2 PROPERTY PASS_REGULAR_EXPRESSION "mcs=12.*num_decoded_sci=4")
add_test(pssch_pscch_test_tm4_p100_uxm2 pssch_pscch_file_test -p 100 -t 4 -s 10 -n 10 -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_uxm_s23.04e6_100prb_1prb_offset_mcs12_padding.dat)
set_property(TEST pssch_pscch_test_tm4_p100_uxm2 PROPERTY PASS_REGULAR_EXPRESSION "mcs=12.*num_decoded_sci=4 num_decoded_tb=4")
# 100 PRB LTE sampling rate, startOffset1 MCS12 ITS data
add_test(pscch_test_tm4_p100_uxm3 pscch_file_test -p 100 -d -t 4 -s 10 -n 10 -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_uxm_s30.72e6_100prb_1prb_offset_mcs12_its.dat)
set_property(TEST pscch_test_tm4_p100_uxm3 PROPERTY PASS_REGULAR_EXPRESSION "mcs=12.*num_decoded_sci=1")
add_test(pssch_pscch_test_tm4_p100_uxm3 pssch_pscch_file_test -p 100 -d -t 4 -s 10 -n 10 -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_uxm_s30.72e6_100prb_1prb_offset_mcs12_its.dat)
set_property(TEST pssch_pscch_test_tm4_p100_uxm3 PROPERTY PASS_REGULAR_EXPRESSION "mcs=12.*num_decoded_sci=1 num_decoded_tb=1")
# 50 PRB LTE sampling rate, startOffset0 MCS28 MAC padding
add_test(pscch_test_tm4_p50_uxm4 pscch_file_test -p 50 -d -t 4 -s 5 -n 10 -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_uxm_s15.36e6_50prb_0prb_offset_mcs28_padding_5ms.dat)
set_property(TEST pscch_test_tm4_p50_uxm4 PROPERTY PASS_REGULAR_EXPRESSION "mcs=28.*num_decoded_sci=5")
add_test(pssch_pscch_test_tm4_p50_uxm4 pssch_pscch_file_test -p 50 -d -t 4 -s 5 -n 10 -i ${CMAKE_HOME_DIRECTORY}/lib/src/phy/phch/test/signal_sidelink_uxm_s15.36e6_50prb_0prb_offset_mcs28_padding_5ms.dat)
set_property(TEST pssch_pscch_test_tm4_p50_uxm4 PROPERTY PASS_REGULAR_EXPRESSION "mcs=28.*num_decoded_sci=5 num_decoded_tb=5")
########################################################################
# NPBCH TEST

@ -30,6 +30,8 @@
#include "srslte/phy/dft/ofdm.h"
#include "srslte/phy/io/filesource.h"
#include "srslte/phy/phch/pscch.h"
#include "srslte/phy/phch/pssch.h"
#include "srslte/phy/phch/ra_sl.h"
#include "srslte/phy/phch/sci.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
@ -47,12 +49,15 @@ static cf_t* input_buffer = NULL;
static srslte_sci_t sci = {};
static srslte_pscch_t pscch = {};
static srslte_chest_sl_t pscch_chest = {};
static srslte_pssch_t pssch = {};
static srslte_chest_sl_t pssch_chest = {};
static srslte_ofdm_t fft = {};
static srslte_sl_comm_resource_pool_t sl_comm_resource_pool = {};
static uint32_t size_sub_channel = 10;
static uint32_t num_sub_channel = 5;
static srslte_chest_sl_cfg_t pscch_chest_sl_cfg = {};
static srslte_chest_sl_cfg_t pssch_chest_sl_cfg = {};
static srslte_filesource_t fsrc = {};
@ -97,23 +102,9 @@ void parse_args(int argc, char** argv)
cell.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10);
break;
case 't':
switch ((int32_t)strtol(argv[optind], NULL, 10)) {
case 1:
cell.tm = SRSLTE_SIDELINK_TM1;
break;
case 2:
cell.tm = SRSLTE_SIDELINK_TM2;
break;
case 3:
cell.tm = SRSLTE_SIDELINK_TM3;
break;
case 4:
cell.tm = SRSLTE_SIDELINK_TM4;
break;
default:
if (srslte_sl_tm_to_cell_sl_tm_t(&cell, strtol(argv[optind], NULL, 10)) != SRSLTE_SUCCESS) {
usage(argv[0]);
exit(-1);
break;
}
break;
case 'v':
@ -124,7 +115,7 @@ void parse_args(int argc, char** argv)
exit(-1);
}
}
if (cell.cp == SRSLTE_CP_EXT && cell.tm >= SRSLTE_SIDELINK_TM3) {
if (SRSLTE_CP_ISEXT(cell.cp) && cell.tm >= SRSLTE_SIDELINK_TM3) {
ERROR("Selected TM does not support extended CP");
usage(argv[0]);
exit(-1);
@ -178,6 +169,16 @@ int base_init()
return SRSLTE_ERROR;
}
if (srslte_pssch_init(&pssch, cell, sl_comm_resource_pool) != SRSLTE_SUCCESS) {
ERROR("Error initializing PSSCH\n");
return SRSLTE_ERROR;
}
if (srslte_chest_sl_init(&pssch_chest, SRSLTE_SIDELINK_PSSCH, cell, sl_comm_resource_pool) != SRSLTE_SUCCESS) {
ERROR("Error in chest PSSCH init\n");
return SRSLTE_ERROR;
}
if (input_file_name) {
if (srslte_filesource_init(&fsrc, input_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) {
printf("Error opening file %s\n", input_file_name);
@ -207,6 +208,9 @@ void base_free()
srslte_pscch_free(&pscch);
srslte_chest_sl_free(&pscch_chest);
srslte_pssch_free(&pssch);
srslte_chest_sl_free(&pssch_chest);
if (sf_buffer) {
free(sf_buffer);
}
@ -232,13 +236,21 @@ int main(int argc, char** argv)
return SRSLTE_ERROR;
}
bool sci_decoded = false;
uint32_t num_decoded_sci = 0;
char sci_msg[SRSLTE_SCI_MSG_MAX_LEN] = {};
uint32_t num_decoded_tb = 0;
uint8_t tb[SRSLTE_SL_SCH_MAX_TB_LEN] = {};
int max_num_subframes = 128;
int num_subframes = 0;
int nread = 0;
uint32_t period_sf_idx = 0;
uint32_t pssch_sf_idx = 0;
uint32_t allowed_pssch_sf_idx = 0;
if (file_offset > 0) {
printf("Offsetting file by %d samples.\n", file_offset);
srslte_filesource_seek(&fsrc, file_offset * sizeof(cf_t));
@ -261,6 +273,10 @@ int main(int argc, char** argv)
if (cell.tm == SRSLTE_SIDELINK_TM1 || cell.tm == SRSLTE_SIDELINK_TM2) {
// 3GPP TS 36.213 Section 14.2.1.2 UE procedure for determining subframes
// and resource blocks for transmitting PSCCH for sidelink transmission mode 2
if (sl_comm_resource_pool.pscch_sf_bitmap[period_sf_idx] == 1) {
for (uint32_t pscch_prb_start_idx = sl_comm_resource_pool.prb_start;
pscch_prb_start_idx <= sl_comm_resource_pool.prb_end;
pscch_prb_start_idx++) {
@ -276,6 +292,7 @@ int main(int argc, char** argv)
srslte_sci_info(&sci, sci_msg, sizeof(sci_msg));
fprintf(stdout, "%s", sci_msg);
sci_decoded = true;
num_decoded_sci++;
}
}
@ -287,12 +304,45 @@ int main(int argc, char** argv)
}
}
}
}
if ((sl_comm_resource_pool.pssch_sf_bitmap[period_sf_idx] == 1) && (sci_decoded == true)) {
if (srslte_ra_sl_pssch_allowed_sf(pssch_sf_idx, sci.trp_idx, SRSLTE_SL_DUPLEX_MODE_FDD, 0)) {
// Redundancy version
uint32_t rv_idx = allowed_pssch_sf_idx % 4;
uint32_t nof_prb_pssch = 0;
uint32_t pssch_prb_start_idx = 0;
srslte_ra_sl_type0_from_riv(sci.riv, cell.nof_prb, &nof_prb_pssch, &pssch_prb_start_idx);
printf("pssch_start_prb_idx = %i nof_prb = %i\n", pssch_prb_start_idx, nof_prb_pssch);
// PSSCH Channel estimation
pssch_chest_sl_cfg.N_x_id = sci.N_sa_id;
pssch_chest_sl_cfg.sf_idx = pssch_sf_idx;
pssch_chest_sl_cfg.prb_start_idx = pssch_prb_start_idx;
pssch_chest_sl_cfg.nof_prb = nof_prb_pssch;
srslte_chest_sl_set_cfg(&pssch_chest, pssch_chest_sl_cfg);
srslte_chest_sl_ls_estimate_equalize(&pssch_chest, sf_buffer, equalized_sf_buffer);
srslte_pssch_cfg_t pssch_cfg = {
pssch_prb_start_idx, nof_prb_pssch, sci.N_sa_id, sci.mcs_idx, rv_idx, pssch_sf_idx};
if (srslte_pssch_set_cfg(&pssch, pssch_cfg) == SRSLTE_SUCCESS) {
if (srslte_pssch_decode(&pssch, equalized_sf_buffer, tb, SRSLTE_SL_SCH_MAX_TB_LEN) == SRSLTE_SUCCESS) {
srslte_vec_fprint_byte(stdout, tb, pssch.sl_sch_tb_len);
num_decoded_tb++;
printf("> Transport Block SUCCESS! TB count: %i\n", num_decoded_tb);
}
}
allowed_pssch_sf_idx++;
}
pssch_sf_idx++;
}
} else if (cell.tm == SRSLTE_SIDELINK_TM3 || cell.tm == SRSLTE_SIDELINK_TM4) {
for (int i = 0; i < sl_comm_resource_pool.num_sub_channel; i++) {
uint32_t pscch_prb_start_idx = sl_comm_resource_pool.size_sub_channel * i;
for (int sub_channel_idx = 0; sub_channel_idx < sl_comm_resource_pool.num_sub_channel; sub_channel_idx++) {
uint32_t pscch_prb_start_idx = sl_comm_resource_pool.size_sub_channel * sub_channel_idx;
for (uint32_t cyclic_shift = 0; cyclic_shift <= 9; cyclic_shift += 3) {
// PSCCH Channel estimation
pscch_chest_sl_cfg.cyclic_shift = cyclic_shift;
pscch_chest_sl_cfg.prb_start_idx = pscch_prb_start_idx;
@ -301,11 +351,50 @@ int main(int argc, char** argv)
if (srslte_pscch_decode(&pscch, equalized_sf_buffer, sci_rx, pscch_prb_start_idx) == SRSLTE_SUCCESS) {
if (srslte_sci_format1_unpack(&sci, sci_rx) == SRSLTE_SUCCESS) {
srslte_sci_info(&sci, sci_msg, sizeof(sci_msg));
fprintf(stdout, "%s", sci_msg);
num_decoded_sci++;
// Decode PSSCH
uint32_t sub_channel_start_idx = 0;
uint32_t L_subCH = 0;
srslte_ra_sl_type0_from_riv(
sci.riv, sl_comm_resource_pool.num_sub_channel, &L_subCH, &sub_channel_start_idx);
// 3GPP TS 36.213 Section 14.1.1.4C
uint32_t pssch_prb_start_idx = (sub_channel_idx * sl_comm_resource_pool.size_sub_channel) +
pscch.pscch_nof_prb + sl_comm_resource_pool.start_prb_sub_channel;
uint32_t nof_prb_pssch = ((L_subCH + sub_channel_idx) * sl_comm_resource_pool.size_sub_channel) -
pssch_prb_start_idx + sl_comm_resource_pool.start_prb_sub_channel;
uint32_t N_x_id = 0;
for (int j = 0; j < SRSLTE_SCI_CRC_LEN; j++) {
N_x_id += pscch.sci_crc[j] * exp2(SRSLTE_SCI_CRC_LEN - 1 - j);
}
uint32_t rv_idx = 0;
if (sci.retransmission == true) {
rv_idx = 1;
}
// PSSCH Channel estimation
pssch_chest_sl_cfg.N_x_id = N_x_id;
pssch_chest_sl_cfg.sf_idx = pssch_sf_idx;
pssch_chest_sl_cfg.prb_start_idx = pssch_prb_start_idx;
pssch_chest_sl_cfg.nof_prb = nof_prb_pssch;
srslte_chest_sl_set_cfg(&pssch_chest, pssch_chest_sl_cfg);
srslte_chest_sl_ls_estimate_equalize(&pssch_chest, sf_buffer, equalized_sf_buffer);
srslte_pssch_cfg_t pssch_cfg = {
pssch_prb_start_idx, nof_prb_pssch, N_x_id, sci.mcs_idx, rv_idx, pssch_sf_idx};
if (srslte_pssch_set_cfg(&pssch, pssch_cfg) == SRSLTE_SUCCESS) {
if (srslte_pssch_decode(&pssch, equalized_sf_buffer, tb, SRSLTE_SL_SCH_MAX_TB_LEN) == SRSLTE_SUCCESS) {
srslte_vec_fprint_byte(stdout, tb, pssch.sl_sch_tb_len);
num_decoded_tb++;
}
}
}
}
if (SRSLTE_VERBOSE_ISDEBUG()) {
@ -321,15 +410,17 @@ int main(int argc, char** argv)
}
}
}
pssch_sf_idx++;
}
num_subframes++;
period_sf_idx++;
} while (nread > 0 && num_subframes < max_num_subframes);
clean_exit:
base_free();
printf("num_decoded_sci=%d\n", num_decoded_sci);
printf("num_decoded_sci=%d num_decoded_tb=%d\n", num_decoded_sci, num_decoded_tb);
ret = (num_decoded_sci > 0) ? SRSLTE_SUCCESS : SRSLTE_ERROR;

@ -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;
}

@ -190,6 +190,16 @@ void srslte_vec_u8_zero(uint8_t* ptr, uint32_t nsamples)
memset(ptr, 0, sizeof(uint8_t) * nsamples);
}
void srslte_vec_i16_zero(int16_t* ptr, uint32_t nsamples)
{
memset(ptr, 0, sizeof(int16_t) * nsamples);
}
void srslte_vec_u32_zero(uint32_t* ptr, uint32_t nsamples)
{
memset(ptr, 0, sizeof(uint32_t) * nsamples);
}
void srslte_vec_cf_zero(cf_t* ptr, uint32_t nsamples)
{
memset(ptr, 0, sizeof(cf_t) * nsamples);

Loading…
Cancel
Save