240 lines
9.1 KiB
C
240 lines
9.1 KiB
C
/*
|
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
|
|
* except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.openairinterface.org/?page_id=698
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*-------------------------------------------------------------------------------
|
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
* contact@openairinterface.org
|
|
*/
|
|
|
|
#include "PHY/defs_nr_UE.h"
|
|
#include "PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h"
|
|
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
|
#include "common/utils/LOG/log.h"
|
|
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
|
|
|
// #define DEBUG_PSBCH
|
|
|
|
static void nr_psbch_extract(uint32_t rxdataF_sz,
|
|
c16_t rxdataF[][rxdataF_sz],
|
|
int estimateSz,
|
|
struct complex16 dl_ch_estimates[][estimateSz],
|
|
struct complex16 rxdataF_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
|
struct complex16 dl_ch_estimates_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
|
uint32_t symbol,
|
|
NR_DL_FRAME_PARMS *frame_params)
|
|
{
|
|
uint16_t rb;
|
|
uint8_t i, j, aarx;
|
|
struct complex16 *dl_ch0, *dl_ch0_ext, *rxF, *rxF_ext;
|
|
const uint8_t nb_rb = SL_NR_NUM_PSBCH_RBS_IN_ONE_SYMBOL;
|
|
|
|
AssertFatal((symbol == 0 || symbol >= 5), "SIDELINK: PSBCH DMRS not contained in symbol %d \n", symbol);
|
|
|
|
for (aarx = 0; aarx < frame_params->nb_antennas_rx; aarx++) {
|
|
unsigned int rx_offset = frame_params->first_carrier_offset + frame_params->ssb_start_subcarrier;
|
|
rx_offset = rx_offset % frame_params->ofdm_symbol_size;
|
|
|
|
rxF = &rxdataF[aarx][symbol * frame_params->ofdm_symbol_size];
|
|
rxF_ext = &rxdataF_ext[aarx][0];
|
|
|
|
dl_ch0 = &dl_ch_estimates[aarx][symbol * frame_params->ofdm_symbol_size];
|
|
dl_ch0_ext = &dl_ch_estimates_ext[aarx][0];
|
|
|
|
#ifdef DEBUG_PSBCH
|
|
LOG_I(PHY, "extract_rbs: rx_offset=%d, symbol %u\n", (rx_offset + (symbol * frame_params->ofdm_symbol_size)), symbol);
|
|
#endif
|
|
|
|
for (rb = 0; rb < nb_rb; rb++) {
|
|
j = 0;
|
|
|
|
for (i = 0; i < NR_NB_SC_PER_RB; i++) {
|
|
if (i % 4 != 0) {
|
|
rxF_ext[j] = rxF[rx_offset];
|
|
dl_ch0_ext[j] = dl_ch0[i];
|
|
|
|
#ifdef DEBUG_PSBCH
|
|
|
|
LOG_I(PHY,
|
|
"rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n",
|
|
(9 * rb) + j,
|
|
rxF_ext[j].r,
|
|
rxF_ext[j].i,
|
|
rx_offset,
|
|
rxF[rx_offset].r,
|
|
rxF[rx_offset].i);
|
|
LOG_I(PHY,
|
|
"dl ch0 ext[%d] = (%d,%d) dl_ch0 [%d]= (%d,%d)\n",
|
|
(9 * rb) + j,
|
|
dl_ch0_ext[j].r,
|
|
dl_ch0_ext[j].i,
|
|
i,
|
|
dl_ch0[i].r,
|
|
dl_ch0[i].i);
|
|
#endif
|
|
j++;
|
|
}
|
|
rx_offset = (rx_offset + 1) % (frame_params->ofdm_symbol_size);
|
|
}
|
|
|
|
rxF_ext += SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_RB;
|
|
dl_ch0_ext += SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_RB;
|
|
dl_ch0 += NR_NB_SC_PER_RB;
|
|
}
|
|
|
|
#ifdef DEBUG_PSBCH
|
|
char filename[40], varname[25];
|
|
sprintf(filename, "psbch_dlch_sym_%d.m", symbol);
|
|
sprintf(varname, "psbch_dlch%d.m", symbol);
|
|
LOG_M(filename, varname, (void *)dl_ch0, frame_params->ofdm_symbol_size, 1, 1);
|
|
sprintf(filename, "psbch_dlchext_sym_%d.m", symbol);
|
|
sprintf(varname, "psbch_dlchext%d.m", symbol);
|
|
LOG_M(filename, varname, (void *)&dl_ch_estimates_ext[0][0], SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL, 1, 1);
|
|
#endif
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
int nr_rx_psbch(PHY_VARS_NR_UE *ue,
|
|
UE_nr_rxtx_proc_t *proc,
|
|
int estimateSz,
|
|
struct complex16 dl_ch_estimates[][estimateSz],
|
|
NR_DL_FRAME_PARMS *frame_parms,
|
|
uint8_t *decoded_output,
|
|
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
|
|
uint16_t slss_id)
|
|
{
|
|
uint32_t decoderState = 0;
|
|
int psbch_e_rx_idx = 0;
|
|
// Extra 2 bits needed as polar decoder expects a multiple of 4 as encoder length
|
|
// If these 2 bits are not added, runs compiled with --sanitize will fail.
|
|
int16_t psbch_e_rx[SL_NR_POLAR_PSBCH_E_NORMAL_CP + 2] = {0};
|
|
|
|
#ifdef DEBUG_PSBCH
|
|
write_output("psbch_rxdataF.m",
|
|
"psbchrxF",
|
|
&rxdataF[0][0],
|
|
frame_parms->ofdm_symbol_size * SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP,
|
|
1,
|
|
1);
|
|
#endif
|
|
// symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot
|
|
double log2_maxh = 0;
|
|
|
|
// 0 for Normal Cyclic Prefix and 1 for EXT CyclicPrefix
|
|
const int numsym = (frame_parms->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP : SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
|
|
|
|
for (int symbol = 0; symbol < numsym;) {
|
|
const uint16_t nb_re = SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL;
|
|
__attribute__((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][nb_re + 1];
|
|
__attribute__((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][nb_re + 1];
|
|
// memset(dl_ch_estimates_ext,0, sizeof dl_ch_estimates_ext);
|
|
nr_psbch_extract(frame_parms->samples_per_slot_wCP,
|
|
rxdataF,
|
|
estimateSz,
|
|
dl_ch_estimates,
|
|
rxdataF_ext,
|
|
dl_ch_estimates_ext,
|
|
symbol,
|
|
frame_parms);
|
|
#ifdef DEBUG_PSBCH
|
|
LOG_I(PHY, "PSBCH RX Symbol %d ofdm size %d\n", symbol, frame_parms->ofdm_symbol_size);
|
|
#endif
|
|
|
|
int max_h = 0;
|
|
if (symbol == 0) {
|
|
max_h = nr_pbch_channel_level(dl_ch_estimates_ext, frame_parms, nb_re);
|
|
// log2_maxh = 3+(log2_approx(max_h)/2);
|
|
log2_maxh = 5 + (log2_approx(max_h) / 2); // LLR32 crc error. LLR 16 CRC works
|
|
}
|
|
#ifdef DEBUG_PSBCH
|
|
LOG_I(PHY, "PSBCH RX log2_maxh = %f (%d)\n", log2_maxh, max_h);
|
|
#endif
|
|
|
|
__attribute__((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][nb_re + 1];
|
|
nr_pbch_channel_compensation(rxdataF_ext,
|
|
dl_ch_estimates_ext,
|
|
nb_re,
|
|
rxdataF_comp,
|
|
frame_parms,
|
|
log2_maxh); // log2_maxh+I0_shift
|
|
|
|
nr_pbch_quantize(psbch_e_rx + psbch_e_rx_idx, (short *)rxdataF_comp[0], SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL);
|
|
|
|
psbch_e_rx_idx += SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL;
|
|
|
|
// SKIP 2 SL-PSS AND 2 SL-SSS symbols
|
|
// Symbols carrying PSBCH 0, 5-12
|
|
symbol = (symbol == 0) ? 5 : symbol + 1;
|
|
}
|
|
|
|
#if 0 // ENABLE SCOPE LATER
|
|
UEscopeCopy(ue, psbchRxdataF_comp, psbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, psbch_e_rx_idx/2);
|
|
UEscopeCopy(ue, psbchLlr, psbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, psbch_e_rx_idx);
|
|
#endif
|
|
|
|
#ifdef DEBUG_PSBCH
|
|
write_output("psbch_rxdataFcomp.m", "psbch_rxFcomp", psbch_unClipped, SL_NR_NUM_PSBCH_DATA_RE_IN_ALL_SYMBOLS, 1, 1);
|
|
#endif
|
|
|
|
// un-scrambling
|
|
LOG_D(PHY, "PSBCH RX POLAR DECODING: total PSBCH bits:%d, rx_slss_id:%d\n", psbch_e_rx_idx, slss_id);
|
|
|
|
nr_pbch_unscrambling(psbch_e_rx, slss_id, 0, 0, psbch_e_rx_idx, 0, 0, 0, NULL);
|
|
// polar decoding de-rate matching
|
|
uint64_t tmp = 0;
|
|
decoderState = polar_decoder_int16(psbch_e_rx,
|
|
(uint64_t *)&tmp,
|
|
0,
|
|
SL_NR_POLAR_PSBCH_MESSAGE_TYPE,
|
|
SL_NR_POLAR_PSBCH_PAYLOAD_BITS,
|
|
SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL);
|
|
|
|
uint32_t psbch_payload = tmp;
|
|
|
|
if (decoderState) {
|
|
LOG_D(PHY, "%d:%d PSBCH RX: NOK \n", proc->frame_rx, proc->nr_slot_rx);
|
|
return (decoderState);
|
|
}
|
|
|
|
// Decoder reversal
|
|
uint32_t a_reversed = 0;
|
|
|
|
for (int i = 0; i < SL_NR_POLAR_PSBCH_PAYLOAD_BITS; i++)
|
|
a_reversed |= (((uint64_t)psbch_payload >> i) & 1) << (31 - i);
|
|
|
|
psbch_payload = a_reversed;
|
|
|
|
*((uint32_t *)decoded_output) = psbch_payload;
|
|
|
|
#ifdef DEBUG_PSBCH
|
|
for (int i = 0; i < 4; i++) {
|
|
LOG_I(PHY, "decoded_output[%d]:%x\n", i, decoded_output[i]);
|
|
}
|
|
#endif
|
|
|
|
ue->symbol_offset = 0;
|
|
|
|
// retrieve DFN and slot number from SL-MIB
|
|
uint32_t DFN = 0, slot_offset = 0;
|
|
DFN = (((psbch_payload & 0x0700) >> 1) | ((psbch_payload & 0xFE0000) >> 17));
|
|
slot_offset = (((psbch_payload & 0x010000) >> 10) | ((psbch_payload & 0xFC000000) >> 26));
|
|
|
|
LOG_D(PHY, "PSBCH RX SL-MIB:%x, decoded DFN:slot %d:%d, %x\n", psbch_payload, DFN, slot_offset, *(uint32_t *)decoded_output);
|
|
|
|
return 0;
|
|
}
|