Initial NR-MIB packing/unpacking

master
Xavier Arteaga 3 years ago committed by Xavier Arteaga
parent 26cc6d7886
commit cdfbe28b69

@ -357,6 +357,14 @@ typedef enum SRSRAN_API {
SRSRAN_DUPLEX_MODE_INVALID SRSRAN_DUPLEX_MODE_INVALID
} srsran_duplex_mode_t; } srsran_duplex_mode_t;
/**
* @brief Determines whether the first DMRS goes into symbol index 2 or 3
*/
typedef enum {
srsran_dmrs_sch_typeA_pos_2 = 0, // Start in slot symbol index 2 (default)
srsran_dmrs_sch_typeA_pos_3 // Start in slot symbol index 3
} srsran_dmrs_sch_typeA_pos_t;
/** /**
* @brief NR carrier parameters. It is a combination of fixed cell and bandwidth-part (BWP) * @brief NR carrier parameters. It is a combination of fixed cell and bandwidth-part (BWP)
*/ */

@ -0,0 +1,62 @@
/**
*
* \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.
*
*/
#ifndef SRSRAN_PBCH_MSG_NR_H
#define SRSRAN_PBCH_MSG_NR_H
#include "srsran/config.h"
#include "srsran/phy/common/phy_common_nr.h"
#include <stdbool.h>
#include <stdint.h>
/**
* @brief NR PBCH payload size generated by higher layers, deduced from TS 38.331 MIB description
*/
#define SRSRAN_PBCH_MSG_NR_SZ 24
/**
* @brief Describes the NR PBCH message
*/
typedef struct SRSRAN_API {
uint8_t payload[SRSRAN_PBCH_MSG_NR_SZ]; ///< Actual PBCH payload provided by higher layers
uint8_t sfn_4lsb; ///< SFN 4 LSB
uint8_t ssb_idx; ///< SS/PBCH blocks index described in TS 38.213 4.1
uint8_t k_ssb_msb; ///< Subcarrier offset MSB described in TS 38.211 7.4.3.1
bool hrf; ///< Half Radio Frame bit
bool crc; ///< Decoder only, it is true only if the received CRC matches
} srsran_pbch_msg_nr_t;
typedef struct SRSRAN_API {
uint32_t sfn; ///< System frame number
uint8_t ssb_idx; ///< SS/PBCH blocks index described in TS 38.213 4.1
bool hrf; ///< Half Radio Frame bit
srsran_subcarrier_spacing_t scs_common; ///< Subcarrier spacing common
uint32_t ssb_offset; ///< SSB subcarrier offset
srsran_dmrs_sch_typeA_pos_t dmrs_typeA_pos; ///< DMRS typeA position
uint32_t coreset0_idx; ///< CORESET Zero configuration index (0-15)
uint32_t ss0_idx; ///< SearchSpace Zero configuration index (0-15)
bool cell_barred; ///< Set to true if the cell is barred
bool intra_freq_reselection; ///< Set to true if allowed
uint32_t spare; ///< Unused bits
} srsran_mib_nr_t;
SRSRAN_API bool srsran_pbch_msg_nr_is_mib(const srsran_pbch_msg_nr_t* msg);
SRSRAN_API int srsran_pbch_msg_nr_mib_pack(const srsran_mib_nr_t* mib, srsran_pbch_msg_nr_t* msg);
SRSRAN_API int srsran_pbch_msg_nr_mib_unpack(const srsran_pbch_msg_nr_t* pbch_msg, srsran_mib_nr_t* mib);
SRSRAN_API uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len);
SRSRAN_API uint32_t srsran_pbch_msg_nr_mib_info(const srsran_mib_nr_t* mib, char* str, uint32_t str_len);
#endif // SRSRAN_PBCH_MSG_NR_H

