sidelink: refactor channel estimation

master
Tiago Alves 5 years ago committed by Andre Puschmann
parent 425c70c8d7
commit 47145c18b7

@ -91,4 +91,4 @@ if(RF_FOUND)
else(RF_FOUND)
message(STATUS " examples will NOT BE INSTALLED.")
endif(RF_FOUND)
endif(RF_FOUND)

@ -19,15 +19,6 @@
*
*/
#include "srslte/phy/ch_estimation/chest_sl.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/dft/ofdm.h"
#include "srslte/phy/phch/pscch.h"
#include "srslte/phy/phch/sci.h"
#include "srslte/phy/rf/rf.h"
#include "srslte/phy/ue/ue_sync.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
#include <semaphore.h>
#include <signal.h>
#include <stdbool.h>
@ -37,21 +28,29 @@
#include <strings.h>
#include <unistd.h>
#include "srslte/phy/ch_estimation/chest_sl.h"
#include "srslte/phy/common/phy_common_sl.h"
#include "srslte/phy/dft/ofdm.h"
#include "srslte/phy/phch/pscch.h"
#include "srslte/phy/phch/sci.h"
#include "srslte/phy/rf/rf.h"
#include "srslte/phy/ue/ue_sync.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
uint32_t nof_ports = 1;
static bool keep_running = true;
char* output_file_name;
static char rf_devname[64] = "";
static char rf_args[64] = "auto";
float rf_gain = 40.0, rf_freq = -1.0;
int nof_rx_antennas = 1;
srslte_cell_sl_t sl_cell = {.nof_prb = 50, .tm = SRSLTE_SIDELINK_TM4, .cp = SRSLTE_CP_NORM, .N_sl_id = 168};
uint32_t size_sub_channel = 10;
uint32_t num_sub_channel = 5;
uint32_t prb_idx = 20;
bool use_standard_lte_rates = false;
bool disable_plots = false;
float rf_gain = 60.0, rf_freq = -1.0;
int nof_rx_antennas = 1;
srslte_cell_sl_t cell_sl = {.nof_prb = 50, .tm = SRSLTE_SIDELINK_TM4, .cp = SRSLTE_CP_NORM, .N_sl_id = 0};
srslte_pscch_t pscch; ///< Defined global for plotting thread
bool use_standard_lte_rates = false;
bool disable_plots = false;
srslte_pscch_t pscch; // Defined global for plotting thread
#ifdef ENABLE_GUI
#include "srsgui/srsgui.h"
@ -77,9 +76,8 @@ void usage(char* prog)
printf("\t-d RF devicename [Default %s]\n", rf_devname);
printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain);
printf("\t-A nof_rx_antennas [Default %d]\n", nof_rx_antennas);
printf("\t-c N_sl_id [Default %d]\n", sl_cell.N_sl_id);
printf("\t-p nof_prb [Default %d]\n", sl_cell.nof_prb);
printf("\t-x prb_idx [Default %i]\n", prb_idx);
printf("\t-c N_sl_id [Default %d]\n", cell_sl.N_sl_id);
printf("\t-p nof_prb [Default %d]\n", cell_sl.nof_prb);
printf("\t-r use_standard_lte_rates [Default %i]\n", use_standard_lte_rates);
#ifdef ENABLE_GUI
printf("\t-w disable plots [Default enabled]\n");
@ -97,23 +95,23 @@ void parse_args(int argc, char** argv)
rf_args[63] = '\0';
break;
case 'c':
sl_cell.N_sl_id = atoi(argv[optind]);
cell_sl.N_sl_id = (int32_t)strtol(argv[optind], NULL, 10);
break;
case 'd':
strncpy(rf_devname, argv[optind], 63);
rf_devname[63] = '\0';
break;
case 'g':
rf_gain = atof(argv[optind]);
rf_gain = strtof(argv[optind], NULL);
break;
case 'p':
sl_cell.nof_prb = atoi(argv[optind]);
cell_sl.nof_prb = (int32_t)strtol(argv[optind], NULL, 10);
break;
case 'f':
rf_freq = atof(argv[optind]);
rf_freq = strtof(argv[optind], NULL);
break;
case 'A':
nof_rx_antennas = atoi(argv[optind]);
nof_rx_antennas = (int32_t)strtol(argv[optind], NULL, 10);
break;
case 'v':
srslte_verbose++;
@ -124,9 +122,6 @@ void parse_args(int argc, char** argv)
case 'r':
use_standard_lte_rates = true;
break;
case 'x':
prb_idx = atoi(argv[optind]);
break;
default:
usage(argv[0]);
exit(-1);
@ -160,6 +155,12 @@ int main(int argc, char** argv)
srslte_use_standard_symbol_size(use_standard_lte_rates);
srslte_sl_comm_resource_pool_t sl_comm_resource_pool;
if (srslte_sl_comm_resource_pool_get_default_config(&sl_comm_resource_pool, cell_sl) != SRSLTE_SUCCESS) {
ERROR("Error initializing sl_comm_resource_pool\n");
return SRSLTE_ERROR;
}
printf("Opening RF device...\n");
srslte_rf_t rf;
if (srslte_rf_open_multi(&rf, rf_args, nof_rx_antennas)) {
@ -169,7 +170,7 @@ int main(int argc, char** argv)
printf("Set RX freq: %.6f MHz\n", srslte_rf_set_rx_freq(&rf, nof_rx_antennas, rf_freq) / 1000000);
printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_gain));
int srate = srslte_sampling_freq_hz(sl_cell.nof_prb);
int srate = srslte_sampling_freq_hz(cell_sl.nof_prb);
if (srate != -1) {
printf("Setting sampling rate %.2f MHz\n", (float)srate / 1000000);
@ -179,12 +180,12 @@ int main(int argc, char** argv)
exit(-1);
}
} else {
ERROR("Invalid number of PRB %d\n", sl_cell.nof_prb);
ERROR("Invalid number of PRB %d\n", cell_sl.nof_prb);
exit(-1);
}
// allocate Rx buffers for 1ms worth of samples
uint32_t sf_len = SRSLTE_SF_LEN_PRB(sl_cell.nof_prb);
uint32_t sf_len = SRSLTE_SF_LEN_PRB(cell_sl.nof_prb);
printf("Using a SF len of %d samples\n", sf_len);
cf_t* rx_buffer[SRSLTE_MAX_PORTS] = {NULL}; //< For radio to receive samples
@ -203,21 +204,23 @@ int main(int argc, char** argv)
}
}
uint32_t sf_n_re = SRSLTE_CP_NSYMB(SRSLTE_CP_NORM) * SRSLTE_NRE * 2 * sl_cell.nof_prb;
cf_t* equalized_sf_buffer = srslte_vec_cf_malloc(sf_n_re);
uint32_t sf_n_re = SRSLTE_CP_NSYMB(SRSLTE_CP_NORM) * SRSLTE_NRE * 2 * cell_sl.nof_prb;
cf_t* equalized_sf_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_re);
// RX
srslte_ofdm_t fft;
if (srslte_ofdm_rx_init(&fft, sl_cell.cp, rx_buffer[0], sf_buffer[0], sl_cell.nof_prb)) {
if (srslte_ofdm_rx_init(&fft, cell_sl.cp, rx_buffer[0], sf_buffer[0], cell_sl.nof_prb)) {
fprintf(stderr, "Error creating FFT object\n");
return SRSLTE_ERROR;
}
srslte_ofdm_set_normalize(&fft, true);
srslte_ofdm_set_freq_shift(&fft, -0.5);
// PSCCH Channel estimation
srslte_chest_sl_t pscch_chest;
srslte_chest_sl_init_pscch_dmrs(&pscch_chest);
// SCI
srslte_sci_t sci;
srslte_sci_init(&sci, cell_sl, sl_comm_resource_pool);
uint8_t sci_rx[SRSLTE_SCI_MAX_LEN] = {};
char sci_msg[SRSLTE_SCI_MSG_MAX_LEN] = {};
// init PSCCH object
if (srslte_pscch_init(&pscch, SRSLTE_MAX_PRB) != SRSLTE_SUCCESS) {
@ -225,13 +228,18 @@ int main(int argc, char** argv)
return SRSLTE_ERROR;
}
if (srslte_pscch_set_cell(&pscch, sl_cell) != SRSLTE_SUCCESS) {
if (srslte_pscch_set_cell(&pscch, cell_sl) != SRSLTE_SUCCESS) {
ERROR("Error in PSCCH set cell\n");
return SRSLTE_ERROR;
}
srslte_sci_t sci;
srslte_sci_init(&sci, sl_cell.nof_prb, sl_cell.tm, size_sub_channel, num_sub_channel);
// PSCCH Channel estimation
srslte_chest_sl_cfg_t pscch_chest_sl_cfg;
srslte_chest_sl_t pscch_chest;
if (srslte_chest_sl_init(&pscch_chest, SRSLTE_SIDELINK_PSCCH, cell_sl, sl_comm_resource_pool) != SRSLTE_SUCCESS) {
ERROR("Error in chest PSCCH init\n");
return SRSLTE_ERROR;
}
srslte_ue_sync_t sync;
if (srslte_ue_sync_init_multi_decim_mode(
@ -241,7 +249,7 @@ int main(int argc, char** argv)
}
srslte_cell_t cell = {};
cell.nof_prb = sl_cell.nof_prb;
cell.nof_prb = cell_sl.nof_prb;
if (srslte_ue_sync_set_cell(&sync, cell)) {
ERROR("Error initiating ue_sync\n");
exit(-1);
@ -262,6 +270,9 @@ int main(int argc, char** argv)
uint32_t num_decoded_sci = 0;
uint32_t subframe_count = 0;
uint32_t pscch_prb_start_idx = 0;
while (keep_running) {
// receive subframe
int ret = srslte_ue_sync_zerocopy(&sync, rx_buffer, sf_len);
@ -283,41 +294,40 @@ int main(int argc, char** argv)
// do FFT
srslte_ofdm_rx_sf(&fft);
for (int i = 0; i < num_sub_channel; i++) {
uint32_t pscch_prb_idx = size_sub_channel * i;
for (int sub_channel_idx = 0; sub_channel_idx < sl_comm_resource_pool.num_sub_channel; sub_channel_idx++) {
pscch_prb_start_idx = sub_channel_idx * sl_comm_resource_pool.size_sub_channel;
for (uint32_t cyclic_shift = 0; cyclic_shift <= 9; cyclic_shift += 3) {
uint8_t sci_rx[SRSLTE_SCI_MAX_LEN] = {};
char sci_msg[SRSLTE_SCI_MSG_MAX_LEN] = {};
// PSCCH Channel estimation
srslte_chest_sl_gen_pscch_dmrs(&pscch_chest, cyclic_shift, sl_cell.tm);
srslte_chest_sl_pscch_ls_estimate_equalize(
&pscch_chest, sf_buffer[0], pscch_prb_idx, equalized_sf_buffer, sl_cell.nof_prb, sl_cell.tm, sl_cell.cp);
if (srslte_pscch_decode(&pscch, equalized_sf_buffer, sci_rx, pscch_prb_idx) == SRSLTE_SUCCESS) {
if (srslte_sci_format1_unpack(&sci, sci_rx) != SRSLTE_SUCCESS) {
printf("Error unpacking sci format 1\n");
return SRSLTE_ERROR;
}
pscch_chest_sl_cfg.cyclic_shift = cyclic_shift;
pscch_chest_sl_cfg.prb_start_idx = pscch_prb_start_idx;
srslte_chest_sl_set_cfg(&pscch_chest, pscch_chest_sl_cfg);
srslte_chest_sl_ls_estimate_equalize(&pscch_chest, sf_buffer[0], equalized_sf_buffer);
srslte_sci_info(sci_msg, &sci);
fprintf(stdout, "%s", sci_msg);
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++;
num_decoded_sci++;
// plot PSCCH
// plot PSCCH
#ifdef ENABLE_GUI
if (!disable_plots) {
sem_post(&plot_sem);
}
if (!disable_plots) {
sem_post(&plot_sem);
}
#endif
}
}
if (SRSLTE_VERBOSE_ISDEBUG()) {
char filename[64];
snprintf(
filename, 64, "pscch_rx_syms_sf%d_shift%d_prbidx%d.bin", subframe_count, cyclic_shift, pscch_prb_idx);
snprintf(filename,
64,
"pscch_rx_syms_sf%d_shift%d_prbidx%d.bin",
subframe_count,
cyclic_shift,
pscch_prb_start_idx);
printf("Saving PSCCH symbols (%d) to %s\n", pscch.E / SRSLTE_PSCCH_QM, filename);
srslte_vec_save_file(filename, pscch.mod_symbols, pscch.E / SRSLTE_PSCCH_QM * sizeof(cf_t));
}

@ -24,23 +24,33 @@
#include <stdio.h>
#include "srslte/config.h"
#include "srslte/phy/ch_estimation/chest_common.h"
#include "srslte/phy/ch_estimation/refsignal_ul.h"
#include "srslte/phy/common/phy_common_sl.h"
#include "srslte/phy/resampling/interp.h"
#define SRSLTE_SL_N_RU_SEQ (30)
#define SRSLTE_SL_MAX_DMRS_SYMB (4)
#define SRSLTE_SL_DEFAULT_NOF_DMRS_CYCLIC_SHIFTS (1)
#define SRSLTE_SL_MAX_PSCCH_NOF_DMRS_CYCLIC_SHIFTS (4)
// Base Sequence Number - always 0 for sidelink: 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 5.5.1.4
#define SRSLTE_SL_BASE_SEQUENCE_NUMBER 0
#define SRSLTE_SL_MAX_DMRS_PERIOD_LENGTH 320
typedef struct {
typedef struct SRSLTE_API {
uint32_t prb_start_idx; // PRB start idx to map RE from RIV
uint32_t nof_prb; // PSSCH nof_prb, Length of continuous PRB to map RE (in the pool) from RIV
uint32_t N_x_id;
uint32_t sf_idx; // PSSCH sf_idx
uint32_t cyclic_shift;
} srslte_chest_sl_cfg_t;
typedef struct SRSLTE_API {
srslte_sl_channels_t channel;
srslte_cell_sl_t cell;
srslte_sl_comm_resource_pool_t sl_comm_resource_pool;
srslte_chest_sl_cfg_t chest_sl_cfg;
float sync_err;
float rsrp_corr;
uint32_t sf_n_re;
uint32_t M_sc_rs;
@ -56,17 +66,7 @@ typedef struct {
float alpha[SRSLTE_SL_MAX_DMRS_SYMB];
// Group Hopping Flag
uint32_t f_gh;
uint32_t* f_gh_pattern;
uint32_t f_ss;
// Sequence Group Number
uint32_t u[SRSLTE_SL_MAX_DMRS_SYMB];
// Base Sequence Number - always 0 for sidelink
uint32_t v;
int32_t N_zc;
int32_t q[SRSLTE_SL_MAX_DMRS_SYMB];
@ -74,79 +74,48 @@ typedef struct {
cf_t* r_uv[SRSLTE_SL_MAX_DMRS_SYMB];
cf_t* r_sequence[SRSLTE_SL_MAX_DMRS_SYMB];
cf_t* r_sequence[SRSLTE_SL_MAX_DMRS_SYMB][SRSLTE_SL_MAX_PSCCH_NOF_DMRS_CYCLIC_SHIFTS];
cf_t* r_sequence_rx[SRSLTE_SL_MAX_DMRS_SYMB];
cf_t* dmrs_received[SRSLTE_SL_MAX_DMRS_SYMB];
cf_t* pilot_estimates_1;
cf_t* pilot_estimates_2;
cf_t* ce;
cf_t* ce_average;
cf_t* noise_tmp;
float noise_estimated;
srslte_interp_linsrslte_vec_t lin_vec_sl;
bool sync_error_enable;
bool rsrp_enable;
bool sync_error_enable;
bool rsrp_enable;
float sync_err;
float rsrp_corr;
} srslte_chest_sl_t;
SRSLTE_API int srslte_chest_sl_gen_dmrs(srslte_chest_sl_t* q,
srslte_sl_tm_t tm,
srslte_sl_channels_t ch,
uint32_t sf_idx,
uint32_t N_sl_id,
uint32_t L_crb,
uint32_t N_x_id,
uint32_t cyclic_shift);
SRSLTE_API int srslte_chest_sl_init_psbch_dmrs(srslte_chest_sl_t* q);
SRSLTE_API int srslte_chest_sl_gen_psbch_dmrs(srslte_chest_sl_t* q, srslte_sl_tm_t txMode, uint32_t N_sl_id);
SRSLTE_API int srslte_chest_sl_put_psbch_dmrs(srslte_chest_sl_t* q,
cf_t* sf_buffer,
srslte_sl_tm_t tx_mode,
uint32_t nof_prb,
srslte_cp_t cp);
SRSLTE_API void srslte_chest_sl_psbch_ls_estimate_equalize(srslte_chest_sl_t* q,
cf_t* sf_buffer,
cf_t* sf_buffer_rx,
uint32_t nof_prb,
srslte_sl_tm_t txMode,
srslte_cp_t cp);
SRSLTE_API int srslte_chest_sl_get_psbch_dmrs(srslte_chest_sl_t* q,
cf_t* sf_buffer_rx,
cf_t** dmrs_received,
srslte_sl_tm_t tx_mode,
uint32_t nof_prb,
srslte_cp_t cp);
SRSLTE_API int srslte_chest_sl_init_pscch_dmrs(srslte_chest_sl_t* q);
SRSLTE_API int srslte_chest_sl_gen_pscch_dmrs(srslte_chest_sl_t* q, uint32_t cyclic_shift, srslte_sl_tm_t tm);
SRSLTE_API int srslte_chest_sl_put_pscch_dmrs(srslte_chest_sl_t* q,
cf_t* sf_buffer,
uint32_t prb_idx,
srslte_sl_tm_t tm,
uint32_t nof_prb,
srslte_cp_t cp);
SRSLTE_API void srslte_chest_sl_pscch_ls_estimate_equalize(srslte_chest_sl_t* q,
cf_t* sf_buffer,
uint32_t prb_idx,
cf_t* sf_buffer_rx,
uint32_t nof_prb,
srslte_sl_tm_t tm,
srslte_cp_t cp);
SRSLTE_API int srslte_chest_sl_get_pscch_dmrs(srslte_chest_sl_t* q,
cf_t* sf_buffer_rx,
uint32_t prb_idx,
cf_t** dmrs_received,
srslte_sl_tm_t tm,
uint32_t nof_prb,
srslte_cp_t cp);
SRSLTE_API int srslte_chest_sl_init(srslte_chest_sl_t* q,
srslte_sl_channels_t channel,
srslte_cell_sl_t cell,
srslte_sl_comm_resource_pool_t sl_comm_resource_pool);
SRSLTE_API int srslte_chest_sl_set_cell(srslte_chest_sl_t* q, srslte_cell_sl_t cell);
SRSLTE_API int srslte_chest_sl_set_cfg(srslte_chest_sl_t* q, srslte_chest_sl_cfg_t chest_sl_cfg);
SRSLTE_API float srslte_chest_sl_get_sync_error(srslte_chest_sl_t* q);
SRSLTE_API float srslte_chest_sl_estimate_noise(srslte_chest_sl_t* q);
SRSLTE_API float srslte_chest_sl_get_rsrp(srslte_chest_sl_t* q);
SRSLTE_API int srslte_chest_sl_put_dmrs(srslte_chest_sl_t* q, cf_t* sf_buffer);
SRSLTE_API int srslte_chest_sl_get_dmrs(srslte_chest_sl_t* q, cf_t* sf_buffer, cf_t** dmrs_received);
SRSLTE_API void srslte_chest_sl_ls_estimate(srslte_chest_sl_t* q, cf_t* sf_buffer);
SRSLTE_API void srslte_chest_sl_ls_equalize(srslte_chest_sl_t* q, cf_t* sf_buffer, cf_t* equalized_sf_buffer);
SRSLTE_API void srslte_chest_sl_ls_estimate_equalize(srslte_chest_sl_t* q, cf_t* sf_buffer, cf_t* equalized_sf_buffer);
SRSLTE_API void srslte_chest_sl_free(srslte_chest_sl_t* q);

@ -35,6 +35,8 @@
#include "srslte/phy/phch/pucch_cfg.h"
#include "srslte/phy/phch/pusch_cfg.h"
#include "srslte/phy/ch_estimation/ul_rs_tables.h"
#define SRSLTE_NOF_GROUPS_U 30
#define SRSLTE_NOF_SEQUENCES_U 2
#define SRSLTE_NOF_DELTA_SS 30
@ -191,4 +193,6 @@ SRSLTE_API uint32_t srslte_refsignal_srs_rb_L_cs(uint32_t bw_cfg, uint32_t nof_p
SRSLTE_API uint32_t srslte_refsignal_srs_M_sc(srslte_refsignal_ul_t* q, srslte_refsignal_srs_cfg_t* cfg);
SRSLTE_API uint32_t srslte_refsignal_get_q(uint32_t u, uint32_t v, uint32_t N_sz);
#endif // SRSLTE_REFSIGNAL_UL_H

@ -19,10 +19,13 @@
*
*/
#ifndef SRSLTE_UL_RS_TABLES_H
#define SRSLTE_UL_RS_TABLES_H
#include <stdint.h>
// Phi values for M_sc=12 Table 5.5.1.2-1 in 36.211
int phi_M_sc_12[30][12] = {{-1, 1, 3, -3, 3, 3, 1, 1, 3, 1, -3, 3}, {1, 1, 3, 3, 3, -1, 1, -3, -3, 1, -3, 3},
static const int phi_M_sc_12[30][12] = {{-1, 1, 3, -3, 3, 3, 1, 1, 3, 1, -3, 3}, {1, 1, 3, 3, 3, -1, 1, -3, -3, 1, -3, 3},
{1, 1, -3, -3, -3, -1, -3, -3, 1, -3, 1, -1}, {-1, 1, 1, 1, 1, -1, -3, -3, 1, -3, 3, -1},
{-1, 3, 1, -1, 1, -1, -3, -1, 1, -1, 1, 3}, {1, -3, 3, -1, -1, 1, 1, -1, -1, 3, -3, 1},
{-1, 3, -3, -3, -3, 3, 1, -1, 3, 3, -3, 1}, {-3, -1, -1, -1, 1, -3, 3, -1, 1, -3, 3, 1},
@ -39,7 +42,7 @@ int phi_M_sc_12[30][12] = {{-1, 1, 3, -3, 3, 3, 1, 1, 3, 1, -3, 3}, {1, 1,
{-1, 3, -3, 3, -1, 3, 3, -3, 3, 3, -1, -1}, {3, -3, -3, -1, -1, -3, -1, 3, -3, 3, 1, -1}};
// Phi values for M_sc=24 Table 5.5.1.2-2 in 36.211
int phi_M_sc_24[30][24] = {{-1, 3, 1, -3, 3, -1, 1, 3, -3, 3, 1, 3, -3, 3, 1, 1, -1, 1, 3, -3, 3, -3, -1, -3},
static const int phi_M_sc_24[30][24] = {{-1, 3, 1, -3, 3, -1, 1, 3, -3, 3, 1, 3, -3, 3, 1, 1, -1, 1, 3, -3, 3, -3, -1, -3},
{-3, 3, -3, -3, -3, 1, -3, -3, 3, -1, 1, 1, 1, 3, 1, -1, 3, -3, -3, 1, 3, 1, 1, -3},
{3, -1, 3, 3, 1, 1, -3, 3, 3, 3, 3, 1, -1, 3, -1, 1, 1, -1, -3, -1, -1, 1, 3, 3},
{-1, -3, 1, 1, 3, -3, 1, 1, -3, -1, -1, 1, 3, 1, 3, 1, -1, 3, 1, 1, -3, -1, -3, -1},
@ -72,7 +75,7 @@ int phi_M_sc_24[30][24] = {{-1, 3, 1, -3, 3, -1, 1, 3, -3, 3, 1, 3, -3, 3, 1, 1,
// Prime numbers used for Section 5.5.1.1 of 36.211
#define NOF_PRIME_NUMBERS 196
uint32_t prime_numbers[NOF_PRIME_NUMBERS] = {
static const uint32_t prime_numbers[NOF_PRIME_NUMBERS] = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251,
@ -84,3 +87,5 @@ uint32_t prime_numbers[NOF_PRIME_NUMBERS] = {
829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953,
967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193};
#endif

@ -30,7 +30,11 @@
#ifndef SRSLTE_PHY_COMMON_SL_H
#define SRSLTE_PHY_COMMON_SL_H
#include "phy_common.h"
/**
* \brief Common parameters and lookup functions for Sidelink PHY
*/
#include "srslte/phy/common/phy_common.h"
typedef enum SRSLTE_API {
SRSLTE_SIDELINK_TM1 = 0,
@ -53,6 +57,20 @@ typedef struct SRSLTE_API {
srslte_cp_t cp;
} srslte_cell_sl_t;
// SL-CommResourcePool: 3GPP TS 36.331 version 15.6.0 Release 15 Section 6.3.8
typedef struct SRSLTE_API {
uint32_t period_length;
uint32_t prb_num;
uint32_t prb_start;
uint32_t prb_end;
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
} srslte_sl_comm_resource_pool_t;
typedef enum SRSLTE_API {
SRSLTE_SIDELINK_DATA_SYMBOL = 0,
SRSLTE_SIDELINK_SYNC_SYMBOL,
@ -60,6 +78,9 @@ typedef enum SRSLTE_API {
SRSLTE_SIDELINK_GUARD_SYMBOL
} srslte_sl_symbol_t;
#define SRSLTE_SL_DUPLEX_MODE_FDD (1)
#define SRSLTE_SL_DUPLEX_MODE_TDD (2)
#define SRSLTE_PSBCH_NOF_PRB (6)
#define SRSLTE_PSCCH_TM34_NOF_PRB (2)
@ -78,6 +99,10 @@ typedef enum SRSLTE_API {
#define SRSLTE_PSBCH_TM34_NUM_DMRS_SYMBOLS (3) ///< PSBCH has 3 DMRS symbols in TM3 and TM4
#define SRSLTE_PSBCH_TM34_NUM_SYNC_SYMBOLS (4) ///< Two symbols PSSS and two SSSS
#define SRSLTE_SCI_CRC_LEN (16)
#define SRSLTE_SCI_MAX_LEN (45)
#define SRSLTE_SCI_TM34_LEN (32)
#define SRSLTE_PSCCH_QM 2
#define SRSLTE_PSCCH_TM12_NOF_PRB (1)
#define SRSLTE_PSCCH_TM34_NOF_PRB (2)
@ -93,14 +118,32 @@ typedef enum SRSLTE_API {
#define SRSLTE_PSCCH_TM34_NUM_DATA_SYMBOLS (10)
#define SRSLTE_PSCCH_TM34_NUM_DMRS_SYMBOLS (4)
#define SRSLTE_PSCCH_MAX_NUM_DATA_SYMBOLS (SRSLTE_PSCCH_TM12_NUM_DATA_SYMBOLS)
#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_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
SRSLTE_API int srslte_sl_get_num_symbols(srslte_sl_tm_t tm, srslte_cp_t cp);
#define SRSLTE_PSSCH_TM12_NUM_DATA_SYMBOLS_CP_EXT \
(10) // PSSCH is in 10 OFDM symbols for extended cyclic prefix (but only 9 are tx'ed)
#define SRSLTE_PSSCH_TM12_NUM_DMRS_SYMBOLS_CP_EXT \
(2) // PSSCH has 2 DMRS symbols for extended cyclic prefix in TM1 and TM2
SRSLTE_API bool srslte_psbch_is_symbol(srslte_sl_symbol_t type, srslte_sl_tm_t tm, uint32_t i);
#define SRSLTE_PSSCH_TM34_NUM_DATA_SYMBOLS (10) // PSSCH is in 10 OFDM symbols (but only 9 are tx'ed)
#define SRSLTE_PSSCH_TM34_NUM_DMRS_SYMBOLS (4) // PSSCH has 4 DMRS symbols in TM3 and TM4
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 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);
SRSLTE_API bool srslte_pssch_is_symbol(srslte_sl_symbol_t type, srslte_sl_tm_t tm, uint32_t i, srslte_cp_t cp);
SRSLTE_API uint32_t srslte_sci_format0_sizeof(uint32_t nof_prb);
#endif // SRSLTE_PHY_COMMON_SL_H
SRSLTE_API int srslte_sl_comm_resource_pool_get_default_config(srslte_sl_comm_resource_pool_t* q,
srslte_cell_sl_t cell);
#endif // SRSLTE_PHY_COMMON_SL_H

@ -90,10 +90,10 @@ typedef struct SRSLTE_API {
SRSLTE_API int srslte_pscch_init(srslte_pscch_t* q, uint32_t max_prb);
SRSLTE_API int srslte_pscch_set_cell(srslte_pscch_t* q, srslte_cell_sl_t cell);
SRSLTE_API int srslte_pscch_encode(srslte_pscch_t* q, uint8_t* sci, cf_t* sf_buffer, uint32_t prb_idx);
SRSLTE_API int srslte_pscch_decode(srslte_pscch_t* q, cf_t* equalized_sf_syms, uint8_t* sci, uint32_t prb_idx);
SRSLTE_API int srslte_pscch_put(srslte_pscch_t* q, cf_t* sf_buffer, uint32_t prb_idx);
SRSLTE_API int srslte_pscch_get(srslte_pscch_t* q, cf_t* sf_buffer, uint32_t prb_idx);
SRSLTE_API int srslte_pscch_encode(srslte_pscch_t* q, uint8_t* sci, cf_t* sf_buffer, uint32_t prb_start_idx);
SRSLTE_API int srslte_pscch_decode(srslte_pscch_t* q, cf_t* equalized_sf_syms, uint8_t* sci, uint32_t prb_start_idx);
SRSLTE_API int srslte_pscch_put(srslte_pscch_t* q, cf_t* sf_buffer, uint32_t prb_start_idx);
SRSLTE_API int srslte_pscch_get(srslte_pscch_t* q, cf_t* sf_buffer, uint32_t prb_start_idx);
SRSLTE_API void srslte_pscch_free(srslte_pscch_t* q);
#endif // SRSLTE_PSCCH_H

@ -94,16 +94,13 @@ typedef struct SRSLTE_API {
} srslte_sci_t;
SRSLTE_API int srslte_sci_init(srslte_sci_t* q,
uint32_t nof_prb,
srslte_sl_tm_t tm,
uint32_t size_sub_channel,
uint32_t num_sub_channel);
SRSLTE_API int
srslte_sci_init(srslte_sci_t* q, srslte_cell_sl_t cell, srslte_sl_comm_resource_pool_t sl_comm_resource_pool);
SRSLTE_API int srslte_sci_format0_pack(srslte_sci_t* q, uint8_t* output);
SRSLTE_API int srslte_sci_format1_pack(srslte_sci_t* q, uint8_t* output);
SRSLTE_API int srslte_sci_format0_unpack(srslte_sci_t* q, uint8_t* input);
SRSLTE_API int srslte_sci_format1_unpack(srslte_sci_t* q, uint8_t* input);
SRSLTE_API void srslte_sci_info(char* str, srslte_sci_t* q);
SRSLTE_API void srslte_sci_info(const srslte_sci_t* sci, char* str, uint32_t len);
SRSLTE_API void srslte_sci_free(srslte_sci_t* q);
#endif // SRSLTE_SCI_H

File diff suppressed because it is too large Load Diff

@ -33,7 +33,6 @@
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
#include "ul_rs_tables.h"
// n_dmrs_2 table 5.5.2.1.1-1 from 36.211
uint32_t n_dmrs_2[8] = {0, 6, 3, 4, 2, 8, 10, 9};
@ -233,7 +232,7 @@ static void arg_r_uv_2prb(float* arg, uint32_t u)
}
}
static uint32_t get_q(uint32_t u, uint32_t v, uint32_t N_sz)
uint32_t srslte_refsignal_get_q(uint32_t u, uint32_t v, uint32_t N_sz)
{
float q;
float q_hat;
@ -253,7 +252,7 @@ static void arg_r_uv_mprb(float* arg, uint32_t M_sc, uint32_t u, uint32_t v)
uint32_t N_sz = largest_prime_lower_than(M_sc);
if (N_sz > 0) {
float q = get_q(u, v, N_sz);
float q = srslte_refsignal_get_q(u, v, N_sz);
float n_sz = (float)N_sz;
for (uint32_t i = 0; i < M_sc; i++) {
float m = (float)(i % N_sz);

@ -19,31 +19,26 @@
*
*/
#include "srslte/phy/common/phy_common.h"
#include <srslte/phy/ch_estimation/chest_sl.h>
#include <srslte/phy/utils/debug.h>
#include <srslte/phy/utils/vector.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
uint32_t nof_prb = 25;
uint32_t N_sl_id = 1;
srslte_cp_t cp = SRSLTE_CP_NORM;
srslte_sl_tm_t tm = SRSLTE_SIDELINK_TM4;
bool run_psbch_test = true;
#include "srslte/phy/ch_estimation/chest_sl.h"
#include "srslte/phy/common/phy_common_sl.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
srslte_cell_sl_t cell = {.nof_prb = 6, .N_sl_id = 168, .tm = SRSLTE_SIDELINK_TM2, .cp = SRSLTE_CP_NORM};
bool run_psbch_test = true;
void usage(char* prog)
{
printf("Usage: %s [recov]\n", prog);
printf("\t-p nof_prb [Default %d]\n", nof_prb);
printf("\t-p nof_prb [Default %d]\n", cell.nof_prb);
printf("\t-e extended cyclic prefix [Default normal]\n");
printf("\t-c N_sl_id [Default %d]\n", N_sl_id);
printf("\t-t Sidelink transmission mode {1,2,3,4} [Default %d]\n", (tm + 1));
printf("\t-c N_sl_id [Default %d]\n", cell.N_sl_id);
printf("\t-t Sidelink transmission mode {1,2,3,4} [Default %d]\n", (cell.tm + 1));
printf("\t-v increase verbosity\n");
}
@ -53,27 +48,27 @@ void parse_args(int argc, char** argv)
while ((opt = getopt(argc, argv, "pecotv")) != -1) {
switch (opt) {
case 'p':
nof_prb = (uint32_t)strtol(argv[optind], NULL, 10);
cell.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10);
break;
case 'e':
cp = SRSLTE_CP_EXT;
cell.cp = SRSLTE_CP_EXT;
break;
case 'c':
N_sl_id = (uint32_t)strtol(argv[optind], NULL, 10);
cell.N_sl_id = (uint32_t)strtol(argv[optind], NULL, 10);
break;
case 't':
switch (strtol(argv[optind], NULL, 10)) {
case 1:
tm = SRSLTE_SIDELINK_TM1;
cell.tm = SRSLTE_SIDELINK_TM1;
break;
case 2:
tm = SRSLTE_SIDELINK_TM2;
cell.tm = SRSLTE_SIDELINK_TM2;
break;
case 3:
tm = SRSLTE_SIDELINK_TM3;
cell.tm = SRSLTE_SIDELINK_TM3;
break;
case 4:
tm = SRSLTE_SIDELINK_TM4;
cell.tm = SRSLTE_SIDELINK_TM4;
break;
default:
usage(argv[0]);
@ -88,37 +83,44 @@ void parse_args(int argc, char** argv)
exit(-1);
}
}
if (cell.cp == SRSLTE_CP_EXT && cell.tm >= SRSLTE_SIDELINK_TM3) {
ERROR("Selected TM does not support extended CP");
usage(argv[0]);
exit(-1);
}
}
int main(int argc, char** argv)
{
parse_args(argc, argv);
int sf_n_re = SRSLTE_CP_NSYMB(cp) * SRSLTE_NRE * nof_prb * 2;
int sf_n_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
cf_t* sf_buffer = srslte_vec_cf_malloc(sf_n_re);
srslte_vec_cf_zero(sf_buffer, sf_n_re);
bzero(sf_buffer, sizeof(cf_t) * sf_n_re);
// Variables init Rx
cf_t* sf_buffer_rx = srslte_vec_cf_malloc(sf_n_re);
srslte_vec_cf_zero(sf_buffer_rx, sf_n_re);
cf_t* equalized_sf_buffer = srslte_vec_cf_malloc(sf_n_re);
bzero(equalized_sf_buffer, sizeof(cf_t) * sf_n_re);
cf_t* dmrs_received[SRSLTE_SL_MAX_DMRS_SYMB] = {NULL};
for (int i = 0; i < SRSLTE_SL_MAX_DMRS_SYMB; i++) {
dmrs_received[i] = srslte_vec_cf_malloc(SRSLTE_NRE * nof_prb);
dmrs_received[i] = srslte_vec_cf_malloc(SRSLTE_NRE * cell.nof_prb);
}
srslte_sl_comm_resource_pool_t sl_comm_resource_pool = {};
// Variables init Tx
srslte_chest_sl_t q = {};
if (run_psbch_test) {
// Tx
srslte_chest_sl_init_psbch_dmrs(&q);
srslte_chest_sl_gen_psbch_dmrs(&q, tm, N_sl_id);
srslte_chest_sl_put_psbch_dmrs(&q, sf_buffer, tm, nof_prb, cp);
srslte_chest_sl_init(&q, SRSLTE_SIDELINK_PSBCH, cell, sl_comm_resource_pool);
srslte_chest_sl_put_dmrs(&q, sf_buffer);
// Rx
srslte_chest_sl_psbch_ls_estimate_equalize(&q, sf_buffer, sf_buffer_rx, nof_prb, tm, cp);
srslte_chest_sl_get_psbch_dmrs(&q, sf_buffer_rx, dmrs_received, tm, nof_prb, cp);
srslte_chest_sl_ls_estimate_equalize(&q, sf_buffer, equalized_sf_buffer);
srslte_chest_sl_get_dmrs(&q, equalized_sf_buffer, dmrs_received);
// Test
// TODO: add proper test
@ -139,11 +141,9 @@ int main(int argc, char** argv)
if (sf_buffer) {
free(sf_buffer);
}
if (sf_buffer_rx) {
free(sf_buffer_rx);
if (equalized_sf_buffer) {
free(equalized_sf_buffer);
}
for (int i = 0; i < SRSLTE_SL_MAX_DMRS_SYMB; i++) {
if (dmrs_received[i]) {
free(dmrs_received[i]);

@ -19,9 +19,32 @@
*
*/
#include <string.h>
#include "srslte/phy/common/phy_common_sl.h"
#include "srslte/phy/common/sequence.h"
#include "srslte/phy/utils/debug.h"
int srslte_sl_group_hopping_f_gh(uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME * 2], uint32_t N_x_id)
{
srslte_sequence_t seq;
bzero(&seq, sizeof(srslte_sequence_t));
if (srslte_sequence_LTE_pr(&seq, 160 * 2, N_x_id / 30)) {
return SRSLTE_ERROR;
}
for (uint32_t ns = 0; ns < SRSLTE_NSLOTS_X_FRAME * 2; ns++) {
f_gh[ns] = 0;
for (int i = 0; i < 8; i++) {
f_gh[ns] += (((uint32_t)seq.c[8 * ns + i]) << i);
}
}
srslte_sequence_free(&seq);
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) {
@ -34,16 +57,16 @@ int srslte_sl_get_num_symbols(srslte_sl_tm_t tm, srslte_cp_t cp)
if (cp == SRSLTE_CP_NORM) {
return SRSLTE_CP_NORM_SF_NSYMB;
} else {
ERROR("Invalid CP");
printf("Invalid CP\n");
return SRSLTE_ERROR;
}
} else {
ERROR("Invalid TM");
printf("Invalid TM\n");
return SRSLTE_ERROR;
}
}
///< Look-up tables for Sidelink channel symbols
// Look-up tables for Sidelink channel symbols
static const srslte_sl_symbol_t srslte_psbch_symbol_map_tm12[SRSLTE_CP_NORM_SF_NSYMB] = {SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_SYNC_SYMBOL,
SRSLTE_SIDELINK_SYNC_SYMBOL,
@ -59,6 +82,20 @@ static const srslte_sl_symbol_t srslte_psbch_symbol_map_tm12[SRSLTE_CP_NORM_SF_N
SRSLTE_SIDELINK_SYNC_SYMBOL,
SRSLTE_SIDELINK_GUARD_SYMBOL};
static const srslte_sl_symbol_t srslte_psbch_symbol_map_tm12_ext[SRSLTE_CP_EXT_SF_NSYMB] = {
SRSLTE_SIDELINK_SYNC_SYMBOL,
SRSLTE_SIDELINK_SYNC_SYMBOL,
SRSLTE_SIDELINK_DMRS_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DMRS_SYMBOL,
SRSLTE_SIDELINK_SYNC_SYMBOL,
SRSLTE_SIDELINK_SYNC_SYMBOL,
SRSLTE_SIDELINK_GUARD_SYMBOL};
static const srslte_sl_symbol_t srslte_psbch_symbol_map_tm34[SRSLTE_CP_NORM_SF_NSYMB] = {SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_SYNC_SYMBOL,
SRSLTE_SIDELINK_SYNC_SYMBOL,
@ -74,13 +111,17 @@ static const srslte_sl_symbol_t srslte_psbch_symbol_map_tm34[SRSLTE_CP_NORM_SF_N
SRSLTE_SIDELINK_SYNC_SYMBOL,
SRSLTE_SIDELINK_GUARD_SYMBOL};
bool srslte_psbch_is_symbol(srslte_sl_symbol_t type, srslte_sl_tm_t tm, uint32_t i)
bool srslte_psbch_is_symbol(srslte_sl_symbol_t type, srslte_sl_tm_t tm, uint32_t i, srslte_cp_t cp)
{
if (tm <= SRSLTE_SIDELINK_TM2) {
if (tm == SRSLTE_SIDELINK_TM1 || tm == SRSLTE_SIDELINK_TM2) {
if (cp == SRSLTE_CP_EXT) {
return srslte_psbch_symbol_map_tm12_ext[i] == type;
}
return srslte_psbch_symbol_map_tm12[i] == type;
} else {
} else if (tm == SRSLTE_SIDELINK_TM3 || tm == SRSLTE_SIDELINK_TM4) {
return srslte_psbch_symbol_map_tm34[i] == type;
}
return false;
}
static const srslte_sl_symbol_t srslte_pscch_symbol_map_tm12[SRSLTE_CP_NORM_SF_NSYMB] = {SRSLTE_SIDELINK_DATA_SYMBOL,
@ -139,3 +180,134 @@ bool srslte_pscch_is_symbol(srslte_sl_symbol_t type, srslte_sl_tm_t tm, uint32_t
}
return false;
}
static const srslte_sl_symbol_t srslte_pssch_symbol_map_tm12[SRSLTE_CP_NORM_SF_NSYMB] = {SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DMRS_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DMRS_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_GUARD_SYMBOL};
static const srslte_sl_symbol_t srslte_pssch_symbol_map_tm12_ext[SRSLTE_CP_EXT_SF_NSYMB] = {
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DMRS_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DMRS_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_GUARD_SYMBOL};
static const srslte_sl_symbol_t srslte_pssch_symbol_map_tm34[SRSLTE_CP_NORM_SF_NSYMB] = {SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DMRS_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DMRS_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DMRS_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_DMRS_SYMBOL,
SRSLTE_SIDELINK_DATA_SYMBOL,
SRSLTE_SIDELINK_GUARD_SYMBOL};
bool srslte_pssch_is_symbol(srslte_sl_symbol_t type, srslte_sl_tm_t tm, uint32_t i, srslte_cp_t cp)
{
if (tm == SRSLTE_SIDELINK_TM1 || tm == SRSLTE_SIDELINK_TM2) {
if (cp == SRSLTE_CP_EXT) {
return srslte_pssch_symbol_map_tm12_ext[i] == type;
}
return srslte_pssch_symbol_map_tm12[i] == type;
} else if (tm == SRSLTE_SIDELINK_TM3 || tm == SRSLTE_SIDELINK_TM4) {
return srslte_pssch_symbol_map_tm34[i] == type;
}
return false;
}
uint32_t srslte_sci_format0_sizeof(uint32_t nof_prb)
{
// 3GPP TS 36.212 5.4.3.1
uint32_t n = 0;
// Frequency hopping flag 1 bit
n += 1;
// Resource block assignment and hopping resource allocation
n += (uint32_t)ceil(log((nof_prb * (nof_prb + 1)) / 2.0) / log(2));
// Time resource pattern 7 bits
n += 7;
// Modulation and coding scheme 5 bit
n += 5;
// Timing advance indication 11 bits
n += 11;
// Group destination ID 8 bits
n += 8;
return n;
}
// Example pool configurations based on 3GPP TS 36.101 Version 15.6 Sections A.7 and A.9
int srslte_sl_comm_resource_pool_get_default_config(srslte_sl_comm_resource_pool_t* q, srslte_cell_sl_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL) {
q->period_length = 40;
if (cell.tm == SRSLTE_SIDELINK_TM3 || cell.tm == SRSLTE_SIDELINK_TM4) {
q->period_length = 160;
}
// Use full Bandwidth
q->prb_num = (uint32_t)ceil(cell.nof_prb / 2.0);
q->prb_start = 0;
q->prb_end = cell.nof_prb - 1;
q->size_sub_channel = 10;
q->num_sub_channel = 5;
q->start_prb_sub_channel = 0;
q->adjacency_pscch_pssch = true;
if (cell.tm == SRSLTE_SIDELINK_TM4) {
switch (cell.nof_prb) {
case 6:
q->size_sub_channel = 6;
q->num_sub_channel = 1;
break;
case 15:
case 25:
case 75:
q->size_sub_channel = 5;
q->num_sub_channel = cell.nof_prb / q->size_sub_channel;
break;
case 50:
case 100:
q->size_sub_channel = 10;
q->num_sub_channel = cell.nof_prb / q->size_sub_channel;
break;
default:
ERROR("Invalid nof_prb");
return SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}

@ -323,7 +323,7 @@ int srslte_psbch_put(srslte_psbch_t* q, cf_t* symbols, cf_t* sf_buffer)
// Mapping to physical resources
for (uint32_t i = 0; i < SRSLTE_CP_NORM_SF_NSYMB; i++) {
if (srslte_psbch_is_symbol(SRSLTE_SIDELINK_DATA_SYMBOL, q->tm, i)) {
if (srslte_psbch_is_symbol(SRSLTE_SIDELINK_DATA_SYMBOL, q->tm, i, q->cp)) {
memcpy(&sf_buffer[k + i * q->nof_prb * SRSLTE_NRE],
&symbols[sample_pos],
sizeof(cf_t) * (SRSLTE_NRE * SRSLTE_PSBCH_NOF_PRB));
@ -341,7 +341,7 @@ int srslte_psbch_get(srslte_psbch_t* q, cf_t* sf_buffer, cf_t* symbols)
// Get PSBCH REs
for (uint32_t i = 0; i < SRSLTE_CP_NORM_SF_NSYMB; i++) {
if (srslte_psbch_is_symbol(SRSLTE_SIDELINK_DATA_SYMBOL, q->tm, i)) {
if (srslte_psbch_is_symbol(SRSLTE_SIDELINK_DATA_SYMBOL, q->tm, i, q->cp)) {
memcpy(&symbols[sample_pos],
&sf_buffer[k + i * q->nof_prb * SRSLTE_NRE],
sizeof(cf_t) * (SRSLTE_NRE * SRSLTE_PSBCH_NOF_PRB));

@ -22,14 +22,12 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "srslte/phy/fec/rm_conv.h"
#include "srslte/phy/modem/demod_soft.h"
#include "srslte/phy/modem/mod.h"
#include "srslte/phy/phch/pscch.h"
#include "srslte/phy/phch/sch.h"
#include "srslte/phy/phch/sci.h"
#include "srslte/phy/scrambling/scrambling.h"
#include "srslte/phy/utils/bit.h"
#include "srslte/phy/utils/debug.h"
@ -82,7 +80,7 @@ int srslte_pscch_init(srslte_pscch_t* q, uint32_t max_prb)
srslte_viterbi_init(
&q->dec, SRSLTE_VITERBI_37, q->encoder.poly, SRSLTE_SCI_MAX_LEN + SRSLTE_SCI_CRC_LEN, q->encoder.tail_biting);
///< Max E value for memory allocation
// Max E value for memory allocation
uint32_t E_max = SRSLTE_NRE * SRSLTE_PSCCH_MAX_NUM_DATA_SYMBOLS * SRSLTE_PSCCH_MAX_NOF_PRB * SRSLTE_PSCCH_QM;
q->e = srslte_vec_u8_malloc(E_max);
if (!q->e) {
@ -196,7 +194,7 @@ int srslte_pscch_set_cell(srslte_pscch_t* q, srslte_cell_sl_t cell)
return ret;
}
int srslte_pscch_encode(srslte_pscch_t* q, uint8_t* sci, cf_t* sf_buffer, uint32_t prb_idx)
int srslte_pscch_encode(srslte_pscch_t* q, uint8_t* sci, cf_t* sf_buffer, uint32_t prb_start_idx)
{
memcpy(q->c, sci, sizeof(uint8_t) * q->sci_len);
@ -238,7 +236,7 @@ int srslte_pscch_encode(srslte_pscch_t* q, uint8_t* sci, cf_t* sf_buffer, uint32
// Void: Single antenna port
// 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 9.4.5
if (srslte_pscch_put(q, sf_buffer, prb_idx) != q->nof_tx_re) {
if (srslte_pscch_put(q, sf_buffer, prb_start_idx) != q->nof_tx_re) {
printf("Error during PSCCH RE mapping\n");
return SRSLTE_ERROR;
}
@ -246,9 +244,9 @@ int srslte_pscch_encode(srslte_pscch_t* q, uint8_t* sci, cf_t* sf_buffer, uint32
return SRSLTE_SUCCESS;
}
int srslte_pscch_decode(srslte_pscch_t* q, cf_t* equalized_sf_syms, uint8_t* sci, uint32_t prb_idx)
int srslte_pscch_decode(srslte_pscch_t* q, cf_t* equalized_sf_syms, uint8_t* sci, uint32_t prb_start_idx)
{
if (srslte_pscch_get(q, equalized_sf_syms, prb_idx) != q->nof_tx_re) {
if (srslte_pscch_get(q, equalized_sf_syms, prb_start_idx) != q->nof_tx_re) {
printf("Error during PSCCH RE extraction\n");
return SRSLTE_ERROR;
}
@ -297,10 +295,10 @@ int srslte_pscch_decode(srslte_pscch_t* q, cf_t* equalized_sf_syms, uint8_t* sci
return SRSLTE_SUCCESS;
}
int srslte_pscch_put(srslte_pscch_t* q, cf_t* sf_buffer, uint32_t prb_idx)
int srslte_pscch_put(srslte_pscch_t* q, cf_t* sf_buffer, uint32_t prb_start_idx)
{
int sample_pos = 0;
int k = prb_idx * SRSLTE_NRE;
int k = prb_start_idx * SRSLTE_NRE;
for (int i = 0; i < srslte_sl_get_num_symbols(q->cell.tm, q->cell.cp); ++i) {
if (srslte_pscch_is_symbol(SRSLTE_SIDELINK_DATA_SYMBOL, q->cell.tm, i, q->cell.cp)) {
memcpy(&sf_buffer[k + i * q->cell.nof_prb * SRSLTE_NRE],
@ -312,10 +310,10 @@ int srslte_pscch_put(srslte_pscch_t* q, cf_t* sf_buffer, uint32_t prb_idx)
return sample_pos;
}
int srslte_pscch_get(srslte_pscch_t* q, cf_t* sf_buffer, uint32_t prb_idx)
int srslte_pscch_get(srslte_pscch_t* q, cf_t* sf_buffer, uint32_t prb_start_idx)
{
int sample_pos = 0;
int k = prb_idx * SRSLTE_NRE;
int k = prb_start_idx * SRSLTE_NRE;
for (int i = 0; i < srslte_sl_get_num_symbols(q->cell.tm, q->cell.cp); ++i) {
if (srslte_pscch_is_symbol(SRSLTE_SIDELINK_DATA_SYMBOL, q->cell.tm, i, q->cell.cp)) {
memcpy(&q->scfdma_symbols[sample_pos],

@ -20,14 +20,11 @@
*/
#include <strings.h>
#include "srslte/phy/phch/sci.h"
#include "srslte/phy/utils/bit.h"
int srslte_sci_init(srslte_sci_t* q,
uint32_t nof_prb,
srslte_sl_tm_t tm,
uint32_t size_sub_channel,
uint32_t num_sub_channel)
int srslte_sci_init(srslte_sci_t* q, srslte_cell_sl_t cell, srslte_sl_comm_resource_pool_t sl_comm_resource_pool)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL) {
@ -35,18 +32,18 @@ int srslte_sci_init(srslte_sci_t* q,
bzero(q, sizeof(srslte_sci_t));
q->nof_prb = nof_prb;
q->tm = tm;
q->nof_prb = cell.nof_prb;
q->tm = cell.tm;
if (tm == SRSLTE_SIDELINK_TM1 || tm == SRSLTE_SIDELINK_TM2) {
q->format = SRSLTE_SCI_FORMAT0;
q->sci_len = srslte_sci_format0_sizeof(nof_prb);
if (cell.tm == SRSLTE_SIDELINK_TM1 || cell.tm == SRSLTE_SIDELINK_TM2) {
q->format = SRSLTE_SCI_FORMAT0;
q->sci_len = srslte_sci_format0_sizeof(cell.nof_prb);
} else if (tm == SRSLTE_SIDELINK_TM3 || tm == SRSLTE_SIDELINK_TM4) {
q->format = SRSLTE_SCI_FORMAT1;
} else if (cell.tm == SRSLTE_SIDELINK_TM3 || cell.tm == SRSLTE_SIDELINK_TM4) {
q->format = SRSLTE_SCI_FORMAT1;
q->sci_len = SRSLTE_SCI_TM34_LEN;
q->size_sub_channel = size_sub_channel;
q->num_sub_channel = num_sub_channel;
q->size_sub_channel = sl_comm_resource_pool.size_sub_channel;
q->num_sub_channel = sl_comm_resource_pool.num_sub_channel;
} else {
return SRSLTE_ERROR;
@ -105,6 +102,17 @@ int srslte_sci_format0_unpack(srslte_sci_t* q, uint8_t* input)
return SRSLTE_ERROR;
}
// Sanity check: avoid SCIs with all 0s
uint32_t i = 0;
for (; i < q->sci_len; i++) {
if (input[i] != 0) {
break;
}
}
if (i == q->sci_len) {
return SRSLTE_ERROR;
}
q->freq_hopping_flag = (bool)srslte_bit_pack(&input, 1);
if (q->freq_hopping_flag) {
printf("Frequency Hopping in Sidelink is not supported\n");
@ -117,6 +125,11 @@ int srslte_sci_format0_unpack(srslte_sci_t* q, uint8_t* input)
q->timing_advance = srslte_bit_pack(&input, 11);
q->N_sa_id = srslte_bit_pack(&input, 8);
// Sanity check
if (q->mcs_idx >= 29) {
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
@ -127,6 +140,17 @@ int srslte_sci_format1_unpack(srslte_sci_t* q, uint8_t* input)
return SRSLTE_ERROR;
}
// Sanity check: avoid SCIs with all 0s
uint32_t i = 0;
for (; i < q->sci_len; i++) {
if (input[i] != 0) {
break;
}
}
if (i == q->sci_len) {
return SRSLTE_ERROR;
}
q->priority = srslte_bit_pack(&input, 3);
q->resource_reserv = srslte_bit_pack(&input, 4);
q->riv = srslte_bit_pack(&input, (uint32_t)ceil(log2(((q->num_sub_channel) * (q->num_sub_channel + 1) / 2))));
@ -134,12 +158,18 @@ int srslte_sci_format1_unpack(srslte_sci_t* q, uint8_t* input)
q->mcs_idx = srslte_bit_pack(&input, 5);
q->retransmission = srslte_bit_pack(&input, 1);
// Sanity check
if (q->mcs_idx >= 29) {
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
void srslte_sci_info(char* str, srslte_sci_t* q)
void srslte_sci_info(const srslte_sci_t* q, char* str, uint32_t len)
{
uint32_t n = snprintf(str, 20, "SCI%i: riv=%i, mcs=%i", q->format, q->riv, q->mcs_idx);
uint32_t n = 0;
n = srslte_print_check(str, len, n, "SCI%i: riv=%i, mcs=%i", q->format, q->riv, q->mcs_idx);
if (q->format == SRSLTE_SCI_FORMAT0) {
n = srslte_print_check(str,
@ -168,29 +198,3 @@ void srslte_sci_free(srslte_sci_t* q)
bzero(q, sizeof(srslte_sci_t));
}
}
uint32_t srslte_sci_format0_sizeof(uint32_t nof_prb)
{
// 3GPP TS 36.212 5.4.3.1
uint32_t n = 0;
// Frequency hopping flag 1 bit
n += 1;
// Resource block assignment and hopping resource allocation
n += (uint32_t)ceil(log((nof_prb * (nof_prb + 1)) / 2.0) / log(2));
// Time resource pattern 7 bits
n += 7;
// Modulation and coding scheme 5 bit
n += 5;
// Timing advance indication 11 bits
n += 11;
// Group destination ID 8 bits
n += 8;
return n;
}

@ -89,39 +89,39 @@ add_executable(pscch_file_test pscch_file_test.c)
target_link_libraries(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(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")
# TM4 file tests
#add_test(pscch_file_test_ideal_tm4_p100 pscch_file_test -p 100 -t 4 -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(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(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(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")
# 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")
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")
# 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(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")
# With PHY ReTx (0 TTI offset?)
#add_test(pscch_test_tm4_p50_uxm1 pscch_file_test -p 50 -d -t 4 -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 "num_decoded_sci=2")
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")
# 100 PRB startOffset 1 MCS12 MAC padding
#add_test(pscch_test_tm4_p100_uxm2 pscch_file_test -p 100 -t 4 -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 "num_decoded_sci=4")
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")
# 100 PRB LTE sampling rate, startOffset1 MCS12 ITS data
#add_test(pscch_test_tm4_p100_uxm3 pscch_file_test -p 100 -d -t 4 -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 "num_decoded_sci=1")
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")
# 50 PRB LTE sampling rate, startOffset0 MCS28 MAC padding
#add_test(pscch_test_tm4_p50_uxm4 pscch_file_test -p 50 -d -t 4 -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 "num_decoded_sci=5")
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")
########################################################################
# NPBCH TEST

@ -24,25 +24,23 @@
#include <strings.h>
#include <unistd.h>
#include <srslte/phy/ch_estimation/chest_sl.h>
#include <srslte/phy/dft/ofdm.h>
#include <srslte/phy/io/filesource.h>
#include <srslte/phy/phch/mib_sl.h>
#include <srslte/phy/phch/psbch.h>
#include <srslte/phy/sync/cfo.h>
#include <srslte/phy/utils/debug.h>
#include <srslte/phy/utils/vector.h>
char* input_file_name;
int32_t N_sl_id = 168;
uint32_t offset = 0;
float frequency_offset = 0.0;
float snr = 100.0;
srslte_cp_t cp = SRSLTE_CP_NORM;
uint32_t nof_prb = 6;
bool use_standard_lte_rates = false;
bool do_equalization = true;
srslte_sl_tm_t tm = SRSLTE_SIDELINK_TM2;
#include "srslte/phy/ch_estimation/chest_sl.h"
#include "srslte/phy/dft/ofdm.h"
#include "srslte/phy/io/filesource.h"
#include "srslte/phy/phch/mib_sl.h"
#include "srslte/phy/phch/psbch.h"
#include "srslte/phy/sync/cfo.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
srslte_cell_sl_t cell = {.nof_prb = 6, .N_sl_id = 168, .tm = SRSLTE_SIDELINK_TM2, .cp = SRSLTE_CP_NORM};
char* input_file_name;
uint32_t offset = 0;
float frequency_offset = 0.0;
float snr = 100.0;
bool use_standard_lte_rates = false;
bool do_equalization = true;
srslte_filesource_t fsrc;
@ -50,12 +48,12 @@ void usage(char* prog)
{
printf("Usage: %s [cdeipt]\n", prog);
printf("\t-i input_file_name\n");
printf("\t-p nof_prb [Default %d]\n", nof_prb);
printf("\t-p nof_prb [Default %d]\n", cell.nof_prb);
printf("\t-e extended CP [Default normal]\n");
printf("\t-d use_standard_lte_rates [Default %i]\n", use_standard_lte_rates);
printf("\t-s skip equalization [Default no]\n");
printf("\t-c N_sl_id [Default %d]\n", N_sl_id);
printf("\t-t Sidelink transmission mode {1,2,3,4} [Default %d]\n", (tm + 1));
printf("\t-c N_sl_id [Default %d]\n", cell.N_sl_id);
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");
}
@ -65,7 +63,7 @@ void parse_args(int argc, char** argv)
while ((opt = getopt(argc, argv, "cdeisptv")) != -1) {
switch (opt) {
case 'c':
N_sl_id = (int32_t)strtol(argv[optind], NULL, 10);
cell.N_sl_id = (int32_t)strtol(argv[optind], NULL, 10);
break;
case 'd':
use_standard_lte_rates = true;
@ -74,27 +72,27 @@ void parse_args(int argc, char** argv)
do_equalization = false;
break;
case 'e':
cp = SRSLTE_CP_EXT;
cell.cp = SRSLTE_CP_EXT;
break;
case 'i':
input_file_name = argv[optind];
break;
case 'p':
nof_prb = (uint32_t)strtol(argv[optind], NULL, 10);
cell.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10);
break;
case 't':
switch (strtol(argv[optind], NULL, 10)) {
case 1:
tm = SRSLTE_SIDELINK_TM1;
cell.tm = SRSLTE_SIDELINK_TM1;
break;
case 2:
tm = SRSLTE_SIDELINK_TM2;
cell.tm = SRSLTE_SIDELINK_TM2;
break;
case 3:
tm = SRSLTE_SIDELINK_TM3;
cell.tm = SRSLTE_SIDELINK_TM3;
break;
case 4:
tm = SRSLTE_SIDELINK_TM4;
cell.tm = SRSLTE_SIDELINK_TM4;
break;
default:
usage(argv[0]);
@ -118,13 +116,13 @@ int main(int argc, char** argv)
parse_args(argc, argv);
srslte_use_standard_symbol_size(use_standard_lte_rates);
int32_t symbol_sz = srslte_symbol_sz(nof_prb);
int32_t symbol_sz = srslte_symbol_sz(cell.nof_prb);
printf("Symbol SZ: %i\n", symbol_sz);
uint32_t sf_n_samples = srslte_symbol_sz(nof_prb) * 15;
uint32_t sf_n_samples = srslte_symbol_sz(cell.nof_prb) * 15;
printf("sf_n_samples: %i\n", sf_n_samples);
uint32_t sf_n_re = SRSLTE_CP_NSYMB(cp) * SRSLTE_NRE * 2 * nof_prb;
uint32_t sf_n_re = SRSLTE_CP_NSYMB(cell.cp) * SRSLTE_NRE * 2 * cell.nof_prb;
cf_t* sf_buffer = srslte_vec_cf_malloc(sf_n_re);
cf_t* equalized_sf_buffer = srslte_vec_cf_malloc(sf_n_re);
@ -133,7 +131,7 @@ int main(int argc, char** argv)
// TX
srslte_ofdm_t ifft;
if (srslte_ofdm_tx_init(&ifft, cp, sf_buffer, output_buffer, nof_prb)) {
if (srslte_ofdm_tx_init(&ifft, cell.cp, sf_buffer, output_buffer, cell.nof_prb)) {
ERROR("Error creating IFFT object\n");
return SRSLTE_ERROR;
}
@ -142,7 +140,7 @@ int main(int argc, char** argv)
// RX
srslte_ofdm_t fft;
if (srslte_ofdm_rx_init(&fft, cp, input_buffer, sf_buffer, nof_prb)) {
if (srslte_ofdm_rx_init(&fft, cell.cp, input_buffer, sf_buffer, cell.nof_prb)) {
fprintf(stderr, "Error creating FFT object\n");
return SRSLTE_ERROR;
}
@ -151,15 +149,16 @@ int main(int argc, char** argv)
// PSBCH
srslte_psbch_t psbch;
if (srslte_psbch_init(&psbch, nof_prb, N_sl_id, tm, SRSLTE_CP_NORM) != SRSLTE_SUCCESS) {
if (srslte_psbch_init(&psbch, cell.nof_prb, cell.N_sl_id, cell.tm, SRSLTE_CP_NORM) != SRSLTE_SUCCESS) {
ERROR("Error in psbch init\n");
return SRSLTE_ERROR;
}
// PSCBH DMRS
srslte_chest_sl_t psbch_chest;
if (srslte_chest_sl_init_psbch_dmrs(&psbch_chest) != SRSLTE_SUCCESS) {
ERROR("Error in psbch dmrs init\n");
srslte_sl_comm_resource_pool_t sl_comm_resource_pool;
srslte_chest_sl_t psbch_chest;
if (srslte_chest_sl_init(&psbch_chest, SRSLTE_SIDELINK_PSBCH, cell, sl_comm_resource_pool) != SRSLTE_SUCCESS) {
ERROR("Error in chest PSBCH init\n");
return SRSLTE_ERROR;
}
@ -177,8 +176,7 @@ int main(int argc, char** argv)
// Equalize
if (do_equalization) {
srslte_chest_sl_gen_psbch_dmrs(&psbch_chest, tm, N_sl_id);
srslte_chest_sl_psbch_ls_estimate_equalize(&psbch_chest, sf_buffer, equalized_sf_buffer, nof_prb, tm, cp);
srslte_chest_sl_ls_estimate_equalize(&psbch_chest, sf_buffer, equalized_sf_buffer);
} else {
// just copy symbols
memcpy(equalized_sf_buffer, sf_buffer, sizeof(cf_t) * sf_n_re);
@ -194,12 +192,12 @@ int main(int argc, char** argv)
// Unpack and print MIB-SL
srslte_mib_sl_t mib_sl;
srslte_mib_sl_init(&mib_sl, tm);
srslte_mib_sl_init(&mib_sl, cell.tm);
srslte_mib_sl_unpack(&mib_sl, mib_sl_rx);
srslte_mib_sl_printf(stdout, &mib_sl);
// check decoded bandwidth matches user configured value
if (srslte_mib_sl_bandwith_to_prb[mib_sl.sl_bandwidth_r12] == nof_prb) {
if (srslte_mib_sl_bandwith_to_prb[mib_sl.sl_bandwidth_r12] == cell.nof_prb) {
ret = SRSLTE_SUCCESS;
}
}

@ -19,7 +19,6 @@
*
*/
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@ -27,52 +26,54 @@
#include "srslte/phy/ch_estimation/chest_sl.h"
#include "srslte/phy/channel/ch_awgn.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/common/phy_common_sl.h"
#include "srslte/phy/dft/ofdm.h"
#include "srslte/phy/io/filesource.h"
#include "srslte/phy/phch/pscch.h"
#include "srslte/phy/phch/sci.h"
#include "srslte/phy/sync/cfo.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
char* input_file_name;
srslte_cell_sl_t cell = {.nof_prb = 6, .N_sl_id = 0, .tm = SRSLTE_SIDELINK_TM2, .cp = SRSLTE_CP_NORM};
bool use_standard_lte_rates = false;
uint32_t size_sub_channel = 10;
uint32_t num_sub_channel = 5;
uint32_t file_offset = 0;
uint32_t sf_n_samples;
uint32_t sf_n_re;
cf_t* sf_buffer;
cf_t* equalized_sf_buffer;
cf_t* input_buffer;
srslte_sci_t sci;
srslte_pscch_t pscch;
srslte_chest_sl_t pscch_chest;
srslte_ofdm_t fft;
uint32_t sf_n_samples;
uint32_t sf_n_re;
cf_t* sf_buffer;
cf_t* equalized_sf_buffer;
cf_t* input_buffer;
srslte_sci_t sci;
srslte_pscch_t pscch;
srslte_chest_sl_t pscch_chest;
srslte_ofdm_t fft;
srslte_sl_comm_resource_pool_t sl_comm_resource_pool;
uint32_t size_sub_channel = 10;
uint32_t num_sub_channel = 5;
srslte_chest_sl_cfg_t pscch_chest_sl_cfg;
srslte_filesource_t fsrc;
void usage(char* prog)
{
printf("Usage: %s [deioptxzn]\n", prog);
printf("Usage: %s [deinopstv]\n", prog);
printf("\t-i input_file_name\n");
printf("\t-o File offset samples [Default %d]\n", file_offset);
printf("\t-p nof_prb [Default %d]\n", cell.nof_prb);
printf("\t-s size_sub_channel [Default for 50 prbs %d]\n", size_sub_channel);
printf("\t-n num_sub_channel [Default for 50 prbs %d]\n", num_sub_channel);
printf("\t-e Extended CP [Default normal]\n");
printf("\t-d use_standard_lte_rates [Default %i]\n", use_standard_lte_rates);
printf("\t-t Sidelink transmission mode {1,2,3,4} [Default %d]\n", (cell.tm + 1));
printf("\t-z Size of sub-channels [Default %i]\n", size_sub_channel);
printf("\t-n Number of sub-channels [Default %i]\n", num_sub_channel);
printf("\t-d use_standard_lte_rates [Default %i]\n", use_standard_lte_rates);
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, "deioptznv")) != -1) {
while ((opt = getopt(argc, argv, "deinopstv")) != -1) {
switch (opt) {
case 'd':
use_standard_lte_rates = true;
@ -86,6 +87,12 @@ void parse_args(int argc, char** argv)
case 'i':
input_file_name = argv[optind];
break;
case 's':
size_sub_channel = (int32_t)strtol(argv[optind], NULL, 10);
break;
case 'n':
num_sub_channel = (int32_t)strtol(argv[optind], NULL, 10);
break;
case 'p':
cell.nof_prb = (int32_t)strtol(argv[optind], NULL, 10);
break;
@ -109,11 +116,6 @@ void parse_args(int argc, char** argv)
break;
}
break;
case 'z':
size_sub_channel = (int32_t)strtol(argv[optind], NULL, 10);
break;
case 'n':
num_sub_channel = (int32_t)strtol(argv[optind], NULL, 10);
case 'v':
srslte_verbose++;
break;
@ -122,13 +124,24 @@ void parse_args(int argc, char** argv)
exit(-1);
}
}
if (cell.cp == SRSLTE_CP_EXT && cell.tm >= SRSLTE_SIDELINK_TM3) {
ERROR("Selected TM does not support extended CP");
usage(argv[0]);
exit(-1);
}
}
int base_init()
{
sf_n_samples = srslte_symbol_sz(cell.nof_prb) * 15;
sf_n_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
sf_n_re = SRSLTE_CP_NSYMB(cell.cp) * SRSLTE_NRE * 2 * cell.nof_prb;
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;
}
sl_comm_resource_pool.num_sub_channel = num_sub_channel;
sl_comm_resource_pool.size_sub_channel = size_sub_channel;
sf_buffer = srslte_vec_cf_malloc(sf_n_re);
if (!sf_buffer) {
@ -148,7 +161,7 @@ int base_init()
return SRSLTE_ERROR;
}
srslte_sci_init(&sci, cell.nof_prb, cell.tm, size_sub_channel, num_sub_channel);
srslte_sci_init(&sci, cell, sl_comm_resource_pool);
if (srslte_pscch_init(&pscch, SRSLTE_MAX_PRB) != SRSLTE_SUCCESS) {
ERROR("Error in PSCCH init\n");
@ -160,7 +173,7 @@ int base_init()
return SRSLTE_ERROR;
}
if (srslte_chest_sl_init_pscch_dmrs(&pscch_chest) != SRSLTE_SUCCESS) {
if (srslte_chest_sl_init(&pscch_chest, SRSLTE_SIDELINK_PSCCH, cell, sl_comm_resource_pool) != SRSLTE_SUCCESS) {
ERROR("Error in PSCCH DMRS init\n");
return SRSLTE_ERROR;
}
@ -220,7 +233,7 @@ int main(int argc, char** argv)
}
uint32_t num_decoded_sci = 0;
char sci_msg[SRSLTE_SCI_MSG_MAX_LEN] = "";
char sci_msg[SRSLTE_SCI_MSG_MAX_LEN] = {};
int max_num_subframes = 128;
int num_subframes = 0;
@ -247,59 +260,62 @@ int main(int argc, char** argv)
srslte_ofdm_rx_sf(&fft);
if (cell.tm == SRSLTE_SIDELINK_TM1 || cell.tm == SRSLTE_SIDELINK_TM2) {
uint32_t prb_num = (uint32_t)ceil(cell.nof_prb / 2);
uint32_t prb_start = 0;
uint32_t prb_end = cell.nof_prb - 1;
uint32_t cyclic_shift = 0;
srslte_chest_sl_gen_pscch_dmrs(&pscch_chest, cyclic_shift, cell.tm);
for (uint32_t pscch_prb_idx = prb_start; pscch_prb_idx <= prb_end; pscch_prb_idx++) {
if (pscch_prb_idx == (prb_start + prb_num)) {
pscch_prb_idx = (prb_end + 1) - prb_num;
}
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++) {
// PSCCH Channel estimation
srslte_chest_sl_pscch_ls_estimate_equalize(
&pscch_chest, sf_buffer, pscch_prb_idx, equalized_sf_buffer, cell.nof_prb, cell.tm, cell.cp);
pscch_chest_sl_cfg.prb_start_idx = pscch_prb_start_idx;
srslte_chest_sl_set_cfg(&pscch_chest, pscch_chest_sl_cfg);
srslte_chest_sl_ls_estimate_equalize(&pscch_chest, sf_buffer, equalized_sf_buffer);
if (srslte_pscch_decode(&pscch, equalized_sf_buffer, sci_rx, pscch_prb_idx) == SRSLTE_SUCCESS) {
if (srslte_sci_format0_unpack(&sci, sci_rx) != SRSLTE_SUCCESS) {
printf("Error unpacking sci format 0\n");
return SRSLTE_ERROR;
}
if (srslte_pscch_decode(&pscch, equalized_sf_buffer, sci_rx, pscch_prb_start_idx) == SRSLTE_SUCCESS) {
if (srslte_sci_format0_unpack(&sci, sci_rx) == SRSLTE_SUCCESS) {
srslte_sci_info(&sci, sci_msg, sizeof(sci_msg));
fprintf(stdout, "%s", sci_msg);
srslte_sci_info(sci_msg, &sci);
fprintf(stdout, "%s", sci_msg);
num_decoded_sci++;
}
}
num_decoded_sci++;
if ((sl_comm_resource_pool.prb_num * 2) <=
(sl_comm_resource_pool.prb_end - sl_comm_resource_pool.prb_start + 1)) {
if ((pscch_prb_start_idx + 1) == (sl_comm_resource_pool.prb_start + sl_comm_resource_pool.prb_num)) {
pscch_prb_start_idx = sl_comm_resource_pool.prb_end - sl_comm_resource_pool.prb_num;
}
}
}
} else if (cell.tm == SRSLTE_SIDELINK_TM3 || cell.tm == SRSLTE_SIDELINK_TM4) {
for (int i = 0; i < num_sub_channel; i++) {
uint32_t pscch_prb_idx = size_sub_channel * i;
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 (uint32_t cyclic_shift = 0; cyclic_shift <= 9; cyclic_shift += 3) {
// PSCCH Channel estimation
srslte_chest_sl_gen_pscch_dmrs(&pscch_chest, cyclic_shift, cell.tm);
srslte_chest_sl_pscch_ls_estimate_equalize(
&pscch_chest, sf_buffer, pscch_prb_idx, equalized_sf_buffer, cell.nof_prb, cell.tm, cell.cp);
if (srslte_pscch_decode(&pscch, equalized_sf_buffer, sci_rx, pscch_prb_idx) == SRSLTE_SUCCESS) {
if (srslte_sci_format1_unpack(&sci, sci_rx) != SRSLTE_SUCCESS) {
printf("Error unpacking sci format 1\n");
return SRSLTE_ERROR;
}
pscch_chest_sl_cfg.cyclic_shift = cyclic_shift;
pscch_chest_sl_cfg.prb_start_idx = pscch_prb_start_idx;
srslte_chest_sl_set_cfg(&pscch_chest, pscch_chest_sl_cfg);
srslte_chest_sl_ls_estimate_equalize(&pscch_chest, sf_buffer, equalized_sf_buffer);
srslte_sci_info(sci_msg, &sci);
fprintf(stdout, "%s", sci_msg);
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) {
num_decoded_sci++;
srslte_sci_info(&sci, sci_msg, sizeof(sci_msg));
fprintf(stdout, "%s", sci_msg);
num_decoded_sci++;
}
}
if (SRSLTE_VERBOSE_ISDEBUG()) {
char filename[64];
snprintf(
filename, 64, "pscch_rx_syms_sf%d_shift%d_prbidx%d.bin", num_subframes, cyclic_shift, pscch_prb_idx);
snprintf(filename,
64,
"pscch_rx_syms_sf%d_shift%d_prbidx%d.bin",
num_subframes,
cyclic_shift,
pscch_prb_start_idx);
printf("Saving PSCCH symbols (%d) to %s\n", pscch.E / SRSLTE_PSCCH_QM, filename);
srslte_vec_save_file(filename, pscch.mod_symbols, pscch.E / SRSLTE_PSCCH_QM * sizeof(cf_t));
}

@ -19,8 +19,6 @@
*
*/
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
@ -31,11 +29,9 @@
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
srslte_cell_sl_t cell = {.nof_prb = 6, .N_sl_id = 168, .tm = SRSLTE_SIDELINK_TM2, .cp = SRSLTE_CP_NORM};
uint32_t size_sub_channel = 10;
uint32_t num_sub_channel = 5;
srslte_cell_sl_t cell = {.nof_prb = 6, .N_sl_id = 168, .tm = SRSLTE_SIDELINK_TM2, .cp = SRSLTE_CP_NORM};
uint32_t prb_idx = 0;
uint32_t prb_start_idx = 0;
void usage(char* prog)
{
@ -85,6 +81,11 @@ void parse_args(int argc, char** argv)
exit(-1);
}
}
if (cell.cp == SRSLTE_CP_EXT && cell.tm >= SRSLTE_SIDELINK_TM3) {
ERROR("Selected TM does not support extended CP");
usage(argv[0]);
exit(-1);
}
}
int main(int argc, char** argv)
@ -93,14 +94,21 @@ int main(int argc, char** argv)
parse_args(argc, argv);
char sci_msg[SRSLTE_SCI_MSG_MAX_LEN] = "";
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;
}
char sci_msg[SRSLTE_SCI_MSG_MAX_LEN] = {};
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);
// SCI
srslte_sci_t sci;
srslte_sci_init(&sci, cell.nof_prb, cell.tm, size_sub_channel, num_sub_channel);
srslte_sci_init(&sci, cell, sl_comm_resource_pool);
sci.mcs_idx = 2;
// PSCCH
srslte_pscch_t pscch;
@ -132,13 +140,13 @@ int main(int argc, char** argv)
srslte_vec_fprint_hex(stdout, sci_tx, sci.sci_len);
// Put SCI into PSCCH
srslte_pscch_encode(&pscch, sci_tx, sf_buffer, prb_idx);
srslte_pscch_encode(&pscch, sci_tx, sf_buffer, prb_start_idx);
// Prepare Rx buffer
uint8_t sci_rx[SRSLTE_SCI_MAX_LEN] = {};
// Decode PSCCH
if (srslte_pscch_decode(&pscch, sf_buffer, sci_rx, prb_idx) == SRSLTE_SUCCESS) {
if (srslte_pscch_decode(&pscch, sf_buffer, sci_rx, prb_start_idx) == SRSLTE_SUCCESS) {
printf("Rx payload: ");
srslte_vec_fprint_hex(stdout, sci_rx, sci.sci_len);
@ -155,7 +163,7 @@ int main(int argc, char** argv)
}
}
srslte_sci_info(sci_msg, &sci);
srslte_sci_info(&sci, sci_msg, sizeof(sci_msg));
fprintf(stdout, "%s", sci_msg);
if (sci.riv == riv_txed) {
ret = SRSLTE_SUCCESS;
@ -167,4 +175,4 @@ int main(int argc, char** argv)
srslte_pscch_free(&pscch);
return ret;
}
}

Loading…
Cancel
Save