mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-21 08:30:31 +00:00
Compare commits
16 Commits
beam_api
...
nr-ue-cell
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82507b0355 | ||
|
|
30876f4f51 | ||
|
|
0c11fb3d8a | ||
|
|
c77d0c8192 | ||
|
|
c38e7d1425 | ||
|
|
5d37b5b758 | ||
|
|
4c79c9e299 | ||
|
|
7bd5498738 | ||
|
|
684ff39727 | ||
|
|
c8d111e8a7 | ||
|
|
6ce55845f0 | ||
|
|
688828cd91 | ||
|
|
451c096ecb | ||
|
|
f9ab227616 | ||
|
|
1c79c448cb | ||
|
|
645e24cbbb |
@@ -683,6 +683,11 @@ int get_nr_table_idx(int nr_bandP, uint8_t scs_index)
|
||||
return i;
|
||||
}
|
||||
|
||||
nr_bandentry_t get_band_entry(int nr_band, uint8_t scs)
|
||||
{
|
||||
return nr_bandtable[get_nr_table_idx(nr_band, scs)];
|
||||
}
|
||||
|
||||
int get_subband_size(int NPRB,int size) {
|
||||
// implements table 5.2.1.4-2 from 36.214
|
||||
//
|
||||
@@ -1027,16 +1032,16 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB,
|
||||
return ssb_offset_point_a;
|
||||
}
|
||||
|
||||
static double get_start_freq(const double fc, const int nbRB, const int mu)
|
||||
static uint32_t get_start_freq(const uint32_t fc_khz, const int nbRB, const int mu)
|
||||
{
|
||||
const int scs = MU_SCS(mu) * 1000;
|
||||
return fc - ((double)nbRB / 2 * NR_NB_SC_PER_RB * scs);
|
||||
const int scs = MU_SCS(mu);
|
||||
return fc_khz - (nbRB * NR_NB_SC_PER_RB / 2 * scs);
|
||||
}
|
||||
|
||||
static double get_stop_freq(const double fc, const int nbRB, const int mu)
|
||||
static uint32_t get_stop_freq(const uint32_t fc_khz, const int nbRB, const int mu)
|
||||
{
|
||||
int scs = MU_SCS(mu) * 1000;
|
||||
return fc + ((double)nbRB / 2 * NR_NB_SC_PER_RB * scs);
|
||||
const int scs = MU_SCS(mu);
|
||||
return fc_khz + (nbRB * NR_NB_SC_PER_RB / 2 * scs);
|
||||
}
|
||||
|
||||
static void compute_M_and_N(const int gscn, int *rM, int *rN)
|
||||
@@ -1063,38 +1068,78 @@ static void compute_M_and_N(const int gscn, int *rM, int *rN)
|
||||
}
|
||||
|
||||
// Section 5.4.3 of 38.101-1 and -2
|
||||
static double get_ssref_from_gscn(const int gscn)
|
||||
// Returns SSRef in kHz
|
||||
uint32_t get_ssref_from_gscn(const int gscn)
|
||||
{
|
||||
int M, N = -1;
|
||||
compute_M_and_N(gscn, &M, &N);
|
||||
if (gscn > 1 && gscn < 7499) { // Sub 3GHz
|
||||
AssertFatal(N > 0 && N < 2500, "Invalid N\n");
|
||||
AssertFatal(M > 0 && M < 6 && (M & 0x1), "Invalid M\n");
|
||||
return (N * 1200e3 + M * 50e3);
|
||||
return (N * 1200 + M * 50);
|
||||
} else if (gscn > 7498 && gscn < 22256) {
|
||||
AssertFatal(N > -1 && N < 14757, "Invalid N\n");
|
||||
return (3000e6 + N * 1.44e6);
|
||||
return (3000000 + N * 1440);
|
||||
} else if (gscn > 22255 && gscn < 26638) {
|
||||
AssertFatal(N > -1 && N < 4382, "Invalid N\n");
|
||||
return (24250.08e6 + N * 17.28e6);
|
||||
return (24250080 + N * 17280);
|
||||
} else {
|
||||
LOG_E(NR_PHY, "Invalid GSCN\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void find_gscn_to_scan(const double startFreq,
|
||||
const double stopFreq,
|
||||
static void compute_M_and_N_from_ssref(const uint32_t ssref, int *rM, int *rN)
|
||||
{
|
||||
if (ssref < 3000000) {
|
||||
for (int M = 1; M < 6; M += 2) {
|
||||
if (((ssref - M * 50) % 1200) == 0) {
|
||||
*rM = M;
|
||||
*rN = (ssref - M * 50) / 1200;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (ssref >= 3000000 && ssref < 24250000) {
|
||||
*rN = (ssref - 3000000) / 1440;
|
||||
} else if (ssref >= 24250000 && ssref < 100000000) {
|
||||
*rN = (ssref - 24250080) / 17280;
|
||||
} else {
|
||||
AssertFatal(0, "Invalid ssref %u kHz\n", ssref);
|
||||
}
|
||||
}
|
||||
|
||||
int get_gscn_from_nrarfcn(const int band, const int scs, const uint32_t arfcn)
|
||||
{
|
||||
int M, N = -1;
|
||||
const uint32_t ssref = from_nrarfcn(band, scs, arfcn) / 1000;
|
||||
compute_M_and_N_from_ssref(ssref, &M, &N);
|
||||
if (ssref < 3000000) {
|
||||
AssertFatal(N > 0 && N < 2500, "Invalid N\n");
|
||||
AssertFatal(M > 0 && M < 6 && (M & 0x1), "Invalid M\n");
|
||||
return 3 * N + (M - 3) / 2;
|
||||
} else if (ssref >= 3000000 && ssref < 24250000) {
|
||||
AssertFatal(N > -1 && N < 14757, "Invalid N\n");
|
||||
return 7499 + N;
|
||||
} else if (ssref >= 24250000 && ssref < 100000000) {
|
||||
AssertFatal(N > -1 && N < 4382, "Invalid N\n");
|
||||
return 22256 + N;
|
||||
}
|
||||
AssertFatal(0, "Invalid ssref %u kHz\n", ssref);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void find_gscn_to_scan(const uint32_t startFreq,
|
||||
const uint32_t stopFreq,
|
||||
const sync_raster_t gscn,
|
||||
int *scanGscnStart,
|
||||
int *scanGscnStop)
|
||||
{
|
||||
const double scs = MU_SCS(gscn.scs_index) * 1e3;
|
||||
const double ssbBW = 20 * NR_NB_SC_PER_RB * scs;
|
||||
const int scs = MU_SCS(gscn.scs_index);
|
||||
const uint32_t ssbBW = 20 * NR_NB_SC_PER_RB * scs;
|
||||
|
||||
for (int g = gscn.first_gscn; g < gscn.last_gscn; g += gscn.step_gscn) {
|
||||
const double centerSSBFreq = get_ssref_from_gscn(g);
|
||||
const double startSSBFreq = centerSSBFreq - ssbBW / 2;
|
||||
const uint32_t centerSSBFreq = get_ssref_from_gscn(g);
|
||||
const uint32_t startSSBFreq = centerSSBFreq - ssbBW / 2;
|
||||
if (startSSBFreq < startFreq)
|
||||
continue;
|
||||
|
||||
@@ -1104,8 +1149,8 @@ static void find_gscn_to_scan(const double startFreq,
|
||||
*scanGscnStop = *scanGscnStart;
|
||||
|
||||
for (int g = gscn.last_gscn; g > gscn.first_gscn; g -= gscn.step_gscn) {
|
||||
const double centerSSBFreq = get_ssref_from_gscn(g);
|
||||
const double stopSSBFreq = centerSSBFreq + ssbBW / 2 - 1;
|
||||
const uint32_t centerSSBFreq = get_ssref_from_gscn(g);
|
||||
const uint32_t stopSSBFreq = centerSSBFreq + ssbBW / 2 - scs;
|
||||
if (stopSSBFreq > stopFreq)
|
||||
continue;
|
||||
|
||||
@@ -1114,23 +1159,32 @@ static void find_gscn_to_scan(const double startFreq,
|
||||
}
|
||||
}
|
||||
|
||||
static int get_ssb_first_sc(const double pointA, const double ssbCenter, const int mu)
|
||||
int get_ssb_first_sc(const uint32_t pointA_kHz, const uint32_t ssbCenter_kHz, const int mu)
|
||||
{
|
||||
const double scs = MU_SCS(mu) * 1e3;
|
||||
const uint32_t scs = MU_SCS(mu);
|
||||
const int ssbRBs = 20;
|
||||
return (int)((ssbCenter - pointA) / scs - (ssbRBs / 2 * NR_NB_SC_PER_RB));
|
||||
return ((ssbCenter_kHz - pointA_kHz) / scs - (ssbRBs * NR_NB_SC_PER_RB / 2));
|
||||
}
|
||||
|
||||
static int get_neigh_gscn_offset(const int gscn, const int gscn2, const int scs_khz)
|
||||
{
|
||||
const uint32_t firstSSRef = get_ssref_from_gscn(gscn);
|
||||
const uint32_t nextSSRef = get_ssref_from_gscn(gscn2);
|
||||
return ((nextSSRef - firstSSRef) % scs_khz);
|
||||
}
|
||||
|
||||
/* Returns array of first SCS offset in the scanning window */
|
||||
int get_scan_ssb_first_sc(const double fc, const int nbRB, const int nrBand, const int mu, nr_gscn_info_t ssbInfo[MAX_GSCN_BAND])
|
||||
int get_scan_ssb_first_sc(uint32_t *fc_khz_p,
|
||||
const int nbRB,
|
||||
const int nrBand,
|
||||
const int mu,
|
||||
const int numScans,
|
||||
const int firstScannedGscn,
|
||||
const int lastScannedGscn,
|
||||
nr_gscn_info_t ssbInfo[MAX_GSCN_BAND])
|
||||
{
|
||||
const double startFreq = get_start_freq(fc, nbRB, mu);
|
||||
const double stopFreq = get_stop_freq(fc, nbRB, mu);
|
||||
|
||||
int scanGscnStart = 0;
|
||||
int scanGscnStop = 0;
|
||||
const sync_raster_t *tmpRaster = sync_raster;
|
||||
const sync_raster_t * end=sync_raster + sizeofArray(sync_raster);
|
||||
const sync_raster_t *end = sync_raster + sizeofArray(sync_raster);
|
||||
while (tmpRaster < end && (tmpRaster->band != nrBand || tmpRaster->scs_index != mu))
|
||||
tmpRaster++;
|
||||
if (tmpRaster >= end) {
|
||||
@@ -1138,18 +1192,69 @@ int get_scan_ssb_first_sc(const double fc, const int nbRB, const int nrBand, con
|
||||
return 0;
|
||||
}
|
||||
|
||||
// for sub 3GHz SSRef = N * 1200kHz + M * 50kHz. So one value of M for each scan
|
||||
/*
|
||||
GSCN First scan Second scan Third scan
|
||||
0 x
|
||||
1 x
|
||||
2 x
|
||||
3 x
|
||||
... x
|
||||
... x
|
||||
...
|
||||
N-3 x
|
||||
N-2 x
|
||||
N-1 x
|
||||
|
||||
*/
|
||||
bool sub3 = (tmpRaster->last_gscn < 7499 && tmpRaster->step_gscn == 1); // GSCN granularity not consistent with SCS
|
||||
const uint32_t scs = MU_SCS(mu);
|
||||
uint32_t fc_khz = *fc_khz_p;
|
||||
uint32_t startFreq;
|
||||
if (fc_khz != 0) {
|
||||
// center freq provided, return list of GSCN in current bandwidth
|
||||
startFreq = get_start_freq(fc_khz, nbRB, mu);
|
||||
} else {
|
||||
// center freq not provided
|
||||
// compute startFreq from first GSCN to be scanned in this run
|
||||
int first_gscn;
|
||||
if (sub3 && (numScans % 3))
|
||||
first_gscn = firstScannedGscn + 1;
|
||||
else
|
||||
first_gscn = (lastScannedGscn == -1) ? tmpRaster->first_gscn : lastScannedGscn + tmpRaster->step_gscn;
|
||||
if (first_gscn > tmpRaster->last_gscn) {
|
||||
// Repeat search
|
||||
first_gscn = tmpRaster->first_gscn;
|
||||
}
|
||||
const uint32_t firstSSRef = get_ssref_from_gscn(first_gscn);
|
||||
const int ssbRBs = 20;
|
||||
startFreq = firstSSRef - (ssbRBs * NR_NB_SC_PER_RB / 2 * scs);
|
||||
fc_khz = startFreq + (nbRB * NR_NB_SC_PER_RB / 2 * scs);
|
||||
// return new center frequency
|
||||
*fc_khz_p = fc_khz;
|
||||
}
|
||||
const uint32_t stopFreq = get_stop_freq(fc_khz, nbRB, mu);
|
||||
int scanGscnStart = 0;
|
||||
int scanGscnStop = 0;
|
||||
find_gscn_to_scan(startFreq, stopFreq, *tmpRaster, &scanGscnStart, &scanGscnStop);
|
||||
|
||||
const double scs = MU_SCS(mu) * 1e3;
|
||||
const double pointA = fc - ((double)nbRB / 2 * scs * NR_NB_SC_PER_RB);
|
||||
const uint32_t pointA = fc_khz - (nbRB * NR_NB_SC_PER_RB / 2 * scs);
|
||||
int numGscn = 0;
|
||||
for (int g = scanGscnStart; (g <= scanGscnStop) && (numGscn < MAX_GSCN_BAND); g += tmpRaster->step_gscn) {
|
||||
const int step_gscn = sub3 ? 3 : tmpRaster->step_gscn;
|
||||
for (int g = scanGscnStart; (g <= scanGscnStop) && (numGscn < MAX_GSCN_BAND); g += step_gscn) {
|
||||
ssbInfo[numGscn].ssRef = get_ssref_from_gscn(g);
|
||||
ssbInfo[numGscn].ssbFirstSC = get_ssb_first_sc(pointA, ssbInfo[numGscn].ssRef, mu);
|
||||
ssbInfo[numGscn].gscn = g;
|
||||
numGscn++;
|
||||
}
|
||||
|
||||
if (numGscn > 2) {
|
||||
// Check if GSCNs to be scanned are aligned with current freq and SCS
|
||||
const int sync_raster_granu = get_neigh_gscn_offset(ssbInfo[0].gscn, ssbInfo[1].gscn, scs);
|
||||
if (sync_raster_granu)
|
||||
LOG_E(NR_PHY, "Sync raster granularity %d unaligned with SCS %d\n", sync_raster_granu, scs);
|
||||
}
|
||||
|
||||
return numGscn;
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,14 @@ typedef struct {
|
||||
nr_sib_type_t SIB_type;
|
||||
} nr_SIBs_t;
|
||||
|
||||
typedef enum {
|
||||
PHY_CONFIG_BIT_MASK_CARRIER = 0,
|
||||
PHY_CONFIG_BIT_MASK_CELL,
|
||||
PHY_CONFIG_BIT_MASK_SSB,
|
||||
PHY_CONFIG_BIT_MASK_TDD,
|
||||
PHY_CONFIG_BIT_MASK_PRACH
|
||||
} nr_phy_config_mask_t;
|
||||
|
||||
typedef struct nr_bandentry_s {
|
||||
int16_t band;
|
||||
uint64_t ul_min;
|
||||
@@ -131,7 +139,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
int gscn;
|
||||
double ssRef;
|
||||
uint32_t ssRef;
|
||||
int ssbFirstSC;
|
||||
} nr_gscn_info_t;
|
||||
|
||||
@@ -277,7 +285,8 @@ int NRRIV2BW(int locationAndBandwidth,int N_RB);
|
||||
int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB);
|
||||
int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize);
|
||||
int PRBalloc_to_locationandbandwidth(int NPRB,int RBstart);
|
||||
int get_subband_size(int NPRB,int size);
|
||||
nr_bandentry_t get_band_entry(int nr_band, uint8_t scs);
|
||||
int get_subband_size(int NPRB, int size);
|
||||
void SLIV2SL(int SLIV,int *S,int *L);
|
||||
int get_dmrs_port(int nl, uint16_t dmrs_ports);
|
||||
uint16_t SL_to_bitmap(int startSymbolIndex, int nrOfSymbols);
|
||||
@@ -299,11 +308,14 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB,
|
||||
int get_ssb_subcarrier_offset(uint32_t absoluteFrequencySSB, uint32_t absoluteFrequencyPointA, int scs);
|
||||
int get_delay_idx(int delay, int max_delay_comp);
|
||||
|
||||
int get_scan_ssb_first_sc(const double fc,
|
||||
int get_scan_ssb_first_sc(uint32_t *fc_khz_p,
|
||||
const int nbRB,
|
||||
const int nrBand,
|
||||
const int mu,
|
||||
nr_gscn_info_t ssbStartSC[MAX_GSCN_BAND]);
|
||||
const int numScans,
|
||||
const int firstScannedGscn,
|
||||
const int lastScannedGscn,
|
||||
nr_gscn_info_t ssbInfo[MAX_GSCN_BAND]);
|
||||
|
||||
void check_ssb_raster(uint64_t freq, int band, int scs);
|
||||
int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_range, int n_rbs);
|
||||
@@ -314,6 +326,9 @@ uint8_t get_PRACH_k_bar(unsigned int delta_f_RA_PRACH, unsigned int delta_f_PUSC
|
||||
unsigned int get_prach_K(int prach_sequence_length, int prach_fmt_id, int pusch_mu, int prach_mu);
|
||||
|
||||
int get_slot_idx_in_period(const int slot, const frame_structure_t *fs);
|
||||
int get_ssb_first_sc(const uint32_t pointA, const uint32_t ssbCenter, const int mu);
|
||||
int get_gscn_from_nrarfcn(const int band, const int scs, const uint32_t arfcn);
|
||||
uint32_t get_ssref_from_gscn(const int gscn);
|
||||
|
||||
frequency_range_t get_freq_range_from_freq(uint64_t freq);
|
||||
frequency_range_t get_freq_range_from_arfcn(uint32_t arfcn);
|
||||
@@ -358,6 +373,12 @@ void nr_deconstruct_5g_s_tmsi(const uint64_t fiveg_s_tmsi, uint16_t *amf_set_id,
|
||||
|
||||
static const char *const duplex_mode_txt[] = {"FDD", "TDD"};
|
||||
|
||||
#define SETBIT(a, b) ((a) |= (1 << (b)))
|
||||
#define GETBIT(a, b) (((a) >> (b)) & 1)
|
||||
|
||||
// Align up to a multiple of 16
|
||||
#define ALIGN_UP_16(a) ((a + 15) & ~15)
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifdef min
|
||||
#undef min
|
||||
|
||||
@@ -91,7 +91,7 @@ Here are some useful command line options for the NR UE:
|
||||
|
||||
| Parameter | Description |
|
||||
|--------------------------|---------------------------------------------------------------------------------------------------------------|
|
||||
| `--ue-scan-carrier` | Scan for cells in current bandwidth. This option can be used if the SSB position of the gNB is unknown. If multiple cells are detected, the UE will try to connect to the first cell. By default, this option is disabled and the UE attempts to only decode SSB given by `--ssb`. |
|
||||
| `--ue-scan-carrier` | Value range: [0 - 2]. 0: Scan disabled and UE attempts to only decode SSB given be `--ssb`. This is the default behavior. 1: Scan for cells in current bandwidth. This option can be used if the SSB position of the gNB is unknown. If multiple cells are detected, the UE will try to connect to the first cell. 2: Scan for cells in NR band given by `--band`. This option can be used to scan cells in an NR band. Like option 1, the UE will try to connect to the fist cell. There is ongoing work to improve this and have a scan only mode to report all cells in the band. |
|
||||
| `--ue-fo-compensation` | Enables the initial frequency offset compensation at the UE. Useful when running over the air and/or without an external clock/time source. |
|
||||
| `--cont-fo-comp` | Enables the continuous frequency offset (FO) estimation and compensation. Parameter value `1` specifies that the main FO contribution comes from the local oscillator's (LO) accuracy. Parameter value `2` specifies that the main FO contribution comes from Doppler shift. Parameter value `3` specifies that no measured residual DL FO is considered for UL FO pre-compensation. |
|
||||
| `--initial-fo` | Sets the known initial frequency offset. Useful especially with large Doppler frequency, e.g. LEO satellite. |
|
||||
@@ -112,6 +112,10 @@ You can view all available options by typing:
|
||||
./nr-uesoftmodem --help
|
||||
```
|
||||
|
||||
### Cell Search Limitation
|
||||
|
||||
The cell search feature in the UE (`--ue-scan-carrier`) works only with real RF devices and not in rfsim. It is because the NR waveform has phase pre-compensation to have different center frequencies at gNB and UE. In real RF the phase offset produced by difference in center frequencies are cancelled by the pre-compensation in OFDM signal generation and Up/Down conversion. But it is not the case in rfsim. However, `--ue-scan-carrier 1` can be used in rfsim when gNB and UE have the same center frequency.
|
||||
|
||||
### UE Capabilities
|
||||
|
||||
The `--uecap_file` option can be used to pass the UE Capabilities input file (path location + filename), e.g.`--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml` for 1 layer or e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports2.xml` for 2 layers.
|
||||
|
||||
@@ -48,7 +48,10 @@
|
||||
#define CONFIG_HLP_UETXG "set UE TX gain\n"
|
||||
#define CONFIG_HLP_UENANTR "set UE number of rx antennas\n"
|
||||
#define CONFIG_HLP_UENANTT "set UE number of tx antennas\n"
|
||||
#define CONFIG_HLP_UESCAN "set UE to scan all possible GSCN in current bandwidth\n"
|
||||
#define CONFIG_HLP_UESCAN \
|
||||
"0: UE will decode SSB based on --ssb parameter,\n" \
|
||||
"1: UE will scan all possible GSCN in given center frequency & bandwidth,\n" \
|
||||
"2: UE will scan the whole NR band and connects to first found cell.\n"
|
||||
#define CONFIG_HLP_UEFO "set UE to enable estimation and compensation of frequency offset\n"
|
||||
#define CONFIG_HLP_PRB_SA "Set the number of PRBs for SA\n"
|
||||
#define CONFIG_HLP_SSC "Set the start subcarrier \n"
|
||||
|
||||
@@ -290,7 +290,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx
|
||||
|
||||
radio_tx_burst_flag_t flags = TX_BURST_INVALID;
|
||||
|
||||
if (UE->received_config_request) {
|
||||
if (GETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_TDD)) {
|
||||
if (fp->frame_type == FDD || get_softmodem_params()->continuous_tx) {
|
||||
flags = TX_BURST_MIDDLE;
|
||||
// In case of Sidelink, USRP write needed only in case transmission
|
||||
@@ -453,21 +453,103 @@ static uint64_t get_carrier_frequency(const int N_RB, const int mu, const uint32
|
||||
return carrier_freq;
|
||||
}
|
||||
|
||||
static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
|
||||
static void dummyWrite(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, int writeBlockSize)
|
||||
{
|
||||
const NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
if (UE->sl_mode == 2)
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
c16_t *dummy_tx[fp->nb_antennas_tx];
|
||||
c16_t dummy_tx_data[writeBlockSize];
|
||||
memset(dummy_tx_data, 0, sizeof(dummy_tx_data));
|
||||
for (int i = 0; i < fp->nb_antennas_tx; i++)
|
||||
dummy_tx[i] = dummy_tx_data;
|
||||
|
||||
int tmp = nrue_ru_write(UE, timestamp, (void **)dummy_tx, writeBlockSize, fp->nb_antennas_tx, 4);
|
||||
AssertFatal(writeBlockSize == tmp, "");
|
||||
}
|
||||
|
||||
static int readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp_t *timestamp, int duration_rx_to_tx, bool toTrash)
|
||||
{
|
||||
const NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
// two frames for initial sync
|
||||
int num_frames = 2;
|
||||
// In Sidelink worst case SL-SSB can be sent once in 16 frames
|
||||
if (UE->sl_mode == 2) {
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
num_frames = SL_NR_PSBCH_REPETITION_IN_FRAMES;
|
||||
}
|
||||
|
||||
c16_t *rxp[fp->nb_antennas_rx];
|
||||
if (toTrash) {
|
||||
rxp[0] = malloc16(get_samples_per_slot(0, fp) * sizeof(c16_t));
|
||||
for (int i = 1; i < fp->nb_antennas_rx; i++)
|
||||
rxp[i] = rxp[0];
|
||||
}
|
||||
|
||||
for (int x = 0; x < num_frames * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; x++) { // two frames for initial sync
|
||||
for (int slot_rx = 0; slot_rx < fp->slots_per_subframe; slot_rx++) {
|
||||
if (!toTrash)
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++)
|
||||
rxp[i] = &UE->common_vars.rxdata[i][x * fp->samples_per_subframe + get_samples_slot_timestamp(fp, slot_rx)];
|
||||
|
||||
int readBlockSize = get_samples_per_slot(slot_rx, fp);
|
||||
int tmp = nrue_ru_read(UE, timestamp, (void **)rxp, readBlockSize, fp->nb_antennas_rx);
|
||||
UEscopeCopy(UE, ueTimeDomainSamplesBeforeSync, rxp[0], sizeof(c16_t), 1, readBlockSize, 0);
|
||||
if (readBlockSize != tmp) {
|
||||
if (toTrash)
|
||||
free(rxp[0]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (IS_SOFTMODEM_RFSIM) {
|
||||
int slot_tx = (slot_rx + duration_rx_to_tx) % fp->slots_per_frame;
|
||||
int writeBlockSize = get_samples_per_slot(slot_tx, fp);
|
||||
int ta = UE->timing_advance + UE->timing_advance_ntn;
|
||||
const openair0_timestamp_t writeTimestamp =
|
||||
*timestamp + get_samples_slot_duration(fp, slot_rx, duration_rx_to_tx) - UE->N_TA_offset - ta;
|
||||
dummyWrite(UE, writeTimestamp, writeBlockSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (toTrash)
|
||||
free(rxp[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE, uint32_t *ssb_arfcn)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
const fapi_nr_config_request_t *config = &UE->nrUE_config;
|
||||
const fapi_nr_ue_carrier_config_t *cfg = &config->carrier_config;
|
||||
// Start synchronization with a target gNB
|
||||
if (UE->synch_request.received_synch_request == 1) {
|
||||
// if upper layers signal BW scan we do as instructed by command line parameter
|
||||
// if upper layers disable BW scan we set it to false
|
||||
if (UE->synch_request.synch_req.ssb_bw_scan)
|
||||
const fapi_nr_synch_request_t *s = &UE->synch_request.synch_req;
|
||||
if (s->ssb_bw_scan)
|
||||
UE->UE_scan_carrier = get_nrUE_params()->UE_scan_carrier;
|
||||
else
|
||||
UE->UE_scan_carrier = false;
|
||||
else {
|
||||
UE->UE_scan_carrier = NO_SCAN;
|
||||
if (s->ssb_arfcn == 0) {
|
||||
if (get_softmodem_params()->do_ra || get_softmodem_params()->phy_test)
|
||||
LOG_E(PHY,
|
||||
"Received sync request without BW scan and no SSB position. Either one should be provided. Attempting sync with "
|
||||
"default SSB position\n");
|
||||
else
|
||||
AssertFatal(0, "Sync request in SA mode must have SSB position or BW scan command\n");
|
||||
} else {
|
||||
fp->ssb_start_subcarrier = get_ssb_first_sc(cfg->dl_frequency,
|
||||
from_nrarfcn(nrue_get_band(UE), fp->numerology_index, s->ssb_arfcn) / 1000,
|
||||
fp->numerology_index);
|
||||
*ssb_arfcn = s->ssb_arfcn;
|
||||
}
|
||||
}
|
||||
UE->target_Nid_cell = UE->synch_request.synch_req.target_Nid_cell;
|
||||
|
||||
const fapi_nr_config_request_t *config = &UE->nrUE_config;
|
||||
const fapi_nr_ue_carrier_config_t *cfg = &config->carrier_config;
|
||||
uint64_t dl_CarrierFreq = get_carrier_frequency(fp->N_RB_DL, fp->numerology_index, cfg->dl_frequency);
|
||||
uint64_t ul_CarrierFreq = get_carrier_frequency(fp->N_RB_UL, fp->numerology_index, cfg->uplink_frequency);
|
||||
if (dl_CarrierFreq != fp->dl_CarrierFreq || ul_CarrierFreq != fp->ul_CarrierFreq) {
|
||||
@@ -484,6 +566,10 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
|
||||
fp->dl_CarrierFreq = dl_CarrierFreq;
|
||||
fp->ul_CarrierFreq = ul_CarrierFreq;
|
||||
init_symbol_rotation(fp);
|
||||
// warm up the RF board after changing frequency
|
||||
int64_t tmp;
|
||||
for (int i = 0; i < 50; i++)
|
||||
readFrame(UE, &tmp, NR_UE_CAPABILITY_SLOT_RX_TO_TX, true);
|
||||
}
|
||||
|
||||
int ssb_start_subcarrier = nr_get_ssb_start_sc(fp->numerology_index,
|
||||
@@ -613,66 +699,6 @@ void UE_dl_processing(void *arg) {
|
||||
TracyCZoneEnd(ctx);
|
||||
}
|
||||
|
||||
void dummyWrite(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, int writeBlockSize)
|
||||
{
|
||||
const NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
if (UE->sl_mode == 2)
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
c16_t *dummy_tx[fp->nb_antennas_tx];
|
||||
c16_t dummy_tx_data[writeBlockSize];
|
||||
memset(dummy_tx_data, 0, sizeof(dummy_tx_data));
|
||||
for (int i = 0; i < fp->nb_antennas_tx; i++)
|
||||
dummy_tx[i] = dummy_tx_data;
|
||||
|
||||
int tmp = nrue_ru_write(UE, timestamp, (void **)dummy_tx, writeBlockSize, fp->nb_antennas_tx, 4);
|
||||
AssertFatal(writeBlockSize == tmp, "");
|
||||
}
|
||||
|
||||
void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp_t *timestamp, int duration_rx_to_tx, bool toTrash)
|
||||
{
|
||||
const NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
// two frames for initial sync
|
||||
int num_frames = 2;
|
||||
// In Sidelink worst case SL-SSB can be sent once in 16 frames
|
||||
if (UE->sl_mode == 2) {
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
num_frames = SL_NR_PSBCH_REPETITION_IN_FRAMES;
|
||||
}
|
||||
|
||||
c16_t *rxp[fp->nb_antennas_rx];
|
||||
if (toTrash) {
|
||||
rxp[0] = malloc16(get_samples_per_slot(0, fp) * sizeof(c16_t));
|
||||
for (int i = 1; i < fp->nb_antennas_rx; i++)
|
||||
rxp[i] = rxp[0];
|
||||
}
|
||||
|
||||
for (int x = 0; x < num_frames * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; x++) { // two frames for initial sync
|
||||
for (int slot_rx = 0; slot_rx < fp->slots_per_subframe; slot_rx++) {
|
||||
if (!toTrash)
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++)
|
||||
rxp[i] = &UE->common_vars.rxdata[i][x * fp->samples_per_subframe + get_samples_slot_timestamp(fp, slot_rx)];
|
||||
|
||||
int readBlockSize = get_samples_per_slot(slot_rx, fp);
|
||||
int tmp = nrue_ru_read(UE, timestamp, (void **)rxp, readBlockSize, fp->nb_antennas_rx);
|
||||
UEscopeCopy(UE, ueTimeDomainSamplesBeforeSync, rxp[0], sizeof(c16_t), 1, readBlockSize, 0);
|
||||
AssertFatal(readBlockSize == tmp, "");
|
||||
|
||||
if (IS_SOFTMODEM_RFSIM) {
|
||||
int slot_tx = (slot_rx + duration_rx_to_tx) % fp->slots_per_frame;
|
||||
int writeBlockSize = get_samples_per_slot(slot_tx, fp);
|
||||
int ta = UE->timing_advance + UE->timing_advance_ntn;
|
||||
const openair0_timestamp_t writeTimestamp =
|
||||
*timestamp + get_samples_slot_duration(fp, slot_rx, duration_rx_to_tx) - UE->N_TA_offset - ta;
|
||||
dummyWrite(UE, writeTimestamp, writeBlockSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (toTrash)
|
||||
free(rxp[0]);
|
||||
}
|
||||
|
||||
static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp_t *timestamp, int duration_rx_to_tx, openair0_timestamp_t rx_offset)
|
||||
{
|
||||
const NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
@@ -760,6 +786,7 @@ void *UE_thread(void *arg)
|
||||
int intialSyncOffset = 0;
|
||||
openair0_timestamp_t sync_timestamp;
|
||||
bool stats_printed = false;
|
||||
uint32_t sync_ssb_arfcn = 0;
|
||||
|
||||
if (get_softmodem_params()->sync_ref && UE->sl_mode == 2) {
|
||||
UE->is_synchronized = 1;
|
||||
@@ -771,6 +798,10 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
|
||||
c16_t *rxp[fp->nb_antennas_rx];
|
||||
int first_scanned_gscn = -1;
|
||||
int last_scanned_gscn = -1;
|
||||
int num_scans = 0;
|
||||
|
||||
while (!oai_exit) {
|
||||
if (syncRunning) {
|
||||
notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf);
|
||||
@@ -778,7 +809,6 @@ void *UE_thread(void *arg)
|
||||
if (res) {
|
||||
syncRunning = false;
|
||||
if (UE->is_synchronized) {
|
||||
UE->synch_request.received_synch_request = 0;
|
||||
if (UE->sl_mode == SL_MODE2_SUPPORTED)
|
||||
decoded_frame_rx = UE->SL_UE_PHY_PARAMS.sync_params.DFN;
|
||||
else {
|
||||
@@ -824,20 +854,68 @@ void *UE_thread(void *arg)
|
||||
AssertFatal(!syncRunning, "At this point synchronization can't be running\n");
|
||||
|
||||
if (!UE->is_synchronized) {
|
||||
readFrame(UE, &sync_timestamp, duration_rx_to_tx, false);
|
||||
notifiedFIFO_elt_t *Msg = newNotifiedFIFO_elt(sizeof(syncData_t), 0, &nf, UE_synch);
|
||||
syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(Msg);
|
||||
*syncMsg = (syncData_t){0};
|
||||
if (UE->UE_scan_carrier) {
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
const int nr_band = nrue_get_band(UE);
|
||||
if (fp->dl_CarrierFreq % 1000)
|
||||
LOG_E(PHY, "Center frequency %lu is not multiple of kHz\n", fp->dl_CarrierFreq);
|
||||
|
||||
if (UE->UE_scan_carrier == SCAN_BW) {
|
||||
// Get list of GSCN in this band for UE's bandwidth and center frequency.
|
||||
LOG_W(PHY, "UE set to scan all GSCN in current bandwidth\n");
|
||||
syncMsg->numGscn =
|
||||
get_scan_ssb_first_sc(fp->dl_CarrierFreq, fp->N_RB_DL, nrue_get_band(UE), fp->numerology_index, syncMsg->gscnInfo);
|
||||
uint32_t dl_freq_khz = fp->dl_CarrierFreq / 1000;
|
||||
syncMsg->numGscn = get_scan_ssb_first_sc(&dl_freq_khz,
|
||||
fp->N_RB_DL,
|
||||
nr_band,
|
||||
fp->numerology_index,
|
||||
0,
|
||||
0,
|
||||
0 /*not used*/,
|
||||
syncMsg->gscnInfo);
|
||||
} else if (UE->UE_scan_carrier == SCAN_BAND) {
|
||||
// Get list of GSCN after last scanned GSCN in this band
|
||||
LOG_W(PHY, "UE set to scan full NR band\n");
|
||||
uint32_t dlFreq = 0;
|
||||
syncMsg->numGscn = get_scan_ssb_first_sc(&dlFreq,
|
||||
fp->N_RB_DL,
|
||||
nr_band,
|
||||
fp->numerology_index,
|
||||
num_scans,
|
||||
first_scanned_gscn,
|
||||
last_scanned_gscn,
|
||||
syncMsg->gscnInfo);
|
||||
num_scans++;
|
||||
// save last gscn from current list to continune in next scan
|
||||
first_scanned_gscn = syncMsg->gscnInfo[0].gscn;
|
||||
last_scanned_gscn = syncMsg->gscnInfo[syncMsg->numGscn - 1].gscn;
|
||||
// set dl freqeuncy for current scan
|
||||
fp->dl_CarrierFreq = dlFreq * 1000;
|
||||
nrue_ru_set_freq(UE, fp->dl_CarrierFreq, fp->dl_CarrierFreq, 0);
|
||||
init_symbol_rotation(fp);
|
||||
} else {
|
||||
LOG_W(PHY, "SSB position provided\n");
|
||||
syncMsg->gscnInfo[0] = (nr_gscn_info_t){.ssbFirstSC = fp->ssb_start_subcarrier};
|
||||
nr_gscn_info_t *g = syncMsg->gscnInfo;
|
||||
g->ssbFirstSC = fp->ssb_start_subcarrier;
|
||||
if (sync_ssb_arfcn) {
|
||||
g->gscn = get_gscn_from_nrarfcn(nr_band, fp->numerology_index, sync_ssb_arfcn);
|
||||
g->ssRef = get_ssref_from_gscn(g->gscn);
|
||||
} else {
|
||||
g->gscn = g->ssRef = 0;
|
||||
}
|
||||
syncMsg->numGscn = 1;
|
||||
}
|
||||
// warm up the RF board after changing frequency
|
||||
int64_t tmp;
|
||||
for (int i = 0; i < 50; i++)
|
||||
readFrame(UE, &tmp, duration_rx_to_tx, true);
|
||||
|
||||
// read 2 frames to do initial sync
|
||||
while (true) {
|
||||
if (readFrame(UE, &sync_timestamp, duration_rx_to_tx, false) == 0)
|
||||
break;
|
||||
}
|
||||
syncMsg->UE = UE;
|
||||
memset(&syncMsg->proc, 0, sizeof(syncMsg->proc));
|
||||
pushNotifiedFIFO(&UE->sync_actor.fifo, Msg);
|
||||
@@ -901,7 +979,7 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
|
||||
/* check if MAC has sent sync request */
|
||||
if (handle_sync_req_from_mac(UE) == 0)
|
||||
if (handle_sync_req_from_mac(UE, &sync_ssb_arfcn) == 0)
|
||||
continue;
|
||||
|
||||
// start of normal case, the UE is in sync
|
||||
@@ -922,16 +1000,15 @@ void *UE_thread(void *arg)
|
||||
curMsg.proc.frame_tx = ((absolute_slot + duration_rx_to_tx) / nb_slot_frame) % MAX_FRAME_NUMBER;
|
||||
curMsg.proc.hfn_rx = (absolute_slot / nb_slot_frame) / MAX_FRAME_NUMBER;
|
||||
curMsg.proc.hfn_tx = ((absolute_slot + duration_rx_to_tx) / nb_slot_frame) / MAX_FRAME_NUMBER;
|
||||
if (UE->received_config_request) {
|
||||
if (UE->sl_mode) {
|
||||
if (sl_cfg) {
|
||||
if (sl_cfg->config_mask == 0xf && UE->sl_mode) {
|
||||
curMsg.proc.rx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.nr_slot_rx, TDD);
|
||||
curMsg.proc.tx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.nr_slot_tx, TDD);
|
||||
} else {
|
||||
curMsg.proc.rx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.nr_slot_rx);
|
||||
curMsg.proc.tx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.nr_slot_tx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else if (GETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_TDD)) {
|
||||
curMsg.proc.rx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.nr_slot_rx);
|
||||
curMsg.proc.tx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.nr_slot_tx);
|
||||
} else {
|
||||
curMsg.proc.rx_slot_type = NR_DOWNLINK_SLOT;
|
||||
curMsg.proc.tx_slot_type = NR_DOWNLINK_SLOT;
|
||||
}
|
||||
|
||||
@@ -380,6 +380,7 @@ int main(int argc, char **argv)
|
||||
mac->nr_band = cell.band;
|
||||
mac->ssb_start_subcarrier = cell.ssb_start;
|
||||
mac->dl_frequency = cell.rf_frequency;
|
||||
mac->N_RB_DL = cell.N_RB_DL;
|
||||
|
||||
UE_CC->sl_mode = get_softmodem_params()->sl_mode;
|
||||
init_actor(&UE_CC->sync_actor, "SYNC_", -1);
|
||||
|
||||
@@ -55,7 +55,7 @@ extern uint16_t ue_id_g;
|
||||
{"ue-txgain", CONFIG_HLP_UETXG, 0, .dblptr=&nrUE_params.tx_gain, .defdblval=0, TYPE_DOUBLE, 0}, \
|
||||
{"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, .iptr=&(nrUE_params.nb_antennas_rx), .defuintval=1, TYPE_UINT8, 0}, \
|
||||
{"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, .iptr=&(nrUE_params.nb_antennas_tx), .defuintval=1, TYPE_UINT8, 0}, \
|
||||
{"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, .iptr=&(nrUE_params.UE_scan_carrier), .defintval=0, TYPE_INT, 0}, \
|
||||
{"ue-scan-carrier", CONFIG_HLP_UESCAN, 0, .iptr=&(nrUE_params.UE_scan_carrier), .defintval=0, TYPE_INT, 0}, \
|
||||
{"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, .iptr=&(nrUE_params.UE_fo_compensation), .defintval=0, TYPE_INT, 0}, \
|
||||
{"ue-max-power", NULL, 0, .iptr=&(nrUE_params.tx_max_power), .defintval=90, TYPE_INT, 0}, \
|
||||
{"r" , CONFIG_HLP_PRB_SA, 0, .iptr=&(nrUE_params.N_RB_DL), .defintval=106, TYPE_UINT, 0}, \
|
||||
|
||||
@@ -727,6 +727,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
int16_t target_Nid_cell;
|
||||
uint32_t ssb_arfcn;
|
||||
bool ssb_bw_scan;
|
||||
} fapi_nr_synch_request_t;
|
||||
|
||||
|
||||
@@ -257,10 +257,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
init_symbol_rotation(fp);
|
||||
init_timeshift_rotation(fp);
|
||||
|
||||
// initialize to false only for SA since in do-ra and phy-test it is already set to true before getting here
|
||||
if (IS_SA_MODE(get_softmodem_params()))
|
||||
ue->received_config_request = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -423,13 +423,20 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fapi_nr_config_request_t* conf
|
||||
|
||||
void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, const nrUE_cell_params_t *cell)
|
||||
{
|
||||
const uint64_t downlink_frequency = cell->rf_frequency;
|
||||
const int64_t delta_duplex = cell->rf_freq_offset;
|
||||
const uint8_t mu = cell->numerology;
|
||||
const int N_RB_DL = cell->N_RB_DL;
|
||||
const int ssb_start_subcarrier = cell->ssb_start;
|
||||
const uint16_t nr_band = cell->band;
|
||||
|
||||
// Set DL freq from band if center freq not provided
|
||||
uint64_t downlink_frequency = cell->rf_frequency;
|
||||
if (downlink_frequency == 0) {
|
||||
const nr_bandentry_t b = get_band_entry(nr_band, mu);
|
||||
/* Set center of the band for radio initialization. Center will be reconfigured
|
||||
during cell search and after SIB1 reception */
|
||||
downlink_frequency = (b.dl_min + (b.dl_max - b.dl_min) / 2) * 1000;
|
||||
}
|
||||
LOG_I(PHY,"SA init parameters. DL freq %lu UL offset %ld SSB numerology %d N_RB_DL %d\n",
|
||||
downlink_frequency,
|
||||
delta_duplex,
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#define SSS_START_IDX (3) /* [0:PSBCH 1:PSS0 2:PSS1 3:SSS0 4:SSS1] */
|
||||
#define NUM_SSS_SYMBOLS (2)
|
||||
|
||||
#define SSS_METRIC_FLOOR_NR (30000)
|
||||
#define SSS_METRIC_FLOOR_NR (20000)
|
||||
|
||||
void init_context_sss_nr(int amp);
|
||||
void free_context_sss_nr(void);
|
||||
|
||||
@@ -394,7 +394,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
memset(ssbInfo->rxdata[ant] + fp->samples_per_frame * 2, 0, fp->ofdm_symbol_size * sizeof(c16_t));
|
||||
}
|
||||
LOG_I(NR_PHY,
|
||||
"Scanning GSCN: %d, with SSB offset: %d, SSB Freq: %lf\n",
|
||||
"Scanning GSCN: %d, with SSB offset: %d, SSB Freq: %u kHz\n",
|
||||
ssbInfo->gscnInfo.gscn,
|
||||
ssbInfo->gscnInfo.ssbFirstSC,
|
||||
ssbInfo->gscnInfo.ssRef);
|
||||
@@ -410,7 +410,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
nr_ue_ssb_scan_t *ssbInfo = &ssb_info[i];
|
||||
if (ssbInfo->syncRes.cell_detected) {
|
||||
LOG_I(NR_PHY,
|
||||
"Cell Detected with GSCN: %d, SSB SC offset: %d, SSB Ref: %lf, PSS Corr peak: %d dB, PSS Corr Average: %d\n",
|
||||
"Cell Detected with GSCN: %d, SSB SC offset: %d, SSB Ref: %u kHz, PSS Corr peak: %d dB, PSS Corr Average: %d\n",
|
||||
ssbInfo->gscnInfo.gscn,
|
||||
ssbInfo->gscnInfo.ssbFirstSC,
|
||||
ssbInfo->gscnInfo.ssRef,
|
||||
@@ -459,12 +459,6 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
LOG_D(PHY, "nr_initial sync ue RB_DL %d\n", fp->N_RB_DL);
|
||||
|
||||
if (res) {
|
||||
// digital compensation of FFO for SSB symbols
|
||||
if (res->freqOffset && ue->UE_fo_compensation) {
|
||||
// In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1
|
||||
// and we do not know yet in which slot it goes.
|
||||
compensate_freq_offset(ue->common_vars.rxdata, fp, res->freqOffset, res->syncRes.frame_id);
|
||||
}
|
||||
// sync at symbol ue->symbol_offset
|
||||
// computing the offset wrt the beginning of the frame
|
||||
int mu = fp->numerology_index;
|
||||
|
||||
@@ -397,19 +397,9 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
NR_POLAR_PBCH_AGGREGATION_LEVEL);
|
||||
pbch_a_prime = tmp;
|
||||
|
||||
nr_downlink_indication_t dl_indication;
|
||||
fapi_nr_rx_indication_t rx_ind = {0};
|
||||
uint16_t number_pdus = 1;
|
||||
if (decoderState)
|
||||
return decoderState;
|
||||
|
||||
if (decoderState) {
|
||||
if (ue) { // decoding failed in synced state
|
||||
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, NULL, NULL);
|
||||
if (ue->if_inst && ue->if_inst->dl_indication)
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
}
|
||||
return(decoderState);
|
||||
}
|
||||
// printf("polar decoder output 0x%08x\n",pbch_a_prime);
|
||||
// Decoder reversal
|
||||
pbch_a_prime = (uint32_t)reverse_bits(pbch_a_prime, NR_POLAR_PBCH_PAYLOAD_BITS);
|
||||
@@ -462,14 +452,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
|
||||
#endif
|
||||
|
||||
if (ue) {
|
||||
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, (void *)result, NULL);
|
||||
|
||||
if (ue->if_inst && ue->if_inst->dl_indication)
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
}
|
||||
|
||||
TracyCZoneEnd(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -267,6 +267,12 @@ typedef struct {
|
||||
int used_by_ue;
|
||||
} nrUE_cell_params_t;
|
||||
|
||||
typedef enum {
|
||||
NO_SCAN = 0,
|
||||
SCAN_BW,
|
||||
SCAN_BAND,
|
||||
} nr_ue_scan_enum_t;
|
||||
|
||||
/// Top-level PHY Data Structure for UE
|
||||
typedef struct PHY_VARS_NR_UE_s {
|
||||
/// \brief Module ID indicator for this instance
|
||||
@@ -278,7 +284,7 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
/// \brief Indicator that UE should perform band scanning
|
||||
int UE_scan;
|
||||
/// \brief Indicator that UE should perform coarse scanning around carrier
|
||||
int UE_scan_carrier;
|
||||
nr_ue_scan_enum_t UE_scan_carrier;
|
||||
/// \brief Indicator that UE should enable estimation and compensation of frequency offset
|
||||
int UE_fo_compensation;
|
||||
/// IF frequency for RF
|
||||
@@ -329,7 +335,6 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
NR_UE_COMMON common_vars;
|
||||
|
||||
nr_ue_if_module_t *if_inst;
|
||||
bool received_config_request;
|
||||
fapi_nr_config_request_t nrUE_config;
|
||||
nr_synch_request_t synch_request;
|
||||
|
||||
|
||||
@@ -378,8 +378,7 @@ void nr_ue_phy_config_request(nr_phy_config_t *phy_config)
|
||||
{
|
||||
PHY_VARS_NR_UE *phy = PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id];
|
||||
fapi_nr_config_request_t *nrUE_config = &phy->nrUE_config;
|
||||
if(phy_config != NULL) {
|
||||
phy->received_config_request = true;
|
||||
if (phy_config != NULL) {
|
||||
memcpy(nrUE_config, &phy_config->config_req, sizeof(fapi_nr_config_request_t));
|
||||
}
|
||||
}
|
||||
@@ -396,7 +395,6 @@ void nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config)
|
||||
PHY_VARS_NR_UE *phy = PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id];
|
||||
sl_nr_phy_config_request_t *sl_config = &phy->SL_UE_PHY_PARAMS.sl_config;
|
||||
if (phy_config != NULL) {
|
||||
phy->received_config_request = true;
|
||||
memcpy(sl_config, &phy_config->sl_config_req, sizeof(sl_nr_phy_config_request_t));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,6 +465,17 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
|
||||
ue->frame_parms.samples_per_frame_wCP,
|
||||
rxdataF);
|
||||
|
||||
nr_downlink_indication_t dl_indication;
|
||||
fapi_nr_rx_indication_t rx_ind = {0};
|
||||
const uint16_t number_pdus = 1;
|
||||
|
||||
void *pbch_result = ret ? NULL : &result;
|
||||
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, pbch_result, NULL);
|
||||
|
||||
if (ue->if_inst && ue->if_inst->dl_indication)
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
|
||||
if (ret==0) {
|
||||
T(T_NRUE_PHY_MIB, T_INT(frame_rx), T_INT(nr_slot_rx),
|
||||
T_INT(ssb_index), T_BUFFER(result.decoded_output, 3));
|
||||
@@ -909,10 +920,10 @@ static bool check_meas_to_perform(PHY_VARS_NR_UE *ue, int nr_slot_rx)
|
||||
|
||||
static bool is_ssb_index_transmitted(const PHY_VARS_NR_UE *ue, const int index)
|
||||
{
|
||||
if (ue->received_config_request) {
|
||||
const fapi_nr_config_request_t *cfg = &ue->nrUE_config;
|
||||
const fapi_nr_config_request_t *cfg = &ue->nrUE_config;
|
||||
if (GETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_SSB)) {
|
||||
const uint32_t curr_mask = cfg->ssb_table.ssb_mask_list[index / 32].ssb_mask;
|
||||
return ((curr_mask >> (31 - (index % 32))) & 0x01);
|
||||
return GETBIT(curr_mask, (31 - (index % 32)));
|
||||
} else
|
||||
return ue->frame_parms.ssb_index == index;
|
||||
}
|
||||
@@ -1004,7 +1015,8 @@ int pbch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_da
|
||||
// checking if current frame is compatible with SSB periodicity
|
||||
|
||||
const int default_ssb_period = 2;
|
||||
const int ssb_period = ue->received_config_request ? ue->nrUE_config.ssb_table.ssb_period : default_ssb_period;
|
||||
const fapi_nr_config_request_t *cfg = &ue->nrUE_config;
|
||||
const int ssb_period = GETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_SSB) ? cfg->ssb_table.ssb_period : default_ssb_period;
|
||||
if (ssb_period == 0 || !(frame_rx % (1 << (ssb_period - 1)))) {
|
||||
const int estimateSz = fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
// loop over SSB blocks
|
||||
|
||||
@@ -449,6 +449,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
NR_SIB1_t *sib1;
|
||||
bool can_start_ra;
|
||||
int ssb_arfcn;
|
||||
} nr_mac_rrc_config_sib1_t;
|
||||
typedef struct {
|
||||
NR_SIB19_r17_t *sib19;
|
||||
@@ -458,6 +459,7 @@ typedef struct {
|
||||
} nr_mac_rrc_config_other_sib_t;
|
||||
typedef struct {
|
||||
int get_sib;
|
||||
int ssb_arfcn;
|
||||
} nr_mac_rrc_sched_sib_t;
|
||||
|
||||
|
||||
|
||||
@@ -3518,52 +3518,14 @@ uint32_t get_Y(const NR_SearchSpace_t *ss, int slot, rnti_t rnti) {
|
||||
return Y;
|
||||
}
|
||||
|
||||
void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||||
frame_t frameP,
|
||||
const NR_MIB_t *mib,
|
||||
uint8_t num_slot_per_frame,
|
||||
uint8_t ssb_subcarrier_offset,
|
||||
uint16_t ssb_start_symbol,
|
||||
NR_SubcarrierSpacing_t scs_ssb,
|
||||
frequency_range_t frequency_range,
|
||||
int nr_band,
|
||||
int grid_size,
|
||||
uint32_t ssb_index,
|
||||
uint32_t ssb_period,
|
||||
uint32_t ssb_offset_point_a)
|
||||
void fill_type0_PDCCH_coreset_config(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||||
const uint32_t scs_ssb,
|
||||
const uint32_t scs_pdcch,
|
||||
const uint32_t index_4msb,
|
||||
const channel_bandwidth_t min_channel_bw,
|
||||
const bool is_condition_A,
|
||||
const uint32_t ssb_offset_point_a)
|
||||
{
|
||||
// according to Table 5.3.5-1 in 38.104
|
||||
// band 79 is the only one which minimum is 40
|
||||
// for all the other channels it is either 10 or 5
|
||||
// and there is no difference between the two for this implementation so it is set it to 10
|
||||
channel_bandwidth_t min_channel_bw;
|
||||
if (nr_band == 79)
|
||||
min_channel_bw = bw_40MHz;
|
||||
else
|
||||
min_channel_bw = bw_10MHz;
|
||||
|
||||
NR_SubcarrierSpacing_t scs_pdcch;
|
||||
if (frequency_range == FR2) {
|
||||
if(mib->subCarrierSpacingCommon == NR_MIB__subCarrierSpacingCommon_scs15or60)
|
||||
scs_pdcch = NR_SubcarrierSpacing_kHz60;
|
||||
else
|
||||
scs_pdcch = NR_SubcarrierSpacing_kHz120;
|
||||
} else {
|
||||
frequency_range = FR1;
|
||||
if(mib->subCarrierSpacingCommon == NR_MIB__subCarrierSpacingCommon_scs15or60)
|
||||
scs_pdcch = NR_SubcarrierSpacing_kHz15;
|
||||
else
|
||||
scs_pdcch = NR_SubcarrierSpacing_kHz30;
|
||||
}
|
||||
type0_PDCCH_CSS_config->scs_pdcch = scs_pdcch;
|
||||
type0_PDCCH_CSS_config->ssb_index = ssb_index;
|
||||
type0_PDCCH_CSS_config->frame = frameP;
|
||||
|
||||
uint8_t ssb_slot = ssb_start_symbol / 14;
|
||||
uint32_t is_condition_A = (ssb_subcarrier_offset == 0); // 38.213 ch.13
|
||||
uint32_t index_4msb = (mib->pdcch_ConfigSIB1.controlResourceSetZero);
|
||||
uint32_t index_4lsb = (mib->pdcch_ConfigSIB1.searchSpaceZero);
|
||||
|
||||
type0_PDCCH_CSS_config->num_rbs = -1;
|
||||
type0_PDCCH_CSS_config->num_symbols = -1;
|
||||
type0_PDCCH_CSS_config->rb_offset = -1;
|
||||
@@ -3683,22 +3645,25 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD
|
||||
min_channel_bw);
|
||||
break;
|
||||
}
|
||||
|
||||
type0_PDCCH_CSS_config->cset_start_rb = ssb_offset_point_a - type0_PDCCH_CSS_config->rb_offset;
|
||||
LOG_D(NR_MAC,
|
||||
"Coreset0: index_4msb=%d, num_rbs=%d, num_symb=%d, rb_offset=%d\n",
|
||||
index_4msb,
|
||||
type0_PDCCH_CSS_config->num_rbs,
|
||||
type0_PDCCH_CSS_config->num_symbols,
|
||||
type0_PDCCH_CSS_config->rb_offset);
|
||||
}
|
||||
|
||||
AssertFatal(type0_PDCCH_CSS_config->num_rbs != -1,
|
||||
"Type0 PDCCH coreset num_rbs undefined, index_4msb=%d, min_channel_bw %d, scs_ssb %d, scs_pdcch %d\n",
|
||||
index_4msb,
|
||||
min_channel_bw,
|
||||
(int)scs_ssb,
|
||||
(int)scs_pdcch);
|
||||
AssertFatal(type0_PDCCH_CSS_config->num_symbols != -1, "Type0 PDCCH coreset num_symbols undefined");
|
||||
AssertFatal(type0_PDCCH_CSS_config->rb_offset != -1, "Type0 PDCCH coreset rb_offset undefined");
|
||||
void fill_type0_PDCCH_search_space_config(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||||
const uint32_t index_4lsb,
|
||||
const uint32_t scs_ssb,
|
||||
const uint32_t scs_pdcch,
|
||||
const uint32_t ssb_start_symbol,
|
||||
const frequency_range_t frequency_range,
|
||||
const uint32_t num_slot_per_frame,
|
||||
const uint32_t ssb_period)
|
||||
{
|
||||
const uint8_t ssb_slot = ssb_start_symbol / 14;
|
||||
|
||||
// type0-pdcch search space
|
||||
float big_o = 0.0f;
|
||||
@@ -3850,8 +3815,87 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD
|
||||
type0_PDCCH_CSS_config->search_space_frame_period = ssb_period * slots_per_frame;
|
||||
}
|
||||
AssertFatal(type0_PDCCH_CSS_config->slot != UINT_MAX, "type0_PDCCH_CSS_config slot not configured");
|
||||
}
|
||||
|
||||
channel_bandwidth_t get_type0_PDCCH_min_channel_bw(const int nr_band)
|
||||
{
|
||||
// according to Table 5.3.5-1 in 38.104
|
||||
// band 79 is the only one which minimum is 40
|
||||
// for all the other channels it is either 10 or 5
|
||||
// and there is no difference between the two for this implementation so it is set it to 10
|
||||
if (nr_band == 79)
|
||||
return bw_40MHz;
|
||||
else
|
||||
return bw_10MHz;
|
||||
}
|
||||
|
||||
NR_SubcarrierSpacing_t get_type0_PDCCH_scs(const frequency_range_t frequency_range, const long scs_common)
|
||||
{
|
||||
if (frequency_range == FR2) {
|
||||
if (scs_common == NR_MIB__subCarrierSpacingCommon_scs15or60)
|
||||
return NR_SubcarrierSpacing_kHz60;
|
||||
else
|
||||
return NR_SubcarrierSpacing_kHz120;
|
||||
} else if (frequency_range == FR1) {
|
||||
if (scs_common == NR_MIB__subCarrierSpacingCommon_scs15or60)
|
||||
return NR_SubcarrierSpacing_kHz15;
|
||||
else
|
||||
return NR_SubcarrierSpacing_kHz30;
|
||||
} else
|
||||
AssertFatal(false, "Invalid frequency range %d\n", frequency_range);
|
||||
}
|
||||
|
||||
void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||||
frame_t frameP,
|
||||
const NR_MIB_t *mib,
|
||||
uint8_t num_slot_per_frame,
|
||||
uint8_t ssb_subcarrier_offset,
|
||||
uint16_t ssb_start_symbol,
|
||||
NR_SubcarrierSpacing_t scs_ssb,
|
||||
frequency_range_t frequency_range,
|
||||
int nr_band,
|
||||
int grid_size,
|
||||
uint32_t ssb_index,
|
||||
uint32_t ssb_period,
|
||||
uint32_t ssb_offset_point_a)
|
||||
{
|
||||
const NR_SubcarrierSpacing_t scs_pdcch = get_type0_PDCCH_scs(frequency_range, mib->subCarrierSpacingCommon);
|
||||
const channel_bandwidth_t min_channel_bw = get_type0_PDCCH_min_channel_bw(nr_band);
|
||||
|
||||
type0_PDCCH_CSS_config->scs_pdcch = scs_pdcch;
|
||||
type0_PDCCH_CSS_config->ssb_index = ssb_index;
|
||||
type0_PDCCH_CSS_config->frame = frameP;
|
||||
|
||||
bool is_condition_A = (ssb_subcarrier_offset == 0); // 38.213 ch.13
|
||||
uint32_t index_4msb = (mib->pdcch_ConfigSIB1.controlResourceSetZero);
|
||||
uint32_t index_4lsb = (mib->pdcch_ConfigSIB1.searchSpaceZero);
|
||||
|
||||
fill_type0_PDCCH_coreset_config(type0_PDCCH_CSS_config,
|
||||
scs_ssb,
|
||||
scs_pdcch,
|
||||
index_4msb,
|
||||
min_channel_bw,
|
||||
is_condition_A,
|
||||
ssb_offset_point_a);
|
||||
|
||||
AssertFatal(type0_PDCCH_CSS_config->num_rbs != -1,
|
||||
"Type0 PDCCH coreset num_rbs undefined, index_4msb=%d, min_channel_bw %d, scs_ssb %d, scs_pdcch %d\n",
|
||||
index_4msb,
|
||||
min_channel_bw,
|
||||
(int)scs_ssb,
|
||||
(int)scs_pdcch);
|
||||
AssertFatal(type0_PDCCH_CSS_config->num_symbols != -1, "Type0 PDCCH coreset num_symbols undefined");
|
||||
AssertFatal(type0_PDCCH_CSS_config->rb_offset != -1, "Type0 PDCCH coreset rb_offset undefined");
|
||||
|
||||
fill_type0_PDCCH_search_space_config(type0_PDCCH_CSS_config,
|
||||
index_4lsb,
|
||||
scs_ssb,
|
||||
scs_pdcch,
|
||||
ssb_start_symbol,
|
||||
frequency_range,
|
||||
num_slot_per_frame,
|
||||
ssb_period);
|
||||
|
||||
type0_PDCCH_CSS_config->cset_start_rb = ssb_offset_point_a - type0_PDCCH_CSS_config->rb_offset;
|
||||
AssertFatal(type0_PDCCH_CSS_config->cset_start_rb >= 0,
|
||||
"Invalid CSET0 start PRB %d SSB offset point A %d RB offset %d\n",
|
||||
type0_PDCCH_CSS_config->cset_start_rb,
|
||||
|
||||
@@ -207,6 +207,18 @@ uint32_t nr_compute_tbslbrm(uint16_t table,
|
||||
uint16_t nb_rb,
|
||||
uint8_t Nl);
|
||||
|
||||
channel_bandwidth_t get_type0_PDCCH_min_channel_bw(const int nr_band);
|
||||
|
||||
NR_SubcarrierSpacing_t get_type0_PDCCH_scs(const frequency_range_t frequency_range, const long scs_common);
|
||||
|
||||
void fill_type0_PDCCH_coreset_config(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||||
const uint32_t scs_ssb,
|
||||
const uint32_t scs_pdcch,
|
||||
const uint32_t index_4msb,
|
||||
const channel_bandwidth_t min_channel_bw,
|
||||
const bool is_condition_A,
|
||||
const uint32_t ssb_offset_point_a);
|
||||
|
||||
void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||||
frame_t frameP,
|
||||
const NR_MIB_t *mib,
|
||||
|
||||
@@ -102,7 +102,33 @@ static void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table, const frame_str
|
||||
}
|
||||
}
|
||||
|
||||
static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommonSIB_t *scc, int cc_idP)
|
||||
static uint32_t get_pointA_frequency(const int arfcn_ssb,
|
||||
const int k_ssb,
|
||||
const int offsetToPointA,
|
||||
const int system_mu,
|
||||
const int scc_common,
|
||||
const int nr_band,
|
||||
const frequency_range_t fr)
|
||||
{
|
||||
const uint32_t ssb_center = from_nrarfcn(nr_band, system_mu, arfcn_ssb) / 1000;
|
||||
const uint32_t ssb_prbs = 20;
|
||||
const uint32_t scs_khz = MU_SCS(system_mu);
|
||||
const uint32_t ssb_start = ssb_center - (ssb_prbs / 2 * NR_NB_SC_PER_RB * scs_khz);
|
||||
uint32_t pointA;
|
||||
if (fr == FR1) {
|
||||
const uint32_t ssb_crb_start = ssb_start - ((k_ssb >> system_mu) * scs_khz);
|
||||
pointA = ssb_crb_start - (((offsetToPointA * NR_NB_SC_PER_RB) >> system_mu) * scs_khz);
|
||||
} else {
|
||||
AssertFatal(system_mu >= 2, "Invalid numerology %d for FR2\n", system_mu);
|
||||
/* for FR2, mu of k_ssb is subCarrierSpacingCommon as specified in 38.211 7.4.3.1 */
|
||||
const uint32_t ssb_crb_start = ssb_start - ((k_ssb >> (system_mu - scc_common)) * scs_khz);
|
||||
/* FR2, offsetToPointA represented as 60kHz SCS */
|
||||
pointA = ssb_crb_start - (((offsetToPointA * NR_NB_SC_PER_RB) >> (system_mu - 2)) * scs_khz);
|
||||
}
|
||||
return pointA;
|
||||
}
|
||||
|
||||
static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommonSIB_t *scc, int cc_idP, const int arfcn_ssb)
|
||||
{
|
||||
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
|
||||
mac->phy_config.Mod_id = mac->ue_id;
|
||||
@@ -119,18 +145,31 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
|
||||
int bw_index = get_supported_band_index(frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
|
||||
mac->frequency_range,
|
||||
frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth);
|
||||
SETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_CARRIER);
|
||||
cfg->carrier_config.dl_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index);
|
||||
|
||||
/** Only set frequency if not already initialized (e.g., from handover reconfigurationWithSync)
|
||||
* MAC maintains its own frequency state, don't overwrite it with command-line parameter which
|
||||
* is related to the initial cell selection. */
|
||||
if (cfg->carrier_config.dl_frequency == 0) {
|
||||
// Initial cell selection: derive from command-line parameter
|
||||
uint64_t dl_bw_khz = (12 * frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth) *
|
||||
(15 << frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing);
|
||||
cfg->carrier_config.dl_frequency = mac->dl_frequency / 1000 - (dl_bw_khz >> 1);
|
||||
// Initial cell selection: derive from SIB1 parameter
|
||||
const frequency_range_t fr = mac->frequency_range;
|
||||
const int sccCommon = (fr == FR2) ? (2 + mac->mib->subCarrierSpacingCommon) : mac->mib->subCarrierSpacingCommon;
|
||||
const uint32_t pointA = get_pointA_frequency(arfcn_ssb,
|
||||
mac->ssb_subcarrier_offset,
|
||||
frequencyInfoDL->offsetToPointA,
|
||||
mac->numerology,
|
||||
sccCommon,
|
||||
mac->nr_band,
|
||||
fr);
|
||||
cfg->carrier_config.dl_frequency = pointA;
|
||||
// Update cset0 start RB
|
||||
NR_Type0_PDCCH_CSS_config_t *cset0 = &mac->type0_PDCCH_CSS_config;
|
||||
// FR2, offsetToPointA represented as 60kHz SCS
|
||||
const int offsetToPointA_mu = (fr == FR2) ? mac->numerology - 2 : mac->numerology;
|
||||
cset0->cset_start_rb = (frequencyInfoDL->offsetToPointA >> offsetToPointA_mu) - cset0->rb_offset;
|
||||
LOG_I(NR_MAC,
|
||||
"[UE %d] Initial cell selection: dl_frequency=%u kHz (from command-line, band=%d, scs=%ld)\n",
|
||||
"[UE %d] Initial cell selection: dl_frequency=%u kHz (from SIB1, band=%d, scs=%ld)\n",
|
||||
mac->ue_id,
|
||||
cfg->carrier_config.dl_frequency,
|
||||
mac->nr_band,
|
||||
@@ -195,11 +234,13 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
|
||||
|
||||
frame_type_t frame_type = get_frame_type(mac->nr_band, mac->numerology);
|
||||
// cell config
|
||||
SETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_CELL);
|
||||
cfg->cell_config.phy_cell_id = mac->physCellId;
|
||||
cfg->cell_config.frame_duplex_type = frame_type;
|
||||
cfg->cell_config.N_TA_offset = get_ta_offset(scc->n_TimingAdvanceOffset);
|
||||
|
||||
// SSB config
|
||||
SETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_SSB);
|
||||
cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower;
|
||||
cfg->ssb_config.scs_common = mac->numerology;
|
||||
|
||||
@@ -228,10 +269,12 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
|
||||
&mac->frame_structure);
|
||||
|
||||
// TDD Table Configuration
|
||||
SETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_TDD);
|
||||
if (cfg->cell_config.frame_duplex_type == TDD)
|
||||
set_tdd_config_nr_ue(&cfg->tdd_table, &mac->frame_structure);
|
||||
|
||||
// PRACH configuration
|
||||
SETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_PRACH);
|
||||
uint8_t nb_preambles = 64;
|
||||
NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup;
|
||||
if(rach_ConfigCommon->totalNumberOfRA_Preambles != NULL)
|
||||
@@ -437,6 +480,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t
|
||||
|
||||
AssertFatal(scc->downlinkConfigCommon, "Not expecting downlinkConfigCommon to be NULL here\n");
|
||||
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
|
||||
SETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_CARRIER);
|
||||
if (frequencyInfoDL) { // NeedM for inter-freq handover
|
||||
mac->nr_band = *frequencyInfoDL->frequencyBandList.list.array[0];
|
||||
frame_type = get_frame_type(mac->nr_band, mac->numerology);
|
||||
@@ -505,11 +549,13 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t
|
||||
}
|
||||
|
||||
// cell config
|
||||
SETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_CELL);
|
||||
cfg->cell_config.phy_cell_id = *scc->physCellId;
|
||||
cfg->cell_config.frame_duplex_type = frame_type;
|
||||
cfg->cell_config.N_TA_offset = get_ta_offset(scc->n_TimingAdvanceOffset);
|
||||
|
||||
// SSB config
|
||||
SETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_SSB);
|
||||
cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower;
|
||||
cfg->ssb_config.scs_common = *scc->ssbSubcarrierSpacing;
|
||||
|
||||
@@ -556,10 +602,12 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t
|
||||
&mac->frame_structure);
|
||||
|
||||
// TDD Table Configuration
|
||||
SETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_TDD);
|
||||
if (cfg->cell_config.frame_duplex_type == TDD)
|
||||
set_tdd_config_nr_ue(&cfg->tdd_table, &mac->frame_structure);
|
||||
|
||||
// PRACH configuration
|
||||
SETBIT(cfg->config_mask, PHY_CONFIG_BIT_MASK_PRACH);
|
||||
uint8_t nb_preambles = 64;
|
||||
if (scc->uplinkConfigCommon && scc->uplinkConfigCommon->initialUplinkBWP
|
||||
&& scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon) { // all NeedM
|
||||
@@ -1082,13 +1130,77 @@ static void update_mib_conf(NR_MIB_t *target, NR_MIB_t *source)
|
||||
target->intraFreqReselection = source->intraFreqReselection;
|
||||
}
|
||||
|
||||
void configure_ue_phy_for_sib1_reception(NR_UE_MAC_INST_t *mac, const int cc_id, const long ssb_arfcn)
|
||||
{
|
||||
const int ssb_scs = mac->numerology;
|
||||
int ssb_sc_offset_norm;
|
||||
if (mac->ssb_subcarrier_offset < 24 && mac->frequency_range == FR1)
|
||||
ssb_sc_offset_norm = mac->ssb_subcarrier_offset >> ssb_scs;
|
||||
else
|
||||
ssb_sc_offset_norm = mac->ssb_subcarrier_offset;
|
||||
|
||||
const NR_SubcarrierSpacing_t scs_pdcch = get_type0_PDCCH_scs(mac->frequency_range, mac->mib->subCarrierSpacingCommon);
|
||||
const channel_bandwidth_t min_ch_bw = get_type0_PDCCH_min_channel_bw(mac->nr_band);
|
||||
const uint32_t index_4msb = (mac->mib->pdcch_ConfigSIB1.controlResourceSetZero);
|
||||
|
||||
NR_Type0_PDCCH_CSS_config_t dummy_cset0 = {0};
|
||||
/* first we obtain RB offset of type 0 PDCCH from MIB */
|
||||
fill_type0_PDCCH_coreset_config(&dummy_cset0, ssb_scs, scs_pdcch, index_4msb, min_ch_bw, (ssb_sc_offset_norm == 0), 0);
|
||||
/* SC offset from current point A to CRB SSB start */
|
||||
const int ssb_sc_crb_offset_point_a = mac->ssb_start_subcarrier - ssb_sc_offset_norm;
|
||||
/* check if type0 PDCCH is within current bandwidth */
|
||||
/* Here we don't consider cset_start_rb from NR_Type0_PDCCH_CSS_config_t becuase the varialbe has PRB granularity but
|
||||
the UE could have arbitrary SC as the start RB. This is because the UE can start with a center frequency that is
|
||||
not PRB aligned wrt the gNB. Hence, the following code uses type0 coreset start SC computed from current point A. */
|
||||
int type0cset_start_sc = ssb_sc_crb_offset_point_a - dummy_cset0.rb_offset * NR_NB_SC_PER_RB;
|
||||
int pointA_adj = 0;
|
||||
if (type0cset_start_sc < 0) { // type 0 PDCCH coreset starts below current point A
|
||||
pointA_adj = type0cset_start_sc;
|
||||
type0cset_start_sc = 0; // adjusted start SC
|
||||
} else {
|
||||
/* check if cset0 start is PRB aligned with current point A. PHY can only handle PDCCH config with RB start wrt point A. */
|
||||
pointA_adj = type0cset_start_sc % NR_NB_SC_PER_RB;
|
||||
type0cset_start_sc -= pointA_adj;
|
||||
}
|
||||
|
||||
AssertFatal(dummy_cset0.num_rbs <= mac->N_RB_DL, "Cannot receive SIB1 with current configured bandwidth %d\n", mac->N_RB_DL);
|
||||
|
||||
const int type0cset_stop_sc = type0cset_start_sc + dummy_cset0.num_rbs * NR_NB_SC_PER_RB;
|
||||
if (type0cset_stop_sc > mac->N_RB_DL * NR_NB_SC_PER_RB) // type 0 PDCCH coreset goes beyond current bw
|
||||
pointA_adj += type0cset_stop_sc - mac->N_RB_DL * NR_NB_SC_PER_RB;
|
||||
|
||||
if (pointA_adj == 0) // no need to change carrier freq
|
||||
return;
|
||||
|
||||
LOG_I(NR_MAC, "Current SSB ARFCN %ld\n", ssb_arfcn);
|
||||
LOG_I(NR_MAC, "Adjusting center frequency by %d sub carriers\n", pointA_adj);
|
||||
const uint32_t ssb_abs_freq = from_nrarfcn(mac->nr_band, ssb_scs, ssb_arfcn) / 1000; // in khz
|
||||
const uint32_t ssb_rbs = 20;
|
||||
const uint32_t scs_khz = MU_SCS(ssb_scs);
|
||||
const uint32_t ssb_start_abs_freq = ssb_abs_freq - ssb_rbs / 2 * NR_NB_SC_PER_RB * scs_khz;
|
||||
const uint32_t pointA_abs_current = ssb_start_abs_freq - mac->ssb_start_subcarrier * scs_khz;
|
||||
const uint32_t pointA_abs_new = pointA_abs_current + pointA_adj * scs_khz;
|
||||
|
||||
/* set new center frequency to receive SIB1 */
|
||||
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
|
||||
cfg->carrier_config.dl_frequency = pointA_abs_new;
|
||||
cfg->carrier_config.uplink_frequency = cfg->carrier_config.dl_frequency;
|
||||
/* send sync request so PHY can sync again with new carrier freq */
|
||||
mac->synch_request.Mod_id = mac->ue_id;
|
||||
mac->synch_request.CC_id = cc_id;
|
||||
fapi_nr_synch_request_t s = {.target_Nid_cell = mac->physCellId, .ssb_bw_scan = false, .ssb_arfcn = ssb_arfcn};
|
||||
mac->synch_request.synch_req = s;
|
||||
mac->if_module->synch_request(&mac->synch_request);
|
||||
mac->if_module->phy_config_request(&mac->phy_config);
|
||||
}
|
||||
|
||||
static bool is_cset0_present(frequency_range_t const fr, uint8_t const kssb)
|
||||
{
|
||||
// TS 38.213 4.1 defines if CORESET 0 is present or not based on Kssb
|
||||
return (fr == FR1) ? (kssb < 24) : (kssb < 12);
|
||||
}
|
||||
|
||||
void nr_rrc_mac_sched_sib(module_id_t module_id, int sched_sib)
|
||||
void nr_rrc_mac_sched_sib(module_id_t module_id, int cc_idP, int sched_sib, const long ssb_arfcn)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
if (sched_sib == 1) {
|
||||
@@ -1098,6 +1210,8 @@ void nr_rrc_mac_sched_sib(module_id_t module_id, int sched_sib)
|
||||
} else if (sched_sib > 1)
|
||||
mac->get_otherSI[sched_sib - 2] = true;
|
||||
|
||||
if (mac->get_sib1)
|
||||
configure_ue_phy_for_sib1_reception(mac, cc_idP, ssb_arfcn);
|
||||
if (mac->state == UE_NOT_SYNC && mac->get_sib1)
|
||||
mac->state = UE_RECEIVING_SIB;
|
||||
}
|
||||
@@ -1973,7 +2087,7 @@ static void configure_si_schedulingInfo(NR_UE_MAC_INST_t *mac,
|
||||
}
|
||||
}
|
||||
|
||||
void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1, bool can_start_ra)
|
||||
void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1, bool can_start_ra, int ssb_arfcn)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
int ret = pthread_mutex_lock(&mac->if_mutex);
|
||||
@@ -1989,7 +2103,7 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si
|
||||
UPDATE_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t);
|
||||
configure_si_schedulingInfo(mac, si_SchedulingInfo, si_SchedulingInfo_v1700);
|
||||
|
||||
config_common_ue_sa(mac, scc, cc_idP);
|
||||
config_common_ue_sa(mac, scc, cc_idP, ssb_arfcn);
|
||||
|
||||
// Build the list of all the valid/transmitted SSBs according to the config
|
||||
LOG_D(NR_MAC, "Build SSB list\n");
|
||||
@@ -2013,6 +2127,17 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si
|
||||
if (mac->state == UE_RECEIVING_SIB && can_start_ra)
|
||||
mac->state = UE_PERFORMING_RA;
|
||||
|
||||
const int new_ssb_start_sc = get_ssb_first_sc(mac->phy_config.config_req.carrier_config.dl_frequency,
|
||||
from_nrarfcn(mac->nr_band, mac->numerology, ssb_arfcn) / 1000,
|
||||
mac->numerology);
|
||||
/* send sync request only if center frequency changes */
|
||||
if (new_ssb_start_sc != mac->ssb_start_subcarrier) {
|
||||
mac->synch_request.Mod_id = mac->ue_id;
|
||||
mac->synch_request.CC_id = cc_idP;
|
||||
fapi_nr_synch_request_t s = {.target_Nid_cell = mac->physCellId, .ssb_bw_scan = false, .ssb_arfcn = ssb_arfcn};
|
||||
mac->synch_request.synch_req = s;
|
||||
mac->if_module->synch_request(&mac->synch_request);
|
||||
}
|
||||
mac->if_module->phy_config_request(&mac->phy_config);
|
||||
mac->phy_config.config_req.ntn_config.params_changed = false;
|
||||
ret = pthread_mutex_unlock(&mac->if_mutex);
|
||||
|
||||
@@ -586,6 +586,8 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
int ssb_start_subcarrier;
|
||||
uint64_t dl_frequency;
|
||||
int numerology;
|
||||
/// Initial bandwidth set in PHY
|
||||
uint16_t N_RB_DL;
|
||||
|
||||
NR_SSB_meas_t ssb_measurements[MAX_NB_SSB];
|
||||
NR_CSIRS_meas_t csirs_measurements;
|
||||
|
||||
@@ -63,8 +63,8 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id,
|
||||
NR_UE_NR_Capability_t *ue_Capability);
|
||||
|
||||
void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mibP, bool barred);
|
||||
void nr_rrc_mac_sched_sib(module_id_t module_id, int sched_sib);
|
||||
void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1, bool can_start_ra);
|
||||
void nr_rrc_mac_sched_sib(module_id_t module_id, int cc_idP, int sched_sib, long ssb_arfcn);
|
||||
void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1, bool can_start_ra, int ssb_arfcn);
|
||||
|
||||
struct position; /* forward declaration */
|
||||
void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19_r17, int hfn, int frame, bool can_start_ra);
|
||||
|
||||
@@ -155,6 +155,7 @@ void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id)
|
||||
mac->synch_request.Mod_id = mac->ue_id;
|
||||
mac->synch_request.CC_id = cc_id;
|
||||
mac->synch_request.synch_req.target_Nid_cell = -1;
|
||||
mac->synch_request.synch_req.ssb_bw_scan = true; // scan according to cmd line option
|
||||
mac->if_module->synch_request(&mac->synch_request);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -549,6 +549,7 @@ static const plmn_data_t plmn_data[] = {
|
||||
{208, 13, "Vivendi", "SFR FR"},
|
||||
{208, 14, "Iliad", "Free Mobile FR"},
|
||||
{208, 15, "Iliad", "Free Mobile FR"},
|
||||
{208, 16, "Iliad", "Free Mobile FR"},
|
||||
{208, 20, "Bouygues Telecom", "Bouygues FR"},
|
||||
{208, 21, "Bouygues Telecom", "Bouygues FR"},
|
||||
{208, 88, "Bouygues Telecom (Zones Blanches)", "Bouygues FR"},
|
||||
|
||||
@@ -134,7 +134,8 @@ void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id)
|
||||
case NR_MAC_RRC_CONFIG_SIB1: {
|
||||
NR_SIB1_t *sib1 = msg->payload.config_sib1.sib1;
|
||||
bool can_start_ra = msg->payload.config_sib1.can_start_ra;
|
||||
nr_rrc_mac_config_req_sib1(instance_id, 0, sib1, can_start_ra);
|
||||
int ssb_arfcn = msg->payload.config_sib1.ssb_arfcn;
|
||||
nr_rrc_mac_config_req_sib1(instance_id, 0, sib1, can_start_ra, ssb_arfcn);
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB1, msg->payload.config_sib1.sib1, ASFM_FREE_EVERYTHING);
|
||||
} break;
|
||||
case NR_MAC_RRC_CONFIG_OTHER_SIB: {
|
||||
@@ -145,7 +146,7 @@ void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id)
|
||||
msg->payload.config_other_sib.can_start_ra);
|
||||
} break;
|
||||
case NR_MAC_RRC_SCHED_SIB:
|
||||
nr_rrc_mac_sched_sib(instance_id, msg->payload.sched_sib.get_sib);
|
||||
nr_rrc_mac_sched_sib(instance_id, 0, msg->payload.sched_sib.get_sib, msg->payload.sched_sib.ssb_arfcn);
|
||||
break;
|
||||
case NR_MAC_RRC_RESUME_RB:
|
||||
nr_rrc_mac_resume_rb(instance_id, msg->payload.resume_rb.is_srb, msg->payload.resume_rb.rb_id);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "NR_UL-DCCH-Message.h"
|
||||
#include "uper_encoder.h"
|
||||
#include "uper_decoder.h"
|
||||
#include "NR_PLMN-Identity.h"
|
||||
|
||||
#include "rrc_defs.h"
|
||||
#include "rrc_proto.h"
|
||||
@@ -364,7 +365,7 @@ static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si,
|
||||
|
||||
static void nr_rrc_ue_prepare_RRCSetupRequest(NR_UE_RRC_INST_t *rrc)
|
||||
{
|
||||
LOG_D(NR_RRC, "Generation of RRCSetupRequest\n");
|
||||
LOG_A(NR_RRC, "Generation of RRCSetupRequest\n");
|
||||
uint8_t rv[6];
|
||||
// Get RRCConnectionRequest, fill random for now
|
||||
// Generate random byte stream for contention resolution
|
||||
@@ -464,6 +465,46 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf
|
||||
xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) sib1);
|
||||
LOG_A(NR_RRC, "SIB1 decoded\n");
|
||||
|
||||
// Print all PLMN in SIB1.
|
||||
const int n = sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.count;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
struct NR_PLMN_IdentityInfo__plmn_IdentityList *PLMN_identityInfoList =
|
||||
&sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.array[i]->plmn_IdentityList;
|
||||
for (int i2 = 0; i2 < PLMN_identityInfoList->list.count; i2++) {
|
||||
NR_PLMN_Identity_t *PLMN_id = PLMN_identityInfoList->list.array[i2];
|
||||
int mccdigits = PLMN_id->mcc->list.count;
|
||||
int mncdigits = PLMN_id->mnc.list.count;
|
||||
|
||||
int mcc;
|
||||
if (mccdigits == 2) {
|
||||
mcc = *PLMN_id->mcc->list.array[0] * 10 + *PLMN_id->mcc->list.array[1];
|
||||
} else {
|
||||
mcc = *PLMN_id->mcc->list.array[0] * 100 + *PLMN_id->mcc->list.array[1] * 10 + *PLMN_id->mcc->list.array[2];
|
||||
}
|
||||
|
||||
int mnc;
|
||||
if (mncdigits == 2) {
|
||||
mnc = *PLMN_id->mnc.list.array[0] * 10 + *PLMN_id->mnc.list.array[1];
|
||||
} else {
|
||||
mnc = *PLMN_id->mnc.list.array[0] * 100 + *PLMN_id->mnc.list.array[1] * 10 + *PLMN_id->mnc.list.array[2];
|
||||
}
|
||||
|
||||
LOG_A(NR_RRC, "PLMN %d.%d MCC %0*d, MNC %0*d\n", i + 1, i2 + 1, mccdigits, mcc, mncdigits, mnc);
|
||||
// search internal table for provider name
|
||||
const size_t num_plmn_data = sizeof(plmn_data) / sizeof(plmn_data[0]);
|
||||
for (size_t plmn_ind = 0;; ++plmn_ind) {
|
||||
if (plmn_ind == num_plmn_data) {
|
||||
LOG_W(NR_RRC, "Did not find operator name from internal table for MCC %0*d, MNC %0*d\n", mccdigits, mcc, mncdigits, mnc);
|
||||
break;
|
||||
}
|
||||
if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) {
|
||||
LOG_A(NR_RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plmn_id_t *plmn_id = malloc_or_fail(sizeof(plmn_id_t));
|
||||
|
||||
/* selected_plmn_identity is one-indexed */
|
||||
@@ -521,6 +562,7 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf
|
||||
nr_mac_rrc_config_sib1_t *config_sib1 = &rrc_msg.payload.config_sib1;
|
||||
config_sib1->sib1 = sib1;
|
||||
config_sib1->can_start_ra = !rrc->is_NTN_UE;
|
||||
config_sib1->ssb_arfcn = rrc->arfcn_ssb;
|
||||
nr_rrc_send_msg_to_mac(rrc, &rrc_msg);
|
||||
}
|
||||
|
||||
@@ -1922,6 +1964,7 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
nr_mac_rrc_message_t sib_msg = {0};
|
||||
sib_msg.payload_type = NR_MAC_RRC_SCHED_SIB;
|
||||
sib_msg.payload.sched_sib.get_sib = get_sib;
|
||||
sib_msg.payload.sched_sib.ssb_arfcn = ssb_arfcn;
|
||||
nr_rrc_send_msg_to_mac(rrc, &sib_msg);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -124,6 +124,29 @@ int check_ref_locked(usrp_state_t *s,size_t mboard) {
|
||||
return ref_locked;
|
||||
}
|
||||
|
||||
static int check_lo_locked(usrp_state_t *s, size_t channel)
|
||||
{
|
||||
std::vector<std::string> sensor_names = s->usrp->get_rx_sensor_names(channel);
|
||||
bool lo_locked = false;
|
||||
if (std::find(sensor_names.begin(), sensor_names.end(), "lo_locked") != sensor_names.end()) {
|
||||
LOG_W(HW, "lo_locked sensor not present on this board\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 30; i++) {
|
||||
lo_locked = s->usrp->get_rx_sensor("lo_locked", channel).to_bool();
|
||||
if (lo_locked) {
|
||||
LOG_I(HW, "LO Lock successful\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(5));
|
||||
}
|
||||
|
||||
LOG_W(HW, "LO Lock failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
static int sync_to_gps(openair0_device_t *device)
|
||||
{
|
||||
//uhd::set_thread_priority_safe();
|
||||
@@ -828,6 +851,13 @@ int trx_usrp_set_freq(openair0_device_t *device, openair0_config_t *openair0_cfg
|
||||
s->usrp->set_tx_freq(tx_tune_req);
|
||||
s->usrp->set_rx_freq(rx_tune_req);
|
||||
|
||||
for(int i=0; i<((int) s->usrp->get_rx_num_channels()); i++) {
|
||||
openair0_config_t *cfg = device->openair0_cfg;
|
||||
if (i < cfg->rx_num_channels) {
|
||||
check_lo_locked(s, i);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user