@ -20,11 +20,7 @@
#include "srsran/phy/fec/polar/polar_encoder.h" #include "srsran/phy/fec/polar/polar_encoder.h"
#include "srsran/phy/fec/polar/polar_rm.h" #include "srsran/phy/fec/polar/polar_rm.h"
#include "srsran/phy/modem/modem_table.h" #include "srsran/phy/modem/modem_table.h"
#include "srsran/phy/phch/pbch_msg_nr.h"
/**
* @brief NR PBCH payload size generated by higher layers, deduced from TS 38.331 MIB description
*/
#define SRSRAN_PBCH_NR_PAYLOAD_SZ 24
/** /**
* @brief Describes the NR PBCH object initialisation arguments * @brief Describes the NR PBCH object initialisation arguments
@ -59,18 +55,6 @@ typedef struct SRSRAN_API {
srsran_modem_table_t qpsk; srsran_modem_table_t qpsk;
} srsran_pbch_nr_t; } srsran_pbch_nr_t;
/**
* @brief Describes the PBCH message
*/
typedef struct SRSRAN_API {
uint8_t payload[SRSRAN_PBCH_NR_PAYLOAD_SZ]; ///< Actual PBCH payload provided by higher layers
uint8_t sfn_4lsb; ///< SFN 4 LSB
uint8_t ssb_idx; ///< SS/PBCH blocks index described in TS 38.213 4.1
uint8_t k_ssb_msb; ///< Subcarrier offset MSB described in TS 38.211 7.4.3.1
bool hrf; ///< Half Radio Frame bit
bool crc; ///< Decoder only, it is true only if the received CRC matches
} srsran_pbch_msg_nr_t;
/** /**
* @brief Initialises an NR PBCH object with the provided arguments * @brief Initialises an NR PBCH object with the provided arguments
* @param q NR PBCH object * @param q NR PBCH object
@ -112,6 +96,4 @@ SRSRAN_API int srsran_pbch_nr_decode(srsran_pbch_nr_t* q,
const cf_t ce[SRSRAN_SSB_NOF_RE], const cf_t ce[SRSRAN_SSB_NOF_RE],
srsran_pbch_msg_nr_t* msg); srsran_pbch_msg_nr_t* msg);
SRSRAN_API uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len);
#endif // SRSRAN_PBCH_NR_H #endif // SRSRAN_PBCH_NR_H

@ -49,14 +49,6 @@ typedef enum {
srsran_dmrs_sch_len_2 // double, 2 symbol long srsran_dmrs_sch_len_2 // double, 2 symbol long
} srsran_dmrs_sch_len_t; } srsran_dmrs_sch_len_t;
/**
* @brief Determines whether the first pilot goes into symbol index 2 or 3
*/
typedef enum {
srsran_dmrs_sch_typeA_pos_2 = 0, // Start in slot symbol index 2 (default)
srsran_dmrs_sch_typeA_pos_3 // Start in slot symbol index 3
} srsran_dmrs_sch_typeA_pos_t;
/** /**
* @brief Determines additional symbols if possible to be added * @brief Determines additional symbols if possible to be added
*/ */

