mirror of https://github.com/pvnis/srsRAN_4G.git
baseline implementation of pscch
parent
8e4f2a4d59
commit
cabd9ae742
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2019 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_PSCCH_H
|
||||||
|
#define SRSLTE_PSCCH_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "srslte/phy/common/phy_common.h"
|
||||||
|
#include "srslte/phy/common/sequence.h"
|
||||||
|
#include "srslte/phy/dft/dft_precoding.h"
|
||||||
|
#include "srslte/phy/fec/convcoder.h"
|
||||||
|
#include "srslte/phy/fec/crc.h"
|
||||||
|
#include "srslte/phy/fec/viterbi.h"
|
||||||
|
#include "srslte/phy/modem/modem_table.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Physical Sidelink control channel.
|
||||||
|
*
|
||||||
|
* Reference: 3GPP TS 36.211 version 15.6.0 Release 15 Section 9.4
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
|
||||||
|
srslte_sl_tm_t tm;
|
||||||
|
srslte_cp_t cp;
|
||||||
|
|
||||||
|
uint32_t sci_len;
|
||||||
|
uint32_t nof_tx_re;
|
||||||
|
|
||||||
|
uint32_t pscch_nof_prb;
|
||||||
|
|
||||||
|
// crc
|
||||||
|
uint8_t* c;
|
||||||
|
srslte_crc_t crc;
|
||||||
|
uint8_t* sci_crc;
|
||||||
|
|
||||||
|
// channel coding
|
||||||
|
srslte_viterbi_t dec;
|
||||||
|
srslte_convcoder_t encoder;
|
||||||
|
uint8_t* d;
|
||||||
|
int16_t* d_16;
|
||||||
|
|
||||||
|
// rate matching
|
||||||
|
uint32_t E;
|
||||||
|
uint8_t* e;
|
||||||
|
int16_t* e_16;
|
||||||
|
|
||||||
|
uint8_t* e_bytes; ///< To pack bits to bytes
|
||||||
|
uint32_t nof_symbols;
|
||||||
|
|
||||||
|
// interleaving
|
||||||
|
uint32_t* interleaver_lut;
|
||||||
|
uint8_t* codeword;
|
||||||
|
uint8_t* codeword_bytes;
|
||||||
|
|
||||||
|
uint32_t nof_prb;
|
||||||
|
|
||||||
|
// scrambling
|
||||||
|
srslte_sequence_t seq;
|
||||||
|
|
||||||
|
// modulation
|
||||||
|
srslte_modem_table_t mod;
|
||||||
|
cf_t* mod_symbols;
|
||||||
|
int16_t* llr;
|
||||||
|
|
||||||
|
// dft precoding
|
||||||
|
srslte_dft_precoding_t dft_precoder;
|
||||||
|
srslte_dft_precoding_t idft_precoder;
|
||||||
|
|
||||||
|
cf_t* scfdma_symbols;
|
||||||
|
|
||||||
|
} srslte_pscch_t;
|
||||||
|
|
||||||
|
SRSLTE_API int srslte_pscch_init(srslte_pscch_t* q, uint32_t nof_prb, srslte_sl_tm_t tm, srslte_cp_t cp);
|
||||||
|
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 void srslte_pscch_free(srslte_pscch_t* q);
|
||||||
|
|
||||||
|
#endif // SRSLTE_PSCCH_H
|
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2019 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_SCI_H
|
||||||
|
#define SRSLTE_SCI_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "srslte/config.h"
|
||||||
|
#include "srslte/phy/common/phy_common.h"
|
||||||
|
|
||||||
|
#define SRSLTE_SCI_MSG_MAX_LEN 80
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sidelink Control Information - Sidelink (SCI0 and SCI1).
|
||||||
|
*
|
||||||
|
* \brief SCI0/1 packing/unpacking functions to convert between bit streams
|
||||||
|
*
|
||||||
|
* Reference: 3GPP TS 36.212 version 15.6.0 Release 15 Section 5.4.3
|
||||||
|
*/
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
|
||||||
|
srslte_sl_tm_t tm;
|
||||||
|
uint32_t sci_len;
|
||||||
|
uint32_t nof_prb;
|
||||||
|
|
||||||
|
srslte_sci_format_t format;
|
||||||
|
|
||||||
|
// sizeSubChannel
|
||||||
|
uint32_t size_sub_channel;
|
||||||
|
|
||||||
|
// numSubChannel
|
||||||
|
uint32_t num_sub_channel;
|
||||||
|
|
||||||
|
///< SCI Format 0: Resource block assignment and hopping resource allocation
|
||||||
|
///< SCI Format 1: Frequency resource location (0,3,6,7,8 bits)
|
||||||
|
uint32_t riv;
|
||||||
|
|
||||||
|
// Modulation and coding scheme (bits);
|
||||||
|
uint32_t mcs_idx;
|
||||||
|
|
||||||
|
///< SCI Format 0
|
||||||
|
// Frequency hopping flag (1 bit)
|
||||||
|
bool freq_hopping_flag;
|
||||||
|
|
||||||
|
uint32_t hopping_bits;
|
||||||
|
|
||||||
|
// TRP - Time resource pattern (7bits)
|
||||||
|
uint32_t trp_idx;
|
||||||
|
|
||||||
|
// Timing advance indication (11 bits)
|
||||||
|
uint32_t timing_advance;
|
||||||
|
|
||||||
|
// Group ID (8 bits)
|
||||||
|
uint32_t N_sa_id;
|
||||||
|
|
||||||
|
///< SCI Format 1
|
||||||
|
// Priority (3bits)
|
||||||
|
uint32_t priority;
|
||||||
|
|
||||||
|
// Resource reservation (4 bits)
|
||||||
|
uint32_t resource_reserv;
|
||||||
|
|
||||||
|
// Time gap (4 bits)
|
||||||
|
uint32_t time_gap;
|
||||||
|
|
||||||
|
// Retransmission index (1 bit)
|
||||||
|
bool retransmission;
|
||||||
|
|
||||||
|
} 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_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_free(srslte_sci_t* q);
|
||||||
|
|
||||||
|
#endif // SRSLTE_SCI_H
|
@ -0,0 +1,361 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2019 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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "srslte/phy/phch/pscch.h"
|
||||||
|
#include "srslte/phy/fec/rm_conv.h"
|
||||||
|
#include "srslte/phy/utils/bit.h"
|
||||||
|
#include "srslte/phy/utils/debug.h"
|
||||||
|
#include "srslte/phy/utils/vector.h"
|
||||||
|
#include "srslte/phy/modem/demod_soft.h"
|
||||||
|
#include "srslte/phy/modem/mod.h"
|
||||||
|
#include "srslte/phy/phch/sch.h"
|
||||||
|
#include "srslte/phy/scrambling/scrambling.h"
|
||||||
|
|
||||||
|
int srslte_pscch_init(srslte_pscch_t* q, uint32_t nof_prb, srslte_sl_tm_t tm, srslte_cp_t cp)
|
||||||
|
{
|
||||||
|
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||||
|
|
||||||
|
if (q != NULL) {
|
||||||
|
ret = SRSLTE_ERROR;
|
||||||
|
|
||||||
|
q->cp = cp;
|
||||||
|
q->tm = tm;
|
||||||
|
q->nof_prb = nof_prb;
|
||||||
|
|
||||||
|
if (tm == SRSLTE_SIDELINK_TM1 || tm == SRSLTE_SIDELINK_TM2) {
|
||||||
|
q->sci_len = srslte_sci_format0_sizeof(nof_prb);
|
||||||
|
q->nof_symbols = SRSLTE_PSCCH_TM12_NUM_DATA_SYMBOLS;
|
||||||
|
q->pscch_nof_prb = SRSLTE_PSCCH_TM12_NOF_PRB;
|
||||||
|
|
||||||
|
if (cp == SRSLTE_CP_EXT) {
|
||||||
|
q->nof_symbols = SRSLTE_PSCCH_TM12_NUM_DATA_SYMBOLS_EXT;
|
||||||
|
}
|
||||||
|
} else if (tm == SRSLTE_SIDELINK_TM3 || tm == SRSLTE_SIDELINK_TM4) {
|
||||||
|
q->sci_len = SRSLTE_SCI_TM34_LEN;
|
||||||
|
q->nof_symbols = SRSLTE_PSCCH_TM34_NUM_DATA_SYMBOLS;
|
||||||
|
q->pscch_nof_prb = SRSLTE_PSCCH_TM34_NOF_PRB;
|
||||||
|
} else {
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRC
|
||||||
|
uint32_t crc_poly = 0x11021;
|
||||||
|
if (srslte_crc_init(&q->crc, crc_poly, SRSLTE_SCI_CRC_LEN)) {
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
q->c = srslte_vec_malloc(sizeof(uint8_t) * SRSLTE_SCI_MAX_LEN + SRSLTE_SCI_CRC_LEN);
|
||||||
|
if (!q->c) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
q->sci_crc = srslte_vec_malloc(sizeof(uint8_t) * SRSLTE_SCI_CRC_LEN);
|
||||||
|
if (!q->sci_crc) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Channel Coding
|
||||||
|
q->encoder.K = 7;
|
||||||
|
q->encoder.R = 3;
|
||||||
|
q->encoder.tail_biting = true;
|
||||||
|
int poly[3] = {0x6D, 0x4F, 0x57};
|
||||||
|
memcpy(q->encoder.poly, poly, 3 * sizeof(int));
|
||||||
|
q->d = srslte_vec_malloc(sizeof(uint8_t) * (3 * (SRSLTE_SCI_MAX_LEN + SRSLTE_SCI_CRC_LEN)));
|
||||||
|
if (!q->d) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
bzero(q->d, sizeof(uint8_t) * (3 * (SRSLTE_SCI_MAX_LEN + SRSLTE_SCI_CRC_LEN)));
|
||||||
|
|
||||||
|
q->d_16 = srslte_vec_malloc(sizeof(int16_t) * (3 * (SRSLTE_SCI_MAX_LEN + SRSLTE_SCI_CRC_LEN)));
|
||||||
|
if (!q->d_16) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
srslte_viterbi_init(
|
||||||
|
&q->dec, SRSLTE_VITERBI_37, q->encoder.poly, SRSLTE_SCI_MAX_LEN + SRSLTE_SCI_CRC_LEN, q->encoder.tail_biting);
|
||||||
|
|
||||||
|
q->E = SRSLTE_NRE * q->nof_symbols * q->pscch_nof_prb * SRSLTE_PSCCH_QM;
|
||||||
|
q->e = srslte_vec_malloc(sizeof(uint8_t) * q->E);
|
||||||
|
if (!q->e) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
q->e_16 = srslte_vec_malloc(sizeof(int16_t) * q->E);
|
||||||
|
if (!q->e_16) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
q->e_bytes = srslte_vec_malloc(sizeof(uint8_t) * q->E / 8);
|
||||||
|
if (!q->e_bytes) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
q->interleaver_lut = srslte_vec_malloc(sizeof(uint32_t) * q->E);
|
||||||
|
if (!q->interleaver_lut) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
q->codeword = srslte_vec_malloc(sizeof(uint8_t) * q->E);
|
||||||
|
if (!q->codeword) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
q->codeword_bytes = srslte_vec_malloc(sizeof(uint8_t) * q->E / 8);
|
||||||
|
if (!q->codeword_bytes) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scrambling
|
||||||
|
bzero(&q->seq, sizeof(srslte_sequence_t));
|
||||||
|
srslte_sequence_LTE_pr(&q->seq, q->E, SRSLTE_PSCCH_SCRAMBLING_SEED);
|
||||||
|
|
||||||
|
// Modulation
|
||||||
|
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
q->mod_symbols = srslte_vec_malloc(sizeof(cf_t) * q->E / SRSLTE_PSCCH_QM);
|
||||||
|
if (!q->mod_symbols) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
q->llr = srslte_vec_malloc(sizeof(float) * q->E);
|
||||||
|
if (!q->llr) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DFT Precoding
|
||||||
|
if (srslte_dft_precoding_init(&q->dft_precoder, q->nof_prb, true)) {
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
q->scfdma_symbols = srslte_vec_malloc(sizeof(cf_t) * q->E / SRSLTE_PSCCH_QM);
|
||||||
|
if (!q->scfdma_symbols) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IDFT Predecoding
|
||||||
|
if (srslte_dft_precoding_init(&q->idft_precoder, q->pscch_nof_prb, false)) {
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
q->nof_tx_re = (q->nof_symbols - 1) * SRSLTE_NRE * q->pscch_nof_prb; // Last OFDM symbol is used channel processing but not transmitted
|
||||||
|
|
||||||
|
ret = SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srslte_pscch_encode(srslte_pscch_t* q, uint8_t* sci, cf_t* sf_buffer, uint32_t prb_idx)
|
||||||
|
{
|
||||||
|
memcpy(q->c, sci, sizeof(uint8_t) * q->sci_len);
|
||||||
|
|
||||||
|
// CRC Attachment
|
||||||
|
srslte_crc_attach(&q->crc, q->c, q->sci_len);
|
||||||
|
|
||||||
|
// Channel Coding
|
||||||
|
srslte_convcoder_encode(&q->encoder, q->c, q->d, q->sci_len + SRSLTE_SCI_CRC_LEN);
|
||||||
|
|
||||||
|
// Rate Matching
|
||||||
|
if (srslte_rm_conv_tx(q->d, (3 * (q->sci_len + SRSLTE_SCI_CRC_LEN)), q->e, q->E)) {
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interleaving
|
||||||
|
srslte_bit_pack_vector(q->e, q->e_bytes, q->E);
|
||||||
|
srslte_sl_ulsch_interleave(q->e_bytes, // input bytes
|
||||||
|
SRSLTE_PSCCH_QM, // modulation
|
||||||
|
q->E / SRSLTE_PSCCH_QM, // prime number
|
||||||
|
q->nof_symbols, // nof pscch symbols
|
||||||
|
q->codeword_bytes // output
|
||||||
|
);
|
||||||
|
srslte_bit_unpack_vector(q->codeword_bytes, q->codeword, q->E);
|
||||||
|
|
||||||
|
// Scrambling
|
||||||
|
srslte_scrambling_b(&q->seq, q->codeword);
|
||||||
|
|
||||||
|
// Modulation
|
||||||
|
srslte_mod_modulate(&q->mod, q->codeword, q->mod_symbols, q->E);
|
||||||
|
|
||||||
|
// Layer Mapping
|
||||||
|
// Void: Single layer
|
||||||
|
// 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 9.4.3
|
||||||
|
|
||||||
|
// DFT Precoding
|
||||||
|
srslte_dft_precoding(&q->dft_precoder, q->mod_symbols, q->scfdma_symbols, q->pscch_nof_prb, q->nof_symbols);
|
||||||
|
|
||||||
|
// Precoding
|
||||||
|
// 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) {
|
||||||
|
printf("Error during PSCCH RE mapping\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srslte_pscch_decode(srslte_pscch_t* q, cf_t* equalized_sf_syms, uint8_t* sci, uint32_t prb_idx)
|
||||||
|
{
|
||||||
|
if (srslte_pscch_get(q, equalized_sf_syms, prb_idx) != q->nof_tx_re) {
|
||||||
|
printf("Error during PSCCH RE extraction\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Precoding
|
||||||
|
// Void: Single antenna port
|
||||||
|
// 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 9.4.5
|
||||||
|
|
||||||
|
// IDFT Precoding
|
||||||
|
srslte_dft_precoding(&q->idft_precoder, q->scfdma_symbols, q->mod_symbols, q->pscch_nof_prb, q->nof_symbols);
|
||||||
|
|
||||||
|
// Layer Mapping
|
||||||
|
// Void: Single layer
|
||||||
|
// 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 9.4.3
|
||||||
|
|
||||||
|
// Demodulation
|
||||||
|
srslte_demod_soft_demodulate_s(SRSLTE_MOD_QPSK, q->mod_symbols, q->llr, q->E / SRSLTE_PSCCH_QM);
|
||||||
|
|
||||||
|
// Descrambling
|
||||||
|
srslte_scrambling_s(&q->seq, q->llr);
|
||||||
|
|
||||||
|
// Deinterleaving
|
||||||
|
srslte_sl_ulsch_deinterleave(
|
||||||
|
q->llr, SRSLTE_PSCCH_QM, q->E / SRSLTE_PSCCH_QM, q->nof_symbols, q->e_16, q->interleaver_lut);
|
||||||
|
|
||||||
|
// Rate matching
|
||||||
|
srslte_rm_conv_rx_s(q->e_16, q->E, q->d_16, (3 * (q->sci_len + SRSLTE_SCI_CRC_LEN)));
|
||||||
|
|
||||||
|
// Channel decoding
|
||||||
|
srslte_viterbi_decode_s(&q->dec, q->d_16, q->c, q->sci_len + SRSLTE_SCI_CRC_LEN);
|
||||||
|
|
||||||
|
// Copy received crc
|
||||||
|
memcpy(q->sci_crc, &q->c[q->sci_len], sizeof(uint8_t) * SRSLTE_SCI_CRC_LEN);
|
||||||
|
|
||||||
|
// Re-attach crc
|
||||||
|
srslte_crc_attach(&q->crc, q->c, q->sci_len);
|
||||||
|
|
||||||
|
// CRC check
|
||||||
|
if (srslte_bit_diff(q->sci_crc, &q->c[q->sci_len], SRSLTE_SCI_CRC_LEN) != 0) {
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove CRC and copy content to sci buffer
|
||||||
|
memcpy(sci, q->c, sizeof(uint8_t) * q->sci_len);
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srslte_pscch_put(srslte_pscch_t* q, cf_t* sf_buffer, uint32_t prb_idx)
|
||||||
|
{
|
||||||
|
int sample_pos = 0;
|
||||||
|
int k = prb_idx * SRSLTE_NRE;
|
||||||
|
for (int i = 0; i < srslte_sl_get_num_symbols(q->tm, q->cp); ++i) {
|
||||||
|
if (srslte_pscch_is_symbol(SRSLTE_SIDELINK_DATA_SYMBOL, q->tm, i, q->cp)) {
|
||||||
|
memcpy(&sf_buffer[k + i * q->nof_prb * SRSLTE_NRE],
|
||||||
|
&q->scfdma_symbols[sample_pos],
|
||||||
|
sizeof(cf_t) * (SRSLTE_NRE * q->pscch_nof_prb));
|
||||||
|
sample_pos += (SRSLTE_NRE * q->pscch_nof_prb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sample_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srslte_pscch_get(srslte_pscch_t* q, cf_t* sf_buffer, uint32_t prb_idx)
|
||||||
|
{
|
||||||
|
int sample_pos = 0;
|
||||||
|
int k = prb_idx * SRSLTE_NRE;
|
||||||
|
for (int i = 0; i < srslte_sl_get_num_symbols(q->tm, q->cp); ++i) {
|
||||||
|
if (srslte_pscch_is_symbol(SRSLTE_SIDELINK_DATA_SYMBOL, q->tm, i, q->cp)) {
|
||||||
|
memcpy(&q->scfdma_symbols[sample_pos],
|
||||||
|
&sf_buffer[k + i * q->nof_prb * SRSLTE_NRE],
|
||||||
|
sizeof(cf_t) * (SRSLTE_NRE * q->pscch_nof_prb));
|
||||||
|
sample_pos += (SRSLTE_NRE * q->pscch_nof_prb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sample_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void srslte_pscch_free(srslte_pscch_t* q)
|
||||||
|
{
|
||||||
|
if (q != NULL) {
|
||||||
|
srslte_dft_precoding_free(&q->dft_precoder);
|
||||||
|
srslte_dft_precoding_free(&q->idft_precoder);
|
||||||
|
srslte_viterbi_free(&q->dec);
|
||||||
|
srslte_sequence_free(&q->seq);
|
||||||
|
srslte_modem_table_free(&q->mod);
|
||||||
|
|
||||||
|
if (q->sci_crc) {
|
||||||
|
free(q->sci_crc);
|
||||||
|
}
|
||||||
|
if (q->c) {
|
||||||
|
free(q->c);
|
||||||
|
}
|
||||||
|
if (q->d) {
|
||||||
|
free(q->d);
|
||||||
|
}
|
||||||
|
if (q->d_16) {
|
||||||
|
free(q->d_16);
|
||||||
|
}
|
||||||
|
if (q->e) {
|
||||||
|
free(q->e);
|
||||||
|
}
|
||||||
|
if (q->e_16) {
|
||||||
|
free(q->e_16);
|
||||||
|
}
|
||||||
|
if (q->e_bytes) {
|
||||||
|
free(q->e_bytes);
|
||||||
|
}
|
||||||
|
if (q->interleaver_lut) {
|
||||||
|
free(q->interleaver_lut);
|
||||||
|
}
|
||||||
|
if (q->codeword) {
|
||||||
|
free(q->codeword);
|
||||||
|
}
|
||||||
|
if (q->codeword_bytes) {
|
||||||
|
free(q->codeword_bytes);
|
||||||
|
}
|
||||||
|
if (q->llr) {
|
||||||
|
free(q->llr);
|
||||||
|
}
|
||||||
|
if (q->mod_symbols) {
|
||||||
|
free(q->mod_symbols);
|
||||||
|
}
|
||||||
|
if (q->scfdma_symbols) {
|
||||||
|
free(q->scfdma_symbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(q, sizeof(srslte_pscch_t));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2019 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 <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 ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||||
|
if (q != NULL) {
|
||||||
|
ret = SRSLTE_ERROR;
|
||||||
|
|
||||||
|
bzero(q, sizeof(srslte_sci_t));
|
||||||
|
|
||||||
|
q->nof_prb = nof_prb;
|
||||||
|
q->tm = tm;
|
||||||
|
|
||||||
|
if (tm == SRSLTE_SIDELINK_TM1 || tm == SRSLTE_SIDELINK_TM2) {
|
||||||
|
q->format = SRSLTE_SCI_FORMAT0;
|
||||||
|
q->sci_len = srslte_sci_format0_sizeof(nof_prb);
|
||||||
|
|
||||||
|
} else if (tm == SRSLTE_SIDELINK_TM3 || 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;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
ret = SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srslte_sci_format0_pack(srslte_sci_t* q, uint8_t* output)
|
||||||
|
{
|
||||||
|
if (!q) {
|
||||||
|
printf("Error packing SCI Format 0\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(output, sizeof(uint8_t) * SRSLTE_SCI_MAX_LEN);
|
||||||
|
srslte_bit_unpack((uint32_t)q->freq_hopping_flag, &output, 1);
|
||||||
|
if (q->freq_hopping_flag) {
|
||||||
|
printf("Frequency Hopping in Sidelink is not supported\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
} else {
|
||||||
|
srslte_bit_unpack(q->riv, &output, (uint32_t)ceil(log2(((q->nof_prb) * (q->nof_prb + 1) / 2))));
|
||||||
|
}
|
||||||
|
srslte_bit_unpack(q->trp_idx, &output, 7);
|
||||||
|
srslte_bit_unpack(q->mcs_idx, &output, 5);
|
||||||
|
srslte_bit_unpack(q->timing_advance, &output, 11);
|
||||||
|
srslte_bit_unpack(q->N_sa_id, &output, 8);
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srslte_sci_format1_pack(srslte_sci_t* q, uint8_t* output)
|
||||||
|
{
|
||||||
|
if (!q) {
|
||||||
|
printf("Error packing SCI Format 1\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(output, sizeof(uint8_t) * SRSLTE_SCI_MAX_LEN);
|
||||||
|
srslte_bit_unpack(q->priority, &output, 3);
|
||||||
|
srslte_bit_unpack(q->resource_reserv, &output, 4);
|
||||||
|
srslte_bit_unpack(q->riv, &output, (uint32_t)ceil(log2(((q->num_sub_channel) * (q->num_sub_channel + 1) / 2))));
|
||||||
|
srslte_bit_unpack(q->time_gap, &output, 4);
|
||||||
|
srslte_bit_unpack(q->mcs_idx, &output, 5);
|
||||||
|
srslte_bit_unpack(q->retransmission, &output, 1);
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srslte_sci_format0_unpack(srslte_sci_t* q, uint8_t* input)
|
||||||
|
{
|
||||||
|
if (!q) {
|
||||||
|
printf("Error unpacking SCI Format 0\n");
|
||||||
|
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");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
} else {
|
||||||
|
q->riv = srslte_bit_pack(&input, (uint32_t)ceil(log2(((q->nof_prb) * (q->nof_prb + 1) / 2))));
|
||||||
|
}
|
||||||
|
q->trp_idx = srslte_bit_pack(&input, 7);
|
||||||
|
q->mcs_idx = srslte_bit_pack(&input, 5);
|
||||||
|
q->timing_advance = srslte_bit_pack(&input, 11);
|
||||||
|
q->N_sa_id = srslte_bit_pack(&input, 8);
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srslte_sci_format1_unpack(srslte_sci_t* q, uint8_t* input)
|
||||||
|
{
|
||||||
|
if (!q) {
|
||||||
|
printf("Error unpacking SCI Format 1\n");
|
||||||
|
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))));
|
||||||
|
q->time_gap = srslte_bit_pack(&input, 4);
|
||||||
|
q->mcs_idx = srslte_bit_pack(&input, 5);
|
||||||
|
q->retransmission = srslte_bit_pack(&input, 1);
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void srslte_sci_info(char* str, srslte_sci_t* q)
|
||||||
|
{
|
||||||
|
uint32_t n = snprintf(str, 20, "SCI%i: riv=%i, mcs=%i", q->format, q->riv, q->mcs_idx);
|
||||||
|
|
||||||
|
if (q->format == SRSLTE_SCI_FORMAT0) {
|
||||||
|
n = srslte_print_check(str,
|
||||||
|
SRSLTE_SCI_MSG_MAX_LEN,
|
||||||
|
n,
|
||||||
|
", trp_idx=%i, t_adv=%i, n_sa_id=%i, freqhoppflg=%s\n",
|
||||||
|
q->trp_idx,
|
||||||
|
q->timing_advance,
|
||||||
|
q->N_sa_id,
|
||||||
|
q->freq_hopping_flag ? "true" : "false");
|
||||||
|
} else if (q->format == SRSLTE_SCI_FORMAT1) {
|
||||||
|
n = srslte_print_check(str,
|
||||||
|
SRSLTE_SCI_MSG_MAX_LEN,
|
||||||
|
n,
|
||||||
|
", priority=%i, res_rsrv=%i, t_gap=%i, rtx=%i\n",
|
||||||
|
q->priority,
|
||||||
|
q->resource_reserv,
|
||||||
|
q->time_gap,
|
||||||
|
q->retransmission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void srslte_sci_free(srslte_sci_t* q)
|
||||||
|
{
|
||||||
|
if (q != NULL) {
|
||||||
|
bzero(q, sizeof(srslte_sci_t));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,319 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2019 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 <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#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/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_cp_t cp = SRSLTE_CP_NORM;
|
||||||
|
uint32_t nof_prb = 6;
|
||||||
|
bool use_standard_lte_rates = false;
|
||||||
|
srslte_sl_tm_t tm = SRSLTE_SIDELINK_TM2;
|
||||||
|
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;
|
||||||
|
|
||||||
|
srslte_filesource_t fsrc;
|
||||||
|
|
||||||
|
void usage(char* prog)
|
||||||
|
{
|
||||||
|
printf("Usage: %s [deioptxzn]\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", 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-t Sidelink transmission mode {1,2,3,4} [Default %d]\n", (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-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) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'd':
|
||||||
|
use_standard_lte_rates = true;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
file_offset = (uint32_t)strtol(argv[optind], NULL, 10);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
cp = SRSLTE_CP_EXT;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
input_file_name = argv[optind];
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
nof_prb = (int32_t)strtol(argv[optind], NULL, 10);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
switch ((int32_t)strtol(argv[optind], NULL, 10)) {
|
||||||
|
case 1:
|
||||||
|
tm = SRSLTE_SIDELINK_TM1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
tm = SRSLTE_SIDELINK_TM2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
tm = SRSLTE_SIDELINK_TM3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
tm = SRSLTE_SIDELINK_TM4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
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;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int base_init()
|
||||||
|
{
|
||||||
|
sf_n_samples = srslte_symbol_sz(nof_prb) * 15;
|
||||||
|
|
||||||
|
sf_n_re = SRSLTE_CP_NSYMB(cp) * SRSLTE_NRE * 2 * nof_prb;
|
||||||
|
|
||||||
|
sf_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_re);
|
||||||
|
if (!sf_buffer) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
equalized_sf_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_re);
|
||||||
|
if (!equalized_sf_buffer) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_samples);
|
||||||
|
if (!input_buffer) {
|
||||||
|
ERROR("Error allocating memory\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
srslte_sci_init(&sci, nof_prb, tm, size_sub_channel, num_sub_channel);
|
||||||
|
|
||||||
|
if (srslte_pscch_init(&pscch, nof_prb, tm, cp) != SRSLTE_SUCCESS) {
|
||||||
|
ERROR("Error in PSCCH init\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srslte_chest_sl_init_pscch_dmrs(&pscch_chest) != SRSLTE_SUCCESS) {
|
||||||
|
ERROR("Error in PSCCH DMRS 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);
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ERROR("Invalid input file name\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srslte_ofdm_rx_init(&fft, cp, input_buffer, sf_buffer, 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);
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void base_free()
|
||||||
|
{
|
||||||
|
srslte_filesource_free(&fsrc);
|
||||||
|
srslte_ofdm_rx_free(&fft);
|
||||||
|
|
||||||
|
srslte_sci_free(&sci);
|
||||||
|
srslte_pscch_free(&pscch);
|
||||||
|
srslte_chest_sl_free(&pscch_chest);
|
||||||
|
|
||||||
|
if (sf_buffer) {
|
||||||
|
free(sf_buffer);
|
||||||
|
}
|
||||||
|
if (equalized_sf_buffer) {
|
||||||
|
free(equalized_sf_buffer);
|
||||||
|
}
|
||||||
|
if (input_buffer) {
|
||||||
|
free(input_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
uint8_t sci_rx[SRSLTE_SCI_MAX_LEN] = {};
|
||||||
|
int ret = SRSLTE_ERROR;
|
||||||
|
|
||||||
|
parse_args(argc, argv);
|
||||||
|
srslte_use_standard_symbol_size(use_standard_lte_rates);
|
||||||
|
|
||||||
|
if (base_init()) {
|
||||||
|
ERROR("Error initializing\n");
|
||||||
|
base_free();
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t num_decoded_sci = 0;
|
||||||
|
char sci_msg[SRSLTE_SCI_MSG_MAX_LEN] = "";
|
||||||
|
|
||||||
|
int max_num_subframes = 128;
|
||||||
|
int num_subframes = 0;
|
||||||
|
int nread = 0;
|
||||||
|
|
||||||
|
if (file_offset > 0) {
|
||||||
|
printf("Offsetting file by %d samples.\n", file_offset);
|
||||||
|
srslte_filesource_seek(&fsrc, file_offset * sizeof(cf_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
nread = srslte_filesource_read(&fsrc, input_buffer, sf_n_samples);
|
||||||
|
if (nread < 0) {
|
||||||
|
fprintf(stderr, "Error reading from file\n");
|
||||||
|
return ret;
|
||||||
|
} else if (nread == 0) {
|
||||||
|
goto clean_exit;
|
||||||
|
} else if (nread < sf_n_samples) {
|
||||||
|
fprintf(stderr, "Couldn't read entire subframe. Still processing ..\n");
|
||||||
|
nread = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CFO estimation and correction
|
||||||
|
srslte_sl_cfo_est_corr_cp(input_buffer, nof_prb, cp);
|
||||||
|
srslte_ofdm_rx_sf(&fft);
|
||||||
|
|
||||||
|
if (tm == SRSLTE_SIDELINK_TM1 || tm == SRSLTE_SIDELINK_TM2) {
|
||||||
|
uint32_t prb_num = (uint32_t)ceil(nof_prb / 2);
|
||||||
|
uint32_t prb_start = 0;
|
||||||
|
uint32_t prb_end = nof_prb - 1;
|
||||||
|
uint32_t cyclic_shift = 0;
|
||||||
|
|
||||||
|
srslte_chest_sl_gen_pscch_dmrs(&pscch_chest, cyclic_shift, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSCCH Channel estimation
|
||||||
|
srslte_chest_sl_pscch_ls_estimate_equalize(
|
||||||
|
&pscch_chest, sf_buffer, pscch_prb_idx, equalized_sf_buffer, nof_prb, tm, cp);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
srslte_sci_info(sci_msg, &sci);
|
||||||
|
fprintf(stdout, "%s", sci_msg);
|
||||||
|
|
||||||
|
num_decoded_sci++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (tm == SRSLTE_SIDELINK_TM3 || tm == SRSLTE_SIDELINK_TM4) {
|
||||||
|
for (int i = 0; i < num_sub_channel; i++) {
|
||||||
|
uint32_t pscch_prb_idx = 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, tm);
|
||||||
|
srslte_chest_sl_pscch_ls_estimate_equalize(
|
||||||
|
&pscch_chest, sf_buffer, pscch_prb_idx, equalized_sf_buffer, nof_prb, tm, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
srslte_sci_info(sci_msg, &sci);
|
||||||
|
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);
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
num_subframes++;
|
||||||
|
} while (nread > 0 && num_subframes < max_num_subframes);
|
||||||
|
|
||||||
|
clean_exit:
|
||||||
|
|
||||||
|
base_free();
|
||||||
|
|
||||||
|
printf("num_decoded_sci=%d\n", num_decoded_sci);
|
||||||
|
|
||||||
|
ret = (num_decoded_sci > 0) ? SRSLTE_SUCCESS : SRSLTE_ERROR;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2019 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 <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "srslte/phy/phch/pscch.h"
|
||||||
|
#include "srslte/phy/phch/sci.h"
|
||||||
|
#include "srslte/phy/utils/debug.h"
|
||||||
|
#include "srslte/phy/utils/vector.h"
|
||||||
|
|
||||||
|
int32_t N_sl_id = 168;
|
||||||
|
uint32_t nof_prb = 6;
|
||||||
|
srslte_cp_t cp = SRSLTE_CP_NORM;
|
||||||
|
srslte_sl_tm_t tm = SRSLTE_SIDELINK_TM2;
|
||||||
|
|
||||||
|
uint32_t size_sub_channel = 10;
|
||||||
|
uint32_t num_sub_channel = 5;
|
||||||
|
|
||||||
|
uint32_t prb_idx = 0;
|
||||||
|
|
||||||
|
void usage(char* prog)
|
||||||
|
{
|
||||||
|
printf("Usage: %s [cdeipt]\n", prog);
|
||||||
|
printf("\t-p nof_prb [Default %d]\n", nof_prb);
|
||||||
|
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-v [set srslte_verbose to debug, default none]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_args(int argc, char** argv)
|
||||||
|
{
|
||||||
|
int opt;
|
||||||
|
while ((opt = getopt(argc, argv, "ceiptv")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'c':
|
||||||
|
N_sl_id = (int32_t)strtol(argv[optind], NULL, 10);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
nof_prb = (uint32_t)strtol(argv[optind], NULL, 10);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
switch (strtol(argv[optind], NULL, 10)) {
|
||||||
|
case 1:
|
||||||
|
tm = SRSLTE_SIDELINK_TM1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
tm = SRSLTE_SIDELINK_TM2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
tm = SRSLTE_SIDELINK_TM3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
tm = SRSLTE_SIDELINK_TM4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
srslte_verbose++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
int ret = SRSLTE_ERROR;
|
||||||
|
|
||||||
|
parse_args(argc, argv);
|
||||||
|
|
||||||
|
char sci_msg[SRSLTE_SCI_MSG_MAX_LEN] = "";
|
||||||
|
|
||||||
|
uint32_t sf_n_re = SRSLTE_SF_LEN_RE(nof_prb, cp);
|
||||||
|
cf_t* sf_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_re);
|
||||||
|
|
||||||
|
// SCI
|
||||||
|
srslte_sci_t sci;
|
||||||
|
srslte_sci_init(&sci, nof_prb, tm, size_sub_channel, num_sub_channel);
|
||||||
|
|
||||||
|
// PSCCH
|
||||||
|
srslte_pscch_t pscch;
|
||||||
|
if (srslte_pscch_init(&pscch, nof_prb, tm, cp) != SRSLTE_SUCCESS) {
|
||||||
|
ERROR("Error in PSCCH init\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCI message bits
|
||||||
|
uint8_t sci_tx[SRSLTE_SCI_MAX_LEN] = {};
|
||||||
|
if (sci.format == SRSLTE_SCI_FORMAT0) {
|
||||||
|
if (srslte_sci_format0_pack(&sci, sci_tx) != SRSLTE_SUCCESS) {
|
||||||
|
printf("Error packing sci format 0\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
} else if (sci.format == SRSLTE_SCI_FORMAT1) {
|
||||||
|
if (srslte_sci_format1_pack(&sci, sci_tx) != SRSLTE_SUCCESS) {
|
||||||
|
printf("Error packing sci format 1\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Tx payload: ");
|
||||||
|
srslte_vec_fprint_hex(stdout, sci_tx, sci.sci_len);
|
||||||
|
|
||||||
|
// Put SCI into PSCCH
|
||||||
|
srslte_pscch_encode(&pscch, sci_tx, sf_buffer, prb_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) {
|
||||||
|
printf("Rx payload: ");
|
||||||
|
srslte_vec_fprint_hex(stdout, sci_rx, sci.sci_len);
|
||||||
|
|
||||||
|
uint32_t riv_txed = sci.riv;
|
||||||
|
if (sci.format == SRSLTE_SCI_FORMAT0) {
|
||||||
|
if (srslte_sci_format0_unpack(&sci, sci_rx) != SRSLTE_SUCCESS) {
|
||||||
|
printf("Error unpacking sci format 0\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
} else if (sci.format == SRSLTE_SCI_FORMAT1) {
|
||||||
|
if (srslte_sci_format1_unpack(&sci, sci_rx) != SRSLTE_SUCCESS) {
|
||||||
|
printf("Error unpacking sci format 1\n");
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
srslte_sci_info(sci_msg, &sci);
|
||||||
|
fprintf(stdout, "%s", sci_msg);
|
||||||
|
if (sci.riv == riv_txed) {
|
||||||
|
ret = SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(sf_buffer);
|
||||||
|
srslte_sci_free(&sci);
|
||||||
|
srslte_pscch_free(&pscch);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue