mirror of https://github.com/PentHertz/srsLTE.git
377 lines
10 KiB
C
377 lines
10 KiB
C
/**
|
|
*
|
|
* \section COPYRIGHT
|
|
*
|
|
* Copyright 2013-2021 Software Radio Systems Limited
|
|
*
|
|
* By using this file, you agree to the terms and conditions set
|
|
* forth in the LICENSE file which can be found at the top level of
|
|
* the distribution.
|
|
*
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "srsran/phy/fec/convolutional/rm_conv.h"
|
|
#include "srsran/phy/modem/demod_soft.h"
|
|
#include "srsran/phy/modem/mod.h"
|
|
#include "srsran/phy/phch/pscch.h"
|
|
#include "srsran/phy/phch/sch.h"
|
|
#include "srsran/phy/scrambling/scrambling.h"
|
|
#include "srsran/phy/utils/bit.h"
|
|
#include "srsran/phy/utils/debug.h"
|
|
#include "srsran/phy/utils/vector.h"
|
|
|
|
int srsran_pscch_init(srsran_pscch_t* q, uint32_t max_prb)
|
|
{
|
|
int ret = SRSRAN_ERROR_INVALID_INPUTS;
|
|
|
|
if (q != NULL) {
|
|
ret = SRSRAN_ERROR;
|
|
|
|
q->max_prb = max_prb;
|
|
|
|
// CRC
|
|
uint32_t crc_poly = 0x11021;
|
|
if (srsran_crc_init(&q->crc, crc_poly, SRSRAN_SCI_CRC_LEN)) {
|
|
return SRSRAN_ERROR;
|
|
}
|
|
q->c = srsran_vec_u8_malloc(SRSRAN_SCI_MAX_LEN + SRSRAN_SCI_CRC_LEN);
|
|
if (!q->c) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
q->sci_crc = srsran_vec_u8_malloc(SRSRAN_SCI_CRC_LEN);
|
|
if (!q->sci_crc) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
|
|
// Max E value for memory allocation
|
|
uint32_t E_max = SRSRAN_NRE * SRSRAN_PSCCH_MAX_NUM_DATA_SYMBOLS * SRSRAN_PSCCH_MAX_NOF_PRB * SRSRAN_PSCCH_QM;
|
|
|
|
// 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 = srsran_vec_u8_malloc(E_max);
|
|
if (!q->d) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
srsran_vec_u8_zero(q->d, E_max);
|
|
|
|
q->d_16 = srsran_vec_i16_malloc(E_max);
|
|
if (!q->d_16) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
|
|
srsran_viterbi_init(
|
|
&q->dec, SRSRAN_VITERBI_37, q->encoder.poly, SRSRAN_SCI_MAX_LEN + SRSRAN_SCI_CRC_LEN, q->encoder.tail_biting);
|
|
|
|
q->e = srsran_vec_u8_malloc(E_max);
|
|
if (!q->e) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
q->e_16 = srsran_vec_i16_malloc(E_max);
|
|
if (!q->e_16) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
q->e_bytes = srsran_vec_u8_malloc(E_max / 8);
|
|
if (!q->e_bytes) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
|
|
q->interleaver_lut = srsran_vec_u32_malloc(E_max);
|
|
if (!q->interleaver_lut) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
|
|
q->codeword = srsran_vec_u8_malloc(E_max);
|
|
if (!q->codeword) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
q->codeword_bytes = srsran_vec_u8_malloc(E_max / 8);
|
|
if (!q->codeword_bytes) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
|
|
// Scrambling
|
|
bzero(&q->seq, sizeof(srsran_sequence_t));
|
|
srsran_sequence_LTE_pr(&q->seq, E_max, SRSRAN_PSCCH_SCRAMBLING_SEED);
|
|
|
|
// Modulation
|
|
if (srsran_modem_table_lte(&q->mod, SRSRAN_MOD_QPSK)) {
|
|
return SRSRAN_ERROR;
|
|
}
|
|
|
|
q->mod_symbols = srsran_vec_cf_malloc(E_max / SRSRAN_PSCCH_QM);
|
|
if (!q->mod_symbols) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
srsran_vec_cf_zero(q->mod_symbols, E_max / SRSRAN_PSCCH_QM);
|
|
|
|
q->llr = srsran_vec_i16_malloc(E_max);
|
|
if (!q->llr) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
|
|
// DFT Precoding
|
|
if (srsran_dft_precoding_init(&q->dft_precoder, SRSRAN_PSCCH_MAX_NOF_PRB, true)) {
|
|
return SRSRAN_ERROR;
|
|
}
|
|
q->scfdma_symbols = srsran_vec_cf_malloc(E_max / SRSRAN_PSCCH_QM);
|
|
if (!q->scfdma_symbols) {
|
|
ERROR("Error allocating memory");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
srsran_vec_cf_zero(q->scfdma_symbols, E_max / SRSRAN_PSCCH_QM);
|
|
|
|
// IDFT Predecoding
|
|
if (srsran_dft_precoding_init(&q->idft_precoder, SRSRAN_PSCCH_MAX_NOF_PRB, false)) {
|
|
return SRSRAN_ERROR;
|
|
}
|
|
|
|
ret = SRSRAN_SUCCESS;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int srsran_pscch_set_cell(srsran_pscch_t* q, srsran_cell_sl_t cell)
|
|
{
|
|
int ret = SRSRAN_ERROR_INVALID_INPUTS;
|
|
|
|
if (q != NULL && cell.nof_prb <= q->max_prb) {
|
|
ret = SRSRAN_ERROR;
|
|
|
|
if (cell.tm == SRSRAN_SIDELINK_TM1 || cell.tm == SRSRAN_SIDELINK_TM2) {
|
|
q->sci_len = srsran_sci_format0_sizeof(cell.nof_prb);
|
|
q->nof_symbols = SRSRAN_PSCCH_TM12_NUM_DATA_SYMBOLS;
|
|
q->pscch_nof_prb = SRSRAN_PSCCH_TM12_NOF_PRB;
|
|
q->E = SRSRAN_PSCCH_TM12_NOF_CODED_BITS;
|
|
|
|
if (cell.cp == SRSRAN_CP_EXT) {
|
|
q->nof_symbols = SRSRAN_PSCCH_TM12_NUM_DATA_SYMBOLS_EXT;
|
|
}
|
|
} else if (cell.tm == SRSRAN_SIDELINK_TM3 || cell.tm == SRSRAN_SIDELINK_TM4) {
|
|
q->sci_len = SRSRAN_SCI_TM34_LEN;
|
|
q->nof_symbols = SRSRAN_PSCCH_TM34_NUM_DATA_SYMBOLS;
|
|
q->pscch_nof_prb = SRSRAN_PSCCH_TM34_NOF_PRB;
|
|
q->E = SRSRAN_PSCCH_TM34_NOF_CODED_BITS;
|
|
} else {
|
|
return ret;
|
|
}
|
|
|
|
q->cell = cell;
|
|
|
|
///< Last OFDM symbol is processed but not transmitted
|
|
q->nof_tx_re = (q->nof_symbols - 1) * SRSRAN_NRE * q->pscch_nof_prb;
|
|
|
|
ret = SRSRAN_SUCCESS;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int srsran_pscch_encode(srsran_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);
|
|
|
|
// CRC Attachment
|
|
srsran_crc_attach(&q->crc, q->c, q->sci_len);
|
|
|
|
// Channel Coding
|
|
srsran_convcoder_encode(&q->encoder, q->c, q->d, q->sci_len + SRSRAN_SCI_CRC_LEN);
|
|
|
|
// Rate Matching
|
|
if (srsran_rm_conv_tx(q->d, (3 * (q->sci_len + SRSRAN_SCI_CRC_LEN)), q->e, q->E)) {
|
|
return SRSRAN_ERROR;
|
|
}
|
|
|
|
// Interleaving
|
|
srsran_bit_pack_vector(q->e, q->e_bytes, q->E);
|
|
srsran_sl_ulsch_interleave(q->e_bytes, // input bytes
|
|
SRSRAN_PSCCH_QM, // modulation
|
|
q->E / SRSRAN_PSCCH_QM, // prime number
|
|
q->nof_symbols, // nof pscch symbols
|
|
q->codeword_bytes // output
|
|
);
|
|
srsran_bit_unpack_vector(q->codeword_bytes, q->codeword, q->E);
|
|
|
|
// Scrambling
|
|
srsran_scrambling_b(&q->seq, q->codeword);
|
|
|
|
// Modulation
|
|
srsran_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
|
|
srsran_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 (srsran_pscch_put(q, sf_buffer, prb_start_idx) != q->nof_tx_re) {
|
|
printf("Error during PSCCH RE mapping\n");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
|
|
return SRSRAN_SUCCESS;
|
|
}
|
|
|
|
int srsran_pscch_decode(srsran_pscch_t* q, cf_t* equalized_sf_syms, uint8_t* sci, uint32_t prb_start_idx)
|
|
{
|
|
if (srsran_pscch_get(q, equalized_sf_syms, prb_start_idx) != q->nof_tx_re) {
|
|
printf("Error during PSCCH RE extraction\n");
|
|
return SRSRAN_ERROR;
|
|
}
|
|
|
|
// Precoding
|
|
// Void: Single antenna port
|
|
// 3GPP TS 36.211 version 15.6.0 Release 15 Sec. 9.4.5
|
|
|
|
// IDFT Precoding
|
|
srsran_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
|
|
srsran_demod_soft_demodulate_s(SRSRAN_MOD_QPSK, q->mod_symbols, q->llr, q->E / SRSRAN_PSCCH_QM);
|
|
|
|
// Descrambling
|
|
srsran_scrambling_s(&q->seq, q->llr);
|
|
|
|
// Deinterleaving
|
|
srsran_sl_ulsch_deinterleave(
|
|
q->llr, SRSRAN_PSCCH_QM, q->E / SRSRAN_PSCCH_QM, q->nof_symbols, q->e_16, q->interleaver_lut);
|
|
|
|
// Rate matching
|
|
srsran_rm_conv_rx_s(q->e_16, q->E, q->d_16, (3 * (q->sci_len + SRSRAN_SCI_CRC_LEN)));
|
|
|
|
// Channel decoding
|
|
srsran_viterbi_decode_s(&q->dec, q->d_16, q->c, q->sci_len + SRSRAN_SCI_CRC_LEN);
|
|
|
|
// Copy received crc
|
|
memcpy(q->sci_crc, &q->c[q->sci_len], sizeof(uint8_t) * SRSRAN_SCI_CRC_LEN);
|
|
|
|
// Re-attach crc
|
|
srsran_crc_attach(&q->crc, q->c, q->sci_len);
|
|
|
|
// CRC check
|
|
if (srsran_bit_diff(q->sci_crc, &q->c[q->sci_len], SRSRAN_SCI_CRC_LEN) != 0) {
|
|
return SRSRAN_ERROR;
|
|
}
|
|
|
|
// Remove CRC and copy content to sci buffer
|
|
memcpy(sci, q->c, sizeof(uint8_t) * q->sci_len);
|
|
|
|
return SRSRAN_SUCCESS;
|
|
}
|
|
|
|
int srsran_pscch_put(srsran_pscch_t* q, cf_t* sf_buffer, uint32_t prb_start_idx)
|
|
{
|
|
int sample_pos = 0;
|
|
int k = prb_start_idx * SRSRAN_NRE;
|
|
for (int i = 0; i < srsran_sl_get_num_symbols(q->cell.tm, q->cell.cp); ++i) {
|
|
if (srsran_pscch_is_symbol(SRSRAN_SIDELINK_DATA_SYMBOL, q->cell.tm, i, q->cell.cp)) {
|
|
memcpy(&sf_buffer[k + i * q->cell.nof_prb * SRSRAN_NRE],
|
|
&q->scfdma_symbols[sample_pos],
|
|
sizeof(cf_t) * (SRSRAN_NRE * q->pscch_nof_prb));
|
|
sample_pos += (SRSRAN_NRE * q->pscch_nof_prb);
|
|
}
|
|
}
|
|
return sample_pos;
|
|
}
|
|
|
|
int srsran_pscch_get(srsran_pscch_t* q, cf_t* sf_buffer, uint32_t prb_start_idx)
|
|
{
|
|
int sample_pos = 0;
|
|
int k = prb_start_idx * SRSRAN_NRE;
|
|
for (int i = 0; i < srsran_sl_get_num_symbols(q->cell.tm, q->cell.cp); ++i) {
|
|
if (srsran_pscch_is_symbol(SRSRAN_SIDELINK_DATA_SYMBOL, q->cell.tm, i, q->cell.cp)) {
|
|
memcpy(&q->scfdma_symbols[sample_pos],
|
|
&sf_buffer[k + i * q->cell.nof_prb * SRSRAN_NRE],
|
|
sizeof(cf_t) * (SRSRAN_NRE * q->pscch_nof_prb));
|
|
sample_pos += (SRSRAN_NRE * q->pscch_nof_prb);
|
|
}
|
|
}
|
|
|
|
// Force zeros in last symbol
|
|
srsran_vec_cf_zero(&q->scfdma_symbols[sample_pos], SRSRAN_NRE * q->pscch_nof_prb);
|
|
|
|
return sample_pos;
|
|
}
|
|
|
|
void srsran_pscch_free(srsran_pscch_t* q)
|
|
{
|
|
if (q != NULL) {
|
|
srsran_dft_precoding_free(&q->dft_precoder);
|
|
srsran_dft_precoding_free(&q->idft_precoder);
|
|
srsran_viterbi_free(&q->dec);
|
|
srsran_sequence_free(&q->seq);
|
|
srsran_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(srsran_pscch_t));
|
|
}
|
|
}
|