@ -0,0 +1,179 @@
/**
*
* \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 "srsran/phy/phch/pbch_msg_nr.h"
#include "srsran/phy/utils/bit.h"
#include "srsran/phy/utils/vector.h"
static bool pbch_msg_nr_is_mib(const srsran_pbch_msg_nr_t* msg)
{
return msg->payload[0] == 0;
}
bool srsran_pbch_msg_nr_is_mib(const srsran_pbch_msg_nr_t* msg)
{
if (msg == NULL) {
return false;
}
return pbch_msg_nr_is_mib(msg);
}
int srsran_pbch_msg_nr_mib_pack(const srsran_mib_nr_t* mib, srsran_pbch_msg_nr_t* pbch_msg)
{
if (mib == NULL || pbch_msg == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
// Copy PBCH message context
pbch_msg->sfn_4lsb = mib->sfn & 0b1111;
pbch_msg->ssb_idx = mib->ssb_idx;
pbch_msg->k_ssb_msb = mib->ssb_offset >> 4U;
pbch_msg->hrf = mib->hrf;
// Pack MIB payload
uint8_t* y = pbch_msg->payload;
// MIB - 1 bit
*(y++) = 0;
// systemFrameNumber - 6 bits MSB
srsran_bit_unpack(mib->sfn >> 4U, &y, 6);
// subCarrierSpacingCommon - 1 bit
*(y++) = (mib->scs_common == srsran_subcarrier_spacing_15kHz || mib->scs_common == srsran_subcarrier_spacing_60kHz)
? 0
: 1;
// ssb-SubcarrierOffset - 4 bits
srsran_bit_unpack(mib->ssb_offset, &y, 4);
// dmrs-TypeA-Position - 1 bit
*(y++) = (mib->dmrs_typeA_pos == srsran_dmrs_sch_typeA_pos_2) ? 0 : 1;
// pdcch-ConfigSIB1
// controlResourceSetZero - 4 bits
srsran_bit_unpack(mib->coreset0_idx, &y, 4);
// searchSpaceZero - 4 bits
srsran_bit_unpack(mib->ss0_idx, &y, 4);
// Barred - 1 bit
*(y++) = (mib->cell_barred) ? 0 : 1;
// intraFreqReselection - 1 bit
*(y++) = (mib->intra_freq_reselection) ? 0 : 1;
// Spare - 1 bit
srsran_bit_unpack(mib->spare, &y, 1);
return SRSRAN_SUCCESS;
}
int srsran_pbch_msg_nr_mib_unpack(const srsran_pbch_msg_nr_t* pbch_msg, srsran_mib_nr_t* mib)
{
if (mib == NULL || pbch_msg == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
// Copy PBCH message context
mib->sfn = pbch_msg->sfn_4lsb;
mib->ssb_idx = pbch_msg->ssb_idx;
mib->hrf = pbch_msg->hrf;
mib->ssb_offset = pbch_msg->k_ssb_msb << 4U;
// Pack MIB payload
uint8_t* y = (uint8_t*)pbch_msg->payload;
// MIB - 1 bit
if (!pbch_msg_nr_is_mib(pbch_msg)) {
return SRSRAN_ERROR;
}
y++;
// systemFrameNumber - 6 bits MSB
mib->sfn |= srsran_bit_pack(&y, 6) << 4U;
// subCarrierSpacingCommon - 1 bit
mib->scs_common = *(y++) == 0 ? srsran_subcarrier_spacing_15kHz : srsran_subcarrier_spacing_30kHz;
// ssb-SubcarrierOffset - 4 bits
mib->ssb_offset |= srsran_bit_pack(&y, 4);
// dmrs-TypeA-Position - 1 bit
mib->dmrs_typeA_pos = *(y++) == 0 ? srsran_dmrs_sch_typeA_pos_2 : srsran_dmrs_sch_typeA_pos_3;
// pdcch-ConfigSIB1
// controlResourceSetZero - 4 bits
mib->coreset0_idx = srsran_bit_pack(&y, 4);
// searchSpaceZero - 4 bits
mib->ss0_idx = srsran_bit_pack(&y, 4);
// Barred - 1 bit
mib->cell_barred = (*(y++) == 0);
// intraFreqReselection - 1 bit
mib->intra_freq_reselection = (*(y++) == 0);
// Spare - 1 bit
mib->spare = srsran_bit_pack(&y, 1);
return SRSRAN_SUCCESS;
}
uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len)
{
if (msg == NULL || str == NULL || str_len == 0) {
return 0;
}
uint32_t len = 0;
len = srsran_print_check(str, str_len, len, "payload=");
len += srsran_vec_sprint_hex(&str[len], str_len - len, (uint8_t*)msg->payload, SRSRAN_PBCH_MSG_NR_SZ);
len = srsran_print_check(str,
str_len,
len,
" sfn_lsb=%d ssb_idx=%d k_ssb_msb=%d hrf=%d ",
msg->sfn_4lsb,
msg->ssb_idx,
msg->k_ssb_msb,
msg->hrf);
return len;
}
uint32_t srsran_pbch_msg_nr_mib_info(const srsran_mib_nr_t* mib, char* str, uint32_t str_len)
{
uint32_t len = 0;
len = srsran_print_check(str,
str_len,
len,
"sfn=%d ssb_idx=%d hrf=%c scs=%d ssb_offset=%d dmrs_typeA_pos=%s coreset0=%d ss0=%d "
"barred=%c intra_freq_reselection=%c spare=%d",
mib->sfn,
mib->ssb_idx,
mib->hrf ? 'y' : 'n',
SRSRAN_SUBC_SPACING_NR(mib->scs_common) / 1000,
mib->ssb_offset,
mib->dmrs_typeA_pos == srsran_dmrs_sch_typeA_pos_2 ? "pos2" : "pos3",
mib->coreset0_idx,
mib->ss0_idx,
mib->cell_barred ? 'y' : 'n',
mib->intra_freq_reselection ? 'y' : 'n',
mib->spare);
return len;
}

@ -43,7 +43,7 @@
/* /*
* Number of generated payload bits, called A * Number of generated payload bits, called A
*/ */
#define PBCH_NR_A (SRSRAN_PBCH_NR_PAYLOAD_SZ + 8) #define PBCH_NR_A (SRSRAN_PBCH_MSG_NR_SZ + 8)
/* /*
* Number of payload bits plus CRC * Number of payload bits plus CRC
@ -184,7 +184,7 @@ static void
pbch_nr_pbch_msg_pack(const srsran_pbch_nr_cfg_t* cfg, const srsran_pbch_msg_nr_t* msg, uint8_t a[PBCH_NR_A]) pbch_nr_pbch_msg_pack(const srsran_pbch_nr_cfg_t* cfg, const srsran_pbch_msg_nr_t* msg, uint8_t a[PBCH_NR_A])
{ {
// Extract actual payload size // Extract actual payload size
uint32_t A_hat = SRSRAN_PBCH_NR_PAYLOAD_SZ; uint32_t A_hat = SRSRAN_PBCH_MSG_NR_SZ;
// Put SFN in a_hat[A_hat] to a_hat[A_hat + 3] // Put SFN in a_hat[A_hat] to a_hat[A_hat + 3]
uint32_t j_sfn = 0; uint32_t j_sfn = 0;
@ -231,7 +231,7 @@ pbch_nr_pbch_msg_unpack(const srsran_pbch_nr_cfg_t* cfg, const uint8_t a[PBCH_NR
} }
// Extract actual payload size // Extract actual payload size
uint32_t A_hat = SRSRAN_PBCH_NR_PAYLOAD_SZ; uint32_t A_hat = SRSRAN_PBCH_MSG_NR_SZ;
// Put SFN in a_hat[A_hat] to a_hat[A_hat + 3] // Put SFN in a_hat[A_hat] to a_hat[A_hat + 3]
uint32_t j_sfn = 0; uint32_t j_sfn = 0;
@ -651,27 +651,3 @@ int srsran_pbch_nr_decode(srsran_pbch_nr_t* q,
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len)
{
if (msg == NULL || str == NULL || str_len == 0) {
return 0;
}
uint32_t len = 0;
len = srsran_print_check(str, str_len, len, "payload=");
len += srsran_vec_sprint_hex(&str[len], str_len - len, (uint8_t*)msg->payload, SRSRAN_PBCH_NR_PAYLOAD_SZ);
len = srsran_print_check(str,
str_len,
len,
" sfn_lsb=%d ssb_idx=%d k_ssb_msb=%d hrf=%d ",
msg->sfn_4lsb,
msg->ssb_idx,
msg->k_ssb_msb,
msg->hrf);
return len;
}

@ -627,6 +627,10 @@ add_executable(dci_nr_test dci_nr_test.c)
target_link_libraries(dci_nr_test srsran_phy) target_link_libraries(dci_nr_test srsran_phy)
add_nr_test(dci_nr_test dci_nr_test) add_nr_test(dci_nr_test dci_nr_test)
add_executable(mib_nr_test mib_nr_test.c)
target_link_libraries(mib_nr_test srsran_phy)
add_nr_test(mib_nr_test mib_nr_test)
add_executable(pucch_nr_test pucch_nr_test.c) add_executable(pucch_nr_test pucch_nr_test.c)
target_link_libraries(pucch_nr_test srsran_phy) target_link_libraries(pucch_nr_test srsran_phy)
add_nr_test(pucch_nr_test pucch_nr_test) add_nr_test(pucch_nr_test pucch_nr_test)

@ -0,0 +1,109 @@
/**
*
* \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 "srsran/phy/phch/pbch_msg_nr.h"
#include "srsran/phy/utils/debug.h"
#include "srsran/phy/utils/random.h"
#include "srsran/support/srsran_test.h"
#include <getopt.h>
#include <string.h>
static uint32_t nof_repetitions = 16;
static srsran_random_t random_gen = NULL;
static int test_packing_unpacking()
{
for (uint32_t r = 0; r < nof_repetitions; r++) {
srsran_mib_nr_t mib = {};
mib.sfn = srsran_random_uniform_int_dist(random_gen, 0, 1023);
mib.ssb_idx = srsran_random_uniform_int_dist(random_gen, 0, 127);
mib.hrf = srsran_random_bool(random_gen, 0.5f);
mib.scs_common =
srsran_random_bool(random_gen, 0.5f) ? srsran_subcarrier_spacing_15kHz : srsran_subcarrier_spacing_30kHz;
mib.ssb_offset = srsran_random_uniform_int_dist(random_gen, 0, 31);
mib.dmrs_typeA_pos =
srsran_random_bool(random_gen, 0.5f) ? srsran_dmrs_sch_typeA_pos_2 : srsran_dmrs_sch_typeA_pos_3;
mib.coreset0_idx = srsran_random_uniform_int_dist(random_gen, 0, 15);
mib.ss0_idx = srsran_random_uniform_int_dist(random_gen, 0, 15);
mib.cell_barred = srsran_random_bool(random_gen, 0.5f);
mib.intra_freq_reselection = srsran_random_bool(random_gen, 0.5f);
mib.spare = srsran_random_uniform_int_dist(random_gen, 0, 1);
srsran_pbch_msg_nr_t pbch_msg = {};
TESTASSERT(srsran_pbch_msg_nr_mib_pack(&mib, &pbch_msg) == SRSRAN_SUCCESS);
TESTASSERT(srsran_pbch_msg_nr_is_mib(&pbch_msg));
srsran_mib_nr_t mib2 = {};
TESTASSERT(srsran_pbch_msg_nr_mib_unpack(&pbch_msg, &mib2) == SRSRAN_SUCCESS);
char str1[256];
char str2[256];
char strp[256];
srsran_pbch_msg_nr_mib_info(&mib, str1, (uint32_t)sizeof(str1));
srsran_pbch_msg_nr_mib_info(&mib2, str2, (uint32_t)sizeof(str2));
srsran_pbch_msg_info(&pbch_msg, strp, (uint32_t)sizeof(strp));
if (memcmp(&mib, &mib2, sizeof(srsran_mib_nr_t)) != 0) {
ERROR("Failed packing/unpacking MIB");
printf(" Source: %s\n", str1);
printf("Unpacked: %s\n", str2);
printf(" Packed: %s\n", strp);
return SRSRAN_ERROR;
}
}
return SRSRAN_SUCCESS;
}
static void usage(char* prog)
{
printf("Usage: %s [cpndv]\n", prog);
printf("\t-v Increase verbose [default none]\n");
printf("\t-R Set number of Packing/Unpacking [default %d]\n", nof_repetitions);
}
static void parse_args(int argc, char** argv)
{
int opt;
while ((opt = getopt(argc, argv, "vR")) != -1) {
switch (opt) {
case 'v':
srsran_verbose++;
break;
case 'R':
nof_repetitions = (uint32_t)strtol(argv[optind], NULL, 10);
break;
default:
usage(argv[0]);
exit(-1);
}
}
}
int main(int argc, char** argv)
{
parse_args(argc, argv);
int ret = SRSRAN_ERROR;
random_gen = srsran_random_init(1234);
if (test_packing_unpacking() < SRSRAN_SUCCESS) {
goto clean_exit;
}
ret = SRSRAN_SUCCESS;
clean_exit:
srsran_random_free(random_gen);
return ret;
}

@ -82,7 +82,7 @@ static void gen_pbch_msg(srsran_pbch_msg_nr_t* pbch_msg, uint32_t ssb_idx)
SRSRAN_MEM_ZERO(pbch_msg, srsran_pbch_msg_nr_t, 1); SRSRAN_MEM_ZERO(pbch_msg, srsran_pbch_msg_nr_t, 1);
// Generate payload // Generate payload
srsran_random_bit_vector(random_gen, pbch_msg->payload, SRSRAN_PBCH_NR_PAYLOAD_SZ); srsran_random_bit_vector(random_gen, pbch_msg->payload, SRSRAN_PBCH_MSG_NR_SZ);
pbch_msg->ssb_idx = ssb_idx; pbch_msg->ssb_idx = ssb_idx;
pbch_msg->crc = true; pbch_msg->crc = true;

Loading…
Cancel
Save