diff --git a/lib/src/phy/phch/pbch_nr.c b/lib/src/phy/phch/pbch_nr.c index e91145ac8..a96cea33b 100644 --- a/lib/src/phy/phch/pbch_nr.c +++ b/lib/src/phy/phch/pbch_nr.c @@ -180,18 +180,33 @@ void srsran_pbch_nr_free(srsran_pbch_nr_t* q) static const uint32_t G[PBCH_NR_A] = {16, 23, 18, 17, 8, 30, 10, 6, 24, 7, 0, 5, 3, 2, 1, 4, 9, 11, 12, 13, 14, 15, 19, 20, 21, 22, 25, 26, 27, 28, 29, 31}; +#define PBCH_SFN_PAYLOAD_BEGIN 1 +#define PBCH_SFN_PAYLOAD_LENGTH 6 +#define PBCH_SFN_2ND_LSB_G (G[PBCH_SFN_PAYLOAD_LENGTH + 2]) +#define PBCH_SFN_3RD_LSB_G (G[PBCH_SFN_PAYLOAD_LENGTH + 1]) + 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]) { // Extract actual payload size uint32_t A_hat = SRSRAN_PBCH_MSG_NR_SZ; + // Put actual payload + uint32_t j_sfn = 0; + uint32_t j_other = 14; + for (uint32_t i = 0; i < A_hat; i++) { + if (i >= PBCH_SFN_PAYLOAD_BEGIN && i < (PBCH_SFN_PAYLOAD_BEGIN + PBCH_SFN_PAYLOAD_LENGTH)) { + a[G[j_sfn++]] = msg->payload[i]; + } else { + a[G[j_other++]] = msg->payload[i]; + } + } + // Put SFN in a_hat[A_hat] to a_hat[A_hat + 3] - uint32_t j_sfn = 0; - a[G[j_sfn++]] = (uint8_t)((msg->sfn_4lsb >> 3U) & 1U); // 4th LSB of SFN - a[G[j_sfn++]] = (uint8_t)((msg->sfn_4lsb >> 2U) & 1U); // 3th LSB of SFN - a[G[j_sfn++]] = (uint8_t)((msg->sfn_4lsb >> 1U) & 1U); // 2th LSB of SFN - a[G[j_sfn++]] = (uint8_t)((msg->sfn_4lsb >> 0U) & 1U); // 1th LSB of SFN + a[G[j_sfn++]] = (uint8_t)((msg->sfn_4lsb >> 3U) & 1U); // 4th LSB of SFN + a[G[j_sfn++]] = (uint8_t)((msg->sfn_4lsb >> 2U) & 1U); // 3th LSB of SFN + a[G[j_sfn++]] = (uint8_t)((msg->sfn_4lsb >> 1U) & 1U); // 2th LSB of SFN + a[G[j_sfn++]] = (uint8_t)((msg->sfn_4lsb >> 0U) & 1U); // 1th LSB of SFN // Put HRF in a_hat[A_hat + 4] a[G[10]] = (msg->hrf ? 1 : 0); @@ -207,16 +222,6 @@ pbch_nr_pbch_msg_pack(const srsran_pbch_nr_cfg_t* cfg, const srsran_pbch_msg_nr_ a[G[13]] = 0; // Reserved } - // Put actual payload - uint32_t j_other = 14; - for (uint32_t i = 0; i < A_hat; i++) { - if (i > 0 && i < 7) { - a[G[j_sfn++]] = msg->payload[i]; - } else { - a[G[j_other++]] = msg->payload[i]; - } - } - if (srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) { PBCH_NR_DEBUG_TX("Packed PBCH bits: "); srsran_vec_fprint_byte(stdout, a, PBCH_NR_A); @@ -233,9 +238,19 @@ pbch_nr_pbch_msg_unpack(const srsran_pbch_nr_cfg_t* cfg, const uint8_t a[PBCH_NR // Extract actual payload size uint32_t A_hat = SRSRAN_PBCH_MSG_NR_SZ; + // Get actual payload + uint32_t j_sfn = 0; + uint32_t j_other = 14; + for (uint32_t i = 0; i < A_hat; i++) { + if (i >= PBCH_SFN_PAYLOAD_BEGIN && i < (PBCH_SFN_PAYLOAD_BEGIN + PBCH_SFN_PAYLOAD_LENGTH)) { + msg->payload[i] = a[G[j_sfn++]]; + } else { + msg->payload[i] = a[G[j_other++]]; + } + } + // Put SFN in a_hat[A_hat] to a_hat[A_hat + 3] - uint32_t j_sfn = 0; - msg->sfn_4lsb = 0; + msg->sfn_4lsb = 0; msg->sfn_4lsb |= (uint8_t)(a[G[j_sfn++]] << 3U); // 4th LSB of SFN msg->sfn_4lsb |= (uint8_t)(a[G[j_sfn++]] << 2U); // 3th LSB of SFN msg->sfn_4lsb |= (uint8_t)(a[G[j_sfn++]] << 1U); // 2th LSB of SFN @@ -254,16 +269,6 @@ pbch_nr_pbch_msg_unpack(const srsran_pbch_nr_cfg_t* cfg, const uint8_t a[PBCH_NR } else { msg->k_ssb_msb = a[G[11]]; } - - // Put actual payload - uint32_t j_other = 14; - for (uint32_t i = 0; i < A_hat; i++) { - if (i > 0 && i < 7) { - msg->payload[i] = a[G[j_sfn++]]; - } else { - msg->payload[i] = a[G[j_other++]]; - } - } } static void pbch_nr_scramble(const srsran_pbch_nr_cfg_t* cfg, const uint8_t a[PBCH_NR_A], uint8_t a_prime[PBCH_NR_A]) @@ -282,7 +287,7 @@ static void pbch_nr_scramble(const srsran_pbch_nr_cfg_t* cfg, const uint8_t a[PB } // Select value v - uint32_t v = 2 * a[G[1]] + a[G[2]]; + uint32_t v = 2 * a[PBCH_SFN_3RD_LSB_G] + a[PBCH_SFN_2ND_LSB_G]; // Advance sequence srsran_sequence_state_advance(&sequence_state, M * v); @@ -292,12 +297,14 @@ static void pbch_nr_scramble(const srsran_pbch_nr_cfg_t* cfg, const uint8_t a[PB srsran_sequence_state_apply_bit(&sequence_state, c, c, PBCH_NR_A); while (i < PBCH_NR_A) { - // a i corresponds to any one of the bits belonging to the SS/PBCH block index, the half frame index, and 2 nd and 3 - // rd least significant bits of the system frame number uint8_t s_i = c[j]; - // else - if (i == G[11] || i == G[12] || i == G[13] || i == G[10] || i == G[1] || i == G[2]) { + // Check if i belongs to a SS/PBCH block index which is only multiplexed when L_max is 64 + bool is_ssb_idx = (i == G[11] || i == G[12] || i == G[13]) && cfg->Lmax == 64; + + // a i corresponds to any one of the bits belonging to the SS/PBCH block index, the half frame index, and 2 nd and 3 + // rd least significant bits of the system frame number + if (is_ssb_idx || i == G[10] || i == PBCH_SFN_2ND_LSB_G || i == PBCH_SFN_3RD_LSB_G) { s_i = 0; } else { j++; diff --git a/lib/src/phy/sync/test/CMakeLists.txt b/lib/src/phy/sync/test/CMakeLists.txt index b0c63a635..6878da0db 100644 --- a/lib/src/phy/sync/test/CMakeLists.txt +++ b/lib/src/phy/sync/test/CMakeLists.txt @@ -150,4 +150,4 @@ target_link_libraries(ssb_file_test srsran_phy) # File test 1 # Captured with command: lib/examples/usrp_capture -a type=x300,clock=external,sampling_rate=46.08e6,rx_subdev_spec=B:0 -g 20 -r 46.08e6 -n 460800 -f 3502.8e6 -o /tmp/n78.fo35028.fs2304M.data -add_nr_test(ssb_file_test ssb_file_test -i ${CMAKE_CURRENT_SOURCE_DIR}/n78.fo35028.fs4608M.data -v -r 46.08e6 -f 3502.8e6 -F 3512.64e6 -n 460800 -A 500 357802 5 0 0 0) +add_nr_test(ssb_file_test ssb_file_test -i ${CMAKE_CURRENT_SOURCE_DIR}/n78.fo35028.fs4608M.data -v -r 46.08e6 -f 3502.8e6 -F 3512.64e6 -n 460800 -A 500 357802 2 0 1 0) diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 1abf645d4..74a745d1e 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -43,6 +43,7 @@ cc_worker::cc_worker(uint32_t cc_idx_, srslog::basic_logger& log, state& phy_sta srsran_ssb_args_t ssb_args = {}; ssb_args.enable_measure = true; + ssb_args.enable_decode = true; if (srsran_ssb_init(&ssb, &ssb_args) < SRSRAN_SUCCESS) { ERROR("Error initiating SSB"); return; @@ -381,6 +382,37 @@ bool cc_worker::measure_csi() logger.debug("SSB-CSI: %s", str.data()); } + bool hrf = (dl_slot_cfg.idx % SRSRAN_NSLOTS_PER_FRAME_NR(phy.cfg.carrier.scs) > + SRSRAN_NSLOTS_PER_FRAME_NR(phy.cfg.carrier.scs) / 2); + srsran_pbch_msg_nr_t pbch_msg = {}; + if (srsran_ssb_decode_pbch(&ssb, phy.cfg.carrier.pci, hrf, ssb_idx, rx_buffer[0], &pbch_msg) < SRSRAN_SUCCESS) { + logger.error("Error decoding PBCH"); + return false; + } + + // Check if PBCH message was decoded + if (pbch_msg.crc) { + // Unpack MIB + srsran_mib_nr_t mib = {}; + if (srsran_pbch_msg_nr_mib_unpack(&pbch_msg, &mib) < SRSRAN_SUCCESS) { + logger.error("Error unpacking PBCH-MIB"); + return false; + } + + // Check if the SFN matches + // ... + + // Log MIB information + if (logger.debug.enabled()) { + std::array str = {}; + srsran_pbch_msg_nr_mib_info(&mib, str.data(), (uint32_t)str.size()); + logger.debug("PBCH-MIB: sfn_4lsb=%d; %s", (dl_slot_cfg.idx / 10) & 0xf, str.data()); + } + } else { + // CRC shall never fail if the UE is in sync + logger.warning("PBCH-MIB: CRC failed"); + } + // Report SSB candidate channel measurement to the PHY state phy.new_csi_trs_measurement(meas); }