Commit 72bf1b1d authored by Robert Schmidt's avatar Robert Schmidt

Merge branch 'integration_2022_wk29' into 'develop'

integration_2022_wk29

See merge request oai/openairinterface5g!1619
parents 65c9af7d b1a3cbb0
...@@ -9,19 +9,19 @@ ...@@ -9,19 +9,19 @@
| Machine | IP address | Lockable Resource | Function | Connected devices | | Machine | IP address | Lockable Resource | Function | Connected devices |
| ------------- | --------------- | --------------------- | ------------------ | ----------------------------------------------------- | | ------------- | --------------- | --------------------- | ------------------ | ----------------------------------------------------- |
| asterix | 172.21.16.127 | CI-Asterix-Usage | gNB | 173.21.19.14 | | asterix | 172.21.16.127 | CI-Asterix-Usage | gNB (n78) | 173.21.19.14 |
| obelix | 172.21.16.128 | CI-Obelix-Usage | eNB, UE (5G) | 172.21.19.13, X300 (192.168.60.2), B200mini (30C51EB) | | obelix | 172.21.16.128 | CI-Obelix-Usage | eNB (n40, n78), nrUE | 172.21.19.13, X300 (192.168.60.2), B200mini (30C51EB) |
| porcepix | 172.21.16.136 | CI-NSA-MiniBench | Executor, EPC, 5GC | -- | | porcepix | 172.21.16.136 | CI-NSA-MiniBench | Executor, EPC, 5GC | -- |
| nrmodule2 | 172.21.16.139 | CI-NSA-MiniBench | Quectel | Quectel module | | nrmodule2 | 172.21.16.139 | CI-NSA-MiniBench | Quectel | Quectel module |
| nepes | 172.21.16.137 | CI-NSA-MiniBench | gNB | B200mini (30C51D4) | | nepes | 172.21.16.137 | CI-NSA-MiniBench | gNB (n78) | B200mini (30C51D4) |
| caracal | 172.21.16.132 | CI-Caracal | gNB/phytest | N300 (192.168.10.2) | | caracal | 172.21.16.132 | CI-Caracal | gNB/phytest | N300 (192.168.10.2) |
| idefix | 172.21.16.135 | CI-NSA-MiniBench | Quectel | Quectel module | | idefix | 172.21.16.135 | CI-NSA-MiniBench | Quectel | Quectel module |
| amariue | 172.21.16.144 | CI-Amarisoft-UE-Usage | TBD | Amarisoft UE simulator | | amariue | 172.21.16.144 | CI-Amarisoft-UE-Usage | nrUE | Amarisoft UE simulator |
| bellatrix | 192.168.117.115 | CI-RAN-VM-Deployment | Executor | -- | | bellatrix | 192.168.117.115 | CI-RAN-VM-Deployment | Executor | -- |
| nano | 192.168.12.62 | CI-Bench-1-Phones | EPC, adb | 2x COTS (adb) | | nano | 192.168.12.62 | CI-Bench-1-Phones | EPC, adb | 2x COTS (adb) |
| hutch | 192.168.12.19 | CI-Bench-1-Phones | eNB (B7) | B200mini (30C5239) | | hutch | 192.168.12.19 | CI-Bench-1-Phones | eNB (B7) | B200mini (30C5239) |
| starsky | 192.168.12.18 | CI-Bench-1-Phones | eNB (B40) | b200mini (30A3E3C) | | starsky | 192.168.12.18 | CI-Bench-1-Phones | eNB (B40) | b200mini (30A3E3C) |
| carabe | 192.168.12.211 | CI-Bench-2-OAI-Phone | UE 4G (B) | B200mini (30AE8C9) | | carabe | 192.168.12.211 | CI-Bench-2-OAI-Phone | UE (B7UE) | B200mini (30AE8C9) |
Note: The available resources, and their current usage, is indicated here: Note: The available resources, and their current usage, is indicated here:
- [Lockable resources of jenkins-oai](https://jenkins-oai.eurecom.fr/lockable-resources/): - [Lockable resources of jenkins-oai](https://jenkins-oai.eurecom.fr/lockable-resources/):
...@@ -40,7 +40,7 @@ Note: The available resources, and their current usage, is indicated here: ...@@ -40,7 +40,7 @@ Note: The available resources, and their current usage, is indicated here:
### OTA Testbench ### OTA Testbench
[Proper image to be followed up. TBD: add antennas/circulators] **Purpose**: Over-the-air 4G/5G (NSA/SA) tests
Note: obelix and porcepix are both used in the OTA testbench and the 5G Note: obelix and porcepix are both used in the OTA testbench and the 5G
NSA/Faraday Cage testbench! NSA/Faraday Cage testbench!
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
\draw (obelix) -- (b210o); \draw (obelix) -- (b210o);
\node[above right=0.35cm of faraday.south west] (antn) \node[above right=0.35cm of faraday.south west] (antn)
{\includegraphics[width=0.3cm]{antenna}}; {\includegraphics[width=0.3cm]{antenna}};
\draw (b210n) -| node [pos=0.2, duplexer] {B78} (antn); \draw (b210n) -| node [pos=0.2, duplexer] {n78} (antn);
\node[left=5cm of faraday, label=above:porcepix] (porcepix) \node[left=5cm of faraday, label=above:porcepix] (porcepix)
{\includegraphics[width=1.2cm]{server}}; {\includegraphics[width=1.2cm]{server}};
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
edge (porcepix); edge (porcepix);
\node[right=0.3cm of asterix, label=above:N310] (n310a) \node[right=0.3cm of asterix, label=above:N310] (n310a)
{\includegraphics[width=1.5cm]{n310}} edge (asterix); {\includegraphics[width=1.5cm]{n310}} edge (asterix);
\node[right=.2cm of n310a, duplexer] (b78o) {B78} edge (n310a); \node[right=.2cm of n310a, duplexer] (b78o) {n78} edge (n310a);
\node[below right=-0.1cm and 0.35cm of b78o.east] (anto1) \node[below right=-0.1cm and 0.35cm of b78o.east] (anto1)
{\includegraphics[width=0.3cm]{antenna}} edge (b78o); {\includegraphics[width=0.3cm]{antenna}} edge (b78o);
\node[above right=-0.1cm and 0.35cm of b78o.east] (anto2) \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2)
...@@ -32,20 +32,20 @@ ...@@ -32,20 +32,20 @@
edge (porcepix); edge (porcepix);
\node[above right=-0.5cm and 0.3cm of obelix, label=above:N310] (n310o) \node[above right=-0.5cm and 0.3cm of obelix, label=above:N310] (n310o)
{\includegraphics[width=1.5cm]{n310}} edge (obelix); {\includegraphics[width=1.5cm]{n310}} edge (obelix);
\node[right=.2cm of n310o, duplexer] (b78o) {B40} edge (n310o); \node[right=.2cm of n310o, duplexer] (b78o) {n40} edge (n310o);
\node[below right=-0.1cm and 0.35cm of b78o.east] (anto1) \node[below right=-0.1cm and 0.35cm of b78o.east] (anto1)
{\includegraphics[width=0.3cm]{antenna}} edge (b78o); {\includegraphics[width=0.3cm]{antenna}} edge (b78o);
\node[above right=-0.1cm and 0.35cm of b78o.east] (anto2) \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2)
{\includegraphics[width=0.3cm]{antenna}} edge (b78o); {\includegraphics[width=0.3cm]{antenna}} edge (b78o);
\node[below right=-0.5cm and 0.3cm of obelix, label=above:X310] (x310o) \node[below right=-0.5cm and 0.3cm of obelix, label=above:X310] (x310o)
{\includegraphics[width=1.5cm]{x310}} edge (obelix); {\includegraphics[width=1.5cm]{x310}} edge (obelix);
\node[right=.2cm of x310o, duplexer] (b78o) {B78} edge (x310o); \node[right=.2cm of x310o, duplexer] (b78o) {n78} edge (x310o);
\node[below right=-0.1cm and 0.35cm of b78o.east] (anto1) \node[below right=-0.1cm and 0.35cm of b78o.east] (anto1)
{\includegraphics[width=0.3cm]{antenna}} edge (b78o); {\includegraphics[width=0.3cm]{antenna}} edge (b78o);
\node[above right=-0.1cm and 0.35cm of b78o.east] (anto2) \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2)
{\includegraphics[width=0.3cm]{antenna}} edge (b78o); {\includegraphics[width=0.3cm]{antenna}} edge (b78o);
\node[right=5.0cm of n310o, label=above:RM500Q-GL] (quectel) \node[above right=-1.3cm and 5.0cm of n310a.east, label=above:RM500Q-GL] (quectel)
{\includegraphics[height=1.2cm]{quectel}}; {\includegraphics[height=1.2cm]{quectel}};
\node[above left=-0.1cm and 0.8cm of quectel.west] (aq2) \node[above left=-0.1cm and 0.8cm of quectel.west] (aq2)
{\includegraphics[width=0.3cm]{antenna}} edge (quectel); {\includegraphics[width=0.3cm]{antenna}} edge (quectel);
...@@ -59,5 +59,10 @@ ...@@ -59,5 +59,10 @@
{\includegraphics[width=1.2cm]{server}} {\includegraphics[width=1.2cm]{server}}
edge (quectel); edge (quectel);
\node[above right=-0.3cm and 5.0cm of x310o.east, label=above:amariue] (amariue)
{\includegraphics[height=1.2cm]{server}};
\node[left=0.8cm of amariue.west] (aa1)
{\includegraphics[width=0.3cm]{antenna}} edge (amariue);
\end{tikzpicture} \end{tikzpicture}
\end{document} \end{document}
...@@ -1666,41 +1666,34 @@ typedef struct ...@@ -1666,41 +1666,34 @@ typedef struct
} nfapi_nr_uci_indication_t; } nfapi_nr_uci_indication_t;
//3.4.10 srs_indication
//table 3-73
typedef struct /// 5G PHY FAPI Specification: SRS indication - Section 3.4.10, Table 3-73
{
uint8_t rb_snr;
}nfapi_nr_srs_indication_reported_symbol_resource_block_t;
typedef struct typedef struct {
{ uint8_t rb_snr; // SNR value in dB. Value: 0 -> 255 representing -64 dB to 63 dB with a step size 0.5 dB, 0xff will be set if this field is invalid.
uint16_t num_rbs; } nfapi_nr_srs_indication_reported_symbol_resource_block_t;
typedef struct {
uint16_t num_rbs; // Number of PRBs to be reported for this SRS PDU. Value: 0 -> 272.
nfapi_nr_srs_indication_reported_symbol_resource_block_t* rb_list; nfapi_nr_srs_indication_reported_symbol_resource_block_t* rb_list;
}nfapi_nr_srs_indication_reported_symbol_t; } nfapi_nr_srs_indication_reported_symbol_t;
#define NFAPI_NR_SRS_IND_MAX_PDU 100 typedef struct {
typedef struct uint32_t handle; // The handle passed to the PHY in the the UL_TTI.request SRS PDU.
{ uint16_t rnti; // The RNTI passed to the PHY in the UL_TTI.request SRS PDU. Value: 1 -> 65535.
uint32_t handle; uint16_t timing_advance; // Timing advance TA measured for the UE [TS 38.213, Section 4.2]. NTA_new = NTA_old + (TA − 31) * 16 * 64 / (2^u). Value: 0 -> 63. 0xffff should be set if this field is invalid.
uint16_t rnti; uint8_t num_symbols; // Number of symbols for SRS. Value: 1 -> 4. If a PHY does not report for individual symbols then this parameter should be set to 1.
uint16_t timing_advance; uint8_t wide_band_snr; // SNR value in dB measured within configured SRS bandwidth on each symbol. Value: 0 -> 255 representing -64 dB to 63 dB with a step size 0.5 dB. 0xff will be set if this field is invalid.
uint8_t num_symbols; uint8_t num_reported_symbols; // Number of symbols reported in this message. This allows PHY to report individual symbols or aggregated symbols where this field will be set to 1. Value: 1 -> 4.
uint8_t wide_band_snr;
uint8_t num_reported_symbols;
nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list; nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list;
} nfapi_nr_srs_indication_pdu_t;
}nfapi_nr_srs_indication_pdu_t; typedef struct {
typedef struct
{
nfapi_p7_message_header_t header; nfapi_p7_message_header_t header;
uint16_t sfn; uint16_t sfn; // SFN. Value: 0 -> 1023
uint16_t slot; uint16_t slot; // Slot. Value: 0 -> 159
uint8_t number_of_pdus; uint8_t number_of_pdus; // Number of PDUs included in this message. Value: 0 -> 255
nfapi_nr_srs_indication_pdu_t* pdu_list; nfapi_nr_srs_indication_pdu_t* pdu_list;
} nfapi_nr_srs_indication_t; } nfapi_nr_srs_indication_t;
......
...@@ -613,21 +613,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, ...@@ -613,21 +613,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
for (int id=0; id<NUMBER_OF_NR_SRS_MAX; id++) { for (int id=0; id<NUMBER_OF_NR_SRS_MAX; id++) {
gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t)); gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t));
gNB->nr_srs_info[id]->sc_list = (uint16_t *) malloc16_clear(6*fp->N_RB_UL*sizeof(uint16_t));
gNB->nr_srs_info[id]->srs_generated_signal = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
gNB->nr_srs_info[id]->noise_power = (uint32_t*)malloc16_clear(sizeof(uint32_t));
gNB->nr_srs_info[id]->srs_received_signal = (int32_t **)malloc16(Prx*sizeof(int32_t*));
gNB->nr_srs_info[id]->srs_ls_estimated_channel = (int32_t **)malloc16(Prx*sizeof(int32_t*));
gNB->nr_srs_info[id]->srs_estimated_channel_freq = (int32_t **)malloc16(Prx*sizeof(int32_t*));
gNB->nr_srs_info[id]->srs_estimated_channel_time = (int32_t **)malloc16(Prx*sizeof(int32_t*));
gNB->nr_srs_info[id]->srs_estimated_channel_time_shifted = (int32_t **)malloc16(Prx*sizeof(int32_t*));
for (i=0;i<Prx;i++){
gNB->nr_srs_info[id]->srs_received_signal[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
gNB->nr_srs_info[id]->srs_ls_estimated_channel[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
gNB->nr_srs_info[id]->srs_estimated_channel_freq[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
gNB->nr_srs_info[id]->srs_estimated_channel_time[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
gNB->nr_srs_info[id]->srs_estimated_channel_time_shifted[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
}
} }
generate_ul_reference_signal_sequences(SHRT_MAX); generate_ul_reference_signal_sequences(SHRT_MAX);
...@@ -785,21 +770,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) ...@@ -785,21 +770,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
free_and_zero(gNB->nr_csi_rs_info); free_and_zero(gNB->nr_csi_rs_info);
for (int id = 0; id < NUMBER_OF_NR_SRS_MAX; id++) { for (int id = 0; id < NUMBER_OF_NR_SRS_MAX; id++) {
for (int i = 0; i < Prx; i++) {
free_and_zero(gNB->nr_srs_info[id]->srs_received_signal[i]);
free_and_zero(gNB->nr_srs_info[id]->srs_ls_estimated_channel[i]);
free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_freq[i]);
free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_time[i]);
free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_time_shifted[i]);
}
free_and_zero(gNB->nr_srs_info[id]->sc_list);
free_and_zero(gNB->nr_srs_info[id]->srs_generated_signal);
free_and_zero(gNB->nr_srs_info[id]->noise_power);
free_and_zero(gNB->nr_srs_info[id]->srs_received_signal);
free_and_zero(gNB->nr_srs_info[id]->srs_ls_estimated_channel);
free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_freq);
free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_time);
free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_time_shifted);
free_and_zero(gNB->nr_srs_info[id]); free_and_zero(gNB->nr_srs_info[id]);
} }
......
...@@ -377,22 +377,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) ...@@ -377,22 +377,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
} }
ue->nr_srs_info = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t)); ue->nr_srs_info = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t));
ue->nr_srs_info->sc_list = (uint16_t *) malloc16_clear(6*fp->N_RB_UL*sizeof(uint16_t));
ue->nr_srs_info->srs_generated_signal = (int32_t *) malloc16_clear( (2*(fp->samples_per_frame)+2048)*sizeof(int32_t) );
ue->nr_srs_info->noise_power = (uint32_t*)malloc16_clear(sizeof(uint32_t));
ue->nr_srs_info->srs_received_signal = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
ue->nr_srs_info->srs_ls_estimated_channel = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
ue->nr_srs_info->srs_estimated_channel_freq = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
ue->nr_srs_info->srs_estimated_channel_time = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
ue->nr_srs_info->srs_estimated_channel_time_shifted = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
for (i=0; i<fp->nb_antennas_rx; i++) {
ue->nr_srs_info->srs_received_signal[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
ue->nr_srs_info->srs_ls_estimated_channel[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
ue->nr_srs_info->srs_estimated_channel_freq[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
ue->nr_srs_info->srs_estimated_channel_time[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
ue->nr_srs_info->srs_estimated_channel_time_shifted[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
}
// RACH // RACH
prach_vars[gNB_id]->prachF = (int16_t *)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) ); prach_vars[gNB_id]->prachF = (int16_t *)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) );
...@@ -520,21 +504,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) ...@@ -520,21 +504,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
free_and_zero(ue->nr_csi_rs_info->csi_rs_estimated_channel_freq); free_and_zero(ue->nr_csi_rs_info->csi_rs_estimated_channel_freq);
free_and_zero(ue->nr_csi_rs_info); free_and_zero(ue->nr_csi_rs_info);
for (int i = 0; i < fp->nb_antennas_rx; i++) {
free_and_zero(ue->nr_srs_info->srs_received_signal[i]);
free_and_zero(ue->nr_srs_info->srs_ls_estimated_channel[i]);
free_and_zero(ue->nr_srs_info->srs_estimated_channel_freq[i]);
free_and_zero(ue->nr_srs_info->srs_estimated_channel_time[i]);
free_and_zero(ue->nr_srs_info->srs_estimated_channel_time_shifted[i]);
}
free_and_zero(ue->nr_srs_info->sc_list);
free_and_zero(ue->nr_srs_info->srs_generated_signal);
free_and_zero(ue->nr_srs_info->noise_power);
free_and_zero(ue->nr_srs_info->srs_received_signal);
free_and_zero(ue->nr_srs_info->srs_ls_estimated_channel);
free_and_zero(ue->nr_srs_info->srs_estimated_channel_freq);
free_and_zero(ue->nr_srs_info->srs_estimated_channel_time);
free_and_zero(ue->nr_srs_info->srs_estimated_channel_time_shifted);
free_and_zero(ue->nr_srs_info); free_and_zero(ue->nr_srs_info);
free_and_zero(ue->csiim_vars[gNB_id]); free_and_zero(ue->csiim_vars[gNB_id]);
......
...@@ -67,6 +67,49 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) ...@@ -67,6 +67,49 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id)
return max_pos - sync_pos; return max_pos - sync_pos;
} }
int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms,
const int32_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]) {
int timing_advance = 0;
int max_val = 0;
for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) {
int temp = 0;
for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
int Re = ((c16_t*)srs_estimated_channel_time[aa])[i].r;
int Im = ((c16_t*)srs_estimated_channel_time[aa])[i].i;
temp += (Re*Re/2) + (Im*Im/2);
}
if (temp > max_val) {
timing_advance = i;
max_val = temp;
}
}
if (timing_advance > frame_parms->ofdm_symbol_size/2) {
timing_advance = timing_advance - frame_parms->ofdm_symbol_size;
}
// Scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size
const uint16_t bw_scaling = frame_parms->ofdm_symbol_size >> 7;
// do some integer rounding to improve TA accuracy
int sync_pos_rounded;
if (timing_advance > 0) {
sync_pos_rounded = timing_advance + (bw_scaling >> 1) - 1;
} else {
sync_pos_rounded = timing_advance - (bw_scaling >> 1) + 1;
}
int timing_advance_update = sync_pos_rounded / bw_scaling;
// put timing advance command in 0..63 range
timing_advance_update += 31;
if (timing_advance_update < 0) timing_advance_update = 0;
if (timing_advance_update > 63) timing_advance_update = 63;
return timing_advance_update;
}
void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB) { void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB) {
......
...@@ -949,9 +949,9 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, ...@@ -949,9 +949,9 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
}//Antenna loop }//Antenna loop
} }
uint32_t calc_power(uint16_t *x, uint32_t size) { uint32_t calc_power(const int16_t *x, const uint32_t size) {
uint64_t sum_x = 0; int64_t sum_x = 0;
uint64_t sum_x2 = 0; int64_t sum_x2 = 0;
for(int k = 0; k<size; k++) { for(int k = 0; k<size; k++) {
sum_x = sum_x + x[k]; sum_x = sum_x + x[k];
sum_x2 = sum_x2 + x[k]*x[k]; sum_x2 = sum_x2 + x[k]*x[k];
...@@ -959,28 +959,34 @@ uint32_t calc_power(uint16_t *x, uint32_t size) { ...@@ -959,28 +959,34 @@ uint32_t calc_power(uint16_t *x, uint32_t size) {
return sum_x2/size - (sum_x/size)*(sum_x/size); return sum_x2/size - (sum_x/size)*(sum_x/size);
} }
int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
int frame, const int frame,
int slot, const int slot,
nfapi_nr_srs_pdu_t *srs_pdu, const nfapi_nr_srs_pdu_t *srs_pdu,
nr_srs_info_t *nr_srs_info, const nr_srs_info_t *nr_srs_info,
int32_t *srs_generated_signal, const int32_t *srs_generated_signal,
int32_t **srs_received_signal, int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)],
int32_t **srs_estimated_channel_freq, int32_t srs_ls_estimated_channel[][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)],
int32_t **srs_estimated_channel_time, int32_t srs_estimated_channel_freq[][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)],
int32_t **srs_estimated_channel_time_shifted, int32_t srs_estimated_channel_time[][gNB->frame_parms.ofdm_symbol_size],
uint32_t *noise_power) { int32_t srs_estimated_channel_time_shifted[][gNB->frame_parms.ofdm_symbol_size],
uint32_t *signal_power,
uint32_t *noise_power_per_rb,
uint32_t *noise_power,
int8_t *snr_per_rb,
int8_t *snr) {
if(nr_srs_info->sc_list_length == 0) { if(nr_srs_info->sc_list_length == 0) {
LOG_E(NR_PHY, "(%d.%d) nr_srs_info was not generated yet!\n", frame, slot); LOG_E(NR_PHY, "(%d.%d) nr_srs_info was not generated yet!\n", frame, slot);
return -1; return -1;
} }
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
int32_t **srs_ls_estimated_channel = nr_srs_info->srs_ls_estimated_channel;
uint16_t noise_real[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length]; int16_t ch_real[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length];
uint16_t noise_imag[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length]; int16_t ch_imag[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length];
int16_t noise_real[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length];
int16_t noise_imag[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length];
int16_t ls_estimated[2]; int16_t ls_estimated[2];
...@@ -993,11 +999,11 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -993,11 +999,11 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) { for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) {
int16_t generated_real = srs_generated_signal[nr_srs_info->sc_list[sc_idx]] & 0xFFFF; int16_t generated_real = ((c16_t*)srs_generated_signal)[nr_srs_info->sc_list[sc_idx]].r;
int16_t generated_imag = (srs_generated_signal[nr_srs_info->sc_list[sc_idx]] >> 16) & 0xFFFF; int16_t generated_imag = ((c16_t*)srs_generated_signal)[nr_srs_info->sc_list[sc_idx]].i;
int16_t received_real = srs_received_signal[ant][nr_srs_info->sc_list[sc_idx]] & 0xFFFF; int16_t received_real = ((c16_t*)srs_received_signal[ant])[nr_srs_info->sc_list[sc_idx]].r;
int16_t received_imag = (srs_received_signal[ant][nr_srs_info->sc_list[sc_idx]] >> 16) & 0xFFFF; int16_t received_imag = ((c16_t*)srs_received_signal[ant])[nr_srs_info->sc_list[sc_idx]].i;
// We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the generated_real and generated_imag. // We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the generated_real and generated_imag.
// So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16 bits. // So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16 bits.
...@@ -1068,8 +1074,10 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -1068,8 +1074,10 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
// Compute noise // Compute noise
for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) { for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) {
noise_real[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)((srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]]-srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]]) & 0xFFFF)); ch_real[ant*nr_srs_info->sc_list_length + sc_idx] = ((c16_t*)srs_estimated_channel_freq[ant])[nr_srs_info->sc_list[sc_idx]].r;
noise_imag[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)(((srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]]-srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]]) >> 16) & 0xFFFF)); ch_imag[ant*nr_srs_info->sc_list_length + sc_idx] = ((c16_t*)srs_estimated_channel_freq[ant])[nr_srs_info->sc_list[sc_idx]].i;
noise_real[ant*nr_srs_info->sc_list_length + sc_idx] = abs(((c16_t*)srs_ls_estimated_channel[ant])[nr_srs_info->sc_list[sc_idx]].r - ch_real[ant*nr_srs_info->sc_list_length + sc_idx]);
noise_imag[ant*nr_srs_info->sc_list_length + sc_idx] = abs(((c16_t*)srs_ls_estimated_channel[ant])[nr_srs_info->sc_list[sc_idx]].i - ch_imag[ant*nr_srs_info->sc_list_length + sc_idx]);
} }
// Convert to time domain // Convert to time domain
...@@ -1086,11 +1094,74 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -1086,11 +1094,74 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
(gNB->frame_parms.ofdm_symbol_size>>1)*sizeof(int32_t)); (gNB->frame_parms.ofdm_symbol_size>>1)*sizeof(int32_t));
} }
// Compute signal power
*signal_power = calc_power(ch_real,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length)
+ calc_power(ch_imag,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length);
#ifdef SRS_DEBUG
LOG_I(NR_PHY,"signal_power = %u\n", *signal_power);
#endif
if (*signal_power == 0) {
LOG_W(NR_PHY, "Received SRS signal power is 0\n");
return -1;
}
// Compute noise power
const uint8_t signal_power_bits = log2_approx(*signal_power);
const uint8_t factor_bits = signal_power_bits < 32 ? 32 - signal_power_bits : 0; // 32 due to input of dB_fixed(uint32_t x)
const int32_t factor_dB = dB_fixed(1<<factor_bits);
const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*12;
const uint8_t srs_symbols_per_rb = srs_pdu->comb_size == 0 ? 6 : 3;
const uint8_t n_noise_estimates = frame_parms->nb_antennas_rx*srs_symbols_per_rb;
uint8_t count_estimates = 0;
uint64_t sum_re = 0;
uint64_t sum_re2 = 0;
uint64_t sum_im = 0;
uint64_t sum_im2 = 0;
for (int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) {
int subcarrier0 = nr_srs_info->sc_list[sc_idx]-subcarrier_offset;
if(subcarrier0 < 0) {
subcarrier0 = subcarrier0 + frame_parms->ofdm_symbol_size;
}
int rb = subcarrier0/NR_NB_SC_PER_RB;
for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) {
sum_re = sum_re + noise_real[ant*nr_srs_info->sc_list_length+sc_idx];
sum_re2 = sum_re2 + noise_real[ant*nr_srs_info->sc_list_length+sc_idx]*noise_real[ant*nr_srs_info->sc_list_length+sc_idx];
sum_im = sum_im + noise_imag[ant*nr_srs_info->sc_list_length+sc_idx];
sum_im2 = sum_im2 + noise_imag[ant*nr_srs_info->sc_list_length+sc_idx]*noise_imag[ant*nr_srs_info->sc_list_length+sc_idx];
count_estimates++;
if (count_estimates == n_noise_estimates) {
noise_power_per_rb[rb] = sum_re2/n_noise_estimates - (sum_re/n_noise_estimates)*(sum_re/n_noise_estimates) +
sum_im2/n_noise_estimates - (sum_im/n_noise_estimates)*(sum_im/n_noise_estimates);
snr_per_rb[rb] = dB_fixed((int32_t)((*signal_power<<factor_bits)/noise_power_per_rb[rb])) - factor_dB;
count_estimates = 0;
sum_re = 0;
sum_re2 = 0;
sum_im = 0;
sum_im2 = 0;
#ifdef SRS_DEBUG
LOG_I(NR_PHY,"noise_power_per_rb[%i] = %i, snr_per_rb[%i] = %i dB\n", rb, noise_power_per_rb[rb], rb, snr_per_rb[rb]);
#endif
}
}
}
*noise_power = calc_power(noise_real,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length) *noise_power = calc_power(noise_real,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length)
+ calc_power(noise_imag,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length); + calc_power(noise_imag,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length);
*snr = dB_fixed((int32_t)((*signal_power<<factor_bits)/(*noise_power))) - factor_dB;
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*12;
uint8_t R = srs_pdu->comb_size == 0 ? 2 : 4; uint8_t R = srs_pdu->comb_size == 0 ? 2 : 4;
for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) {
for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) { for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) {
...@@ -1118,7 +1189,7 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -1118,7 +1189,7 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
} }
} }
LOG_I(NR_PHY,"noise_power = %u\n", *noise_power); LOG_I(NR_PHY,"noise_power = %u, SNR = %i dB\n", *noise_power, *snr);
#endif #endif
return 0; return 0;
......
...@@ -55,6 +55,9 @@ void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq ...@@ -55,6 +55,9 @@ void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq
int nr_est_timing_advance_pusch(PHY_VARS_gNB* phy_vars_gNB, int UE_id); int nr_est_timing_advance_pusch(PHY_VARS_gNB* phy_vars_gNB, int UE_id);
int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms,
const int32_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]);
void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *rel15_ul, nfapi_nr_pusch_pdu_t *rel15_ul,
...@@ -63,15 +66,20 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, ...@@ -63,15 +66,20 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
unsigned char symbol, unsigned char symbol,
uint32_t nb_re_pusch); uint32_t nb_re_pusch);
int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
int frame, const int frame,
int slot, const int slot,
nfapi_nr_srs_pdu_t *srs_pdu, const nfapi_nr_srs_pdu_t *srs_pdu,
nr_srs_info_t *nr_srs_info, const nr_srs_info_t *nr_srs_info,
int32_t *srs_generated_signal, const int32_t *srs_generated_signal,
int32_t **srs_received_signal, int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)],
int32_t **srs_estimated_channel_freq, int32_t srs_ls_estimated_channel[][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)],
int32_t **srs_estimated_channel_time, int32_t srs_estimated_channel_freq[][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)],
int32_t **srs_estimated_channel_time_shifted, int32_t srs_estimated_channel_time[][gNB->frame_parms.ofdm_symbol_size],
uint32_t *noise_power); int32_t srs_estimated_channel_time_shifted[][gNB->frame_parms.ofdm_symbol_size],
uint32_t *signal_power,
uint32_t *noise_power_per_rb,
uint32_t *noise_power,
int8_t *snr_per_rb,
int8_t *snr);
#endif #endif
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "PHY/LTE_REFSIG/lte_refsig.h" #include "PHY/LTE_REFSIG/lte_refsig.h"
#include "PHY/sse_intrin.h" #include "PHY/sse_intrin.h"
#include "executables/softmodem-common.h"
//#define DEBUG_PBCH //#define DEBUG_PBCH
//#define DEBUG_PBCH_ENCODING //#define DEBUG_PBCH_ENCODING
...@@ -248,6 +249,9 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu, ...@@ -248,6 +249,9 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
for (int i=0; i<NR_PBCH_PDU_BITS; i++) for (int i=0; i<NR_PBCH_PDU_BITS; i++)
pbch->pbch_a |= ((pbch_pdu[i>>3]>>(7-(i&7)))&1)<<i; pbch->pbch_a |= ((pbch_pdu[i>>3]>>(7-(i&7)))&1)<<i;
// NSA to signal no coreset0
const int ssb_sc_offset = get_softmodem_params()->sa ? config->ssb_table.ssb_subcarrier_offset.value : 31;
#ifdef DEBUG_PBCH_ENCODING #ifdef DEBUG_PBCH_ENCODING
for (int i=0; i<3; i++) for (int i=0; i<3; i++)
printf("pbch_pdu[%d]: 0x%02x\n", i, pbch_pdu[i]); printf("pbch_pdu[%d]: 0x%02x\n", i, pbch_pdu[i]);
...@@ -265,7 +269,7 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu, ...@@ -265,7 +269,7 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
for (int i=0; i<3; i++) for (int i=0; i<3; i++)
pbch->pbch_a |= ((ssb_index>>(5-i))&1)<<(29+i); // resp. 6th, 5th and 4th bits of ssb_index pbch->pbch_a |= ((ssb_index>>(5-i))&1)<<(29+i); // resp. 6th, 5th and 4th bits of ssb_index
else else
pbch->pbch_a |= ((config->ssb_table.ssb_subcarrier_offset.value>>4)&1)<<29; //MSB of k_SSB (bit index 4) pbch->pbch_a |= ((ssb_sc_offset>>4)&1)<<29; //MSB of k_SSB (bit index 4)
LOG_D(PHY,"After extra byte: pbch_a = 0x%08x\n",pbch->pbch_a); LOG_D(PHY,"After extra byte: pbch_a = 0x%08x\n",pbch->pbch_a);
......
...@@ -330,7 +330,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, ...@@ -330,7 +330,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB,
int slot, int slot,
nfapi_nr_srs_pdu_t *srs_pdu, nfapi_nr_srs_pdu_t *srs_pdu,
nr_srs_info_t *nr_srs_info, nr_srs_info_t *nr_srs_info,
int32_t **srs_received_signal); int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)]);
void init_prach_list(PHY_VARS_gNB *gNB); void init_prach_list(PHY_VARS_gNB *gNB);
void init_prach_ru_list(RU_t *ru); void init_prach_ru_list(RU_t *ru);
......
...@@ -98,7 +98,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, ...@@ -98,7 +98,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB,
int slot, int slot,
nfapi_nr_srs_pdu_t *srs_pdu, nfapi_nr_srs_pdu_t *srs_pdu,
nr_srs_info_t *nr_srs_info, nr_srs_info_t *nr_srs_info,
int32_t **srs_received_signal) { int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)]) {
if(nr_srs_info->sc_list_length == 0) { if(nr_srs_info->sc_list_length == 0) {
LOG_E(NR_PHY, "(%d.%d) nr_srs_info was not generated yet!\n", frame, slot); LOG_E(NR_PHY, "(%d.%d) nr_srs_info was not generated yet!\n", frame, slot);
...@@ -113,6 +113,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, ...@@ -113,6 +113,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB,
uint64_t symbol_offset = (n_symbols+l0)*frame_parms->ofdm_symbol_size; uint64_t symbol_offset = (n_symbols+l0)*frame_parms->ofdm_symbol_size;
int32_t *rx_signal; int32_t *rx_signal;
bool no_srs_signal = true;
for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) {
memset(srs_received_signal[ant], 0, frame_parms->ofdm_symbol_size*sizeof(int32_t)); memset(srs_received_signal[ant], 0, frame_parms->ofdm_symbol_size*sizeof(int32_t));
...@@ -121,6 +122,10 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, ...@@ -121,6 +122,10 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB,
for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) { for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) {
srs_received_signal[ant][nr_srs_info->sc_list[sc_idx]] = rx_signal[nr_srs_info->sc_list[sc_idx]]; srs_received_signal[ant][nr_srs_info->sc_list[sc_idx]] = rx_signal[nr_srs_info->sc_list[sc_idx]];
if (rx_signal[nr_srs_info->sc_list[sc_idx]] != 0) {
no_srs_signal = false;
}
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*12; uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*12;
int subcarrier_log = nr_srs_info->sc_list[sc_idx]-subcarrier_offset; int subcarrier_log = nr_srs_info->sc_list[sc_idx]-subcarrier_offset;
...@@ -140,5 +145,11 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, ...@@ -140,5 +145,11 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB,
#endif #endif
} }
} }
return 0;
if (no_srs_signal) {
LOG_W(NR_PHY, "No SRS signal\n");
return -1;
} else {
return 0;
}
} }
\ No newline at end of file
...@@ -241,15 +241,9 @@ typedef struct { ...@@ -241,15 +241,9 @@ typedef struct {
typedef struct { typedef struct {
uint16_t sc_list_length; uint16_t sc_list_length;
uint16_t *sc_list; uint16_t sc_list[6*273];
uint8_t srs_generated_signal_bits; uint8_t srs_generated_signal_bits;
int32_t *srs_generated_signal; int32_t srs_generated_signal[OFDM_SYMBOL_SIZE_SAMPLES_MAX * MAX_NUM_NR_SRS_SYMBOLS];
int32_t **srs_received_signal;
int32_t **srs_ls_estimated_channel;
int32_t **srs_estimated_channel_freq;
int32_t **srs_estimated_channel_time;
int32_t **srs_estimated_channel_time_shifted;
uint32_t *noise_power;
} nr_srs_info_t; } nr_srs_info_t;
typedef struct { typedef struct {
......
This diff is collapsed.
...@@ -67,7 +67,10 @@ openair0_config_t openair0_cfg[MAX_CARDS]; ...@@ -67,7 +67,10 @@ openair0_config_t openair0_cfg[MAX_CARDS];
uint8_t const nr_rv_round_map[4] = {0, 2, 3, 1}; uint8_t const nr_rv_round_map[4] = {0, 2, 3, 1};
uint64_t get_softmodem_optmask(void) {return 0;} uint64_t get_softmodem_optmask(void) {return 0;}
softmodem_params_t *get_softmodem_params(void) {return 0;} static softmodem_params_t softmodem_params;
softmodem_params_t *get_softmodem_params(void) {
return &softmodem_params;
}
void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {}
...@@ -174,6 +177,7 @@ int main(int argc, char **argv) ...@@ -174,6 +177,7 @@ int main(int argc, char **argv)
int ssb_subcarrier_offset = 0; int ssb_subcarrier_offset = 0;
channel_desc_t *gNB2UE; channel_desc_t *gNB2UE;
get_softmodem_params()->sa = 1;
//uint8_t extended_prefix_flag=0; //uint8_t extended_prefix_flag=0;
//int8_t interf1=-21,interf2=-21; //int8_t interf1=-21,interf2=-21;
...@@ -460,6 +464,7 @@ int main(int argc, char **argv) ...@@ -460,6 +464,7 @@ int main(int argc, char **argv)
frame_parms->Nid_cell = Nid_cell; frame_parms->Nid_cell = Nid_cell;
frame_parms->nushift = Nid_cell%4; frame_parms->nushift = Nid_cell%4;
frame_parms->ssb_type = nr_ssb_type_C; frame_parms->ssb_type = nr_ssb_type_C;
frame_parms->freq_range = mu<2 ? nr_FR1 : nr_FR2;
nr_phy_config_request_sim_pbchsim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); nr_phy_config_request_sim_pbchsim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
phy_init_nr_gNB(gNB,0,1); phy_init_nr_gNB(gNB,0,1);
...@@ -584,9 +589,12 @@ int main(int argc, char **argv) ...@@ -584,9 +589,12 @@ int main(int argc, char **argv)
for (i=0; i<frame_parms->Lmax; i++) { for (i=0; i<frame_parms->Lmax; i++) {
if((SSB_positions >> i) & 0x01) { if((SSB_positions >> i) & 0x01) {
const int sc_offset = frame_parms->freq_range == nr_FR1 ? ssb_subcarrier_offset<<mu : ssb_subcarrier_offset;
const int prb_offset = frame_parms->freq_range == nr_FR1 ? gNB->gNB_config.ssb_table.ssb_offset_point_a.value<<mu : gNB->gNB_config.ssb_table.ssb_offset_point_a.value << (mu - 2);
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33; msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33;
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i; msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i;
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = ssb_subcarrier_offset; msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset;
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = prb_offset;
start_symbol = nr_get_ssb_start_symbol(frame_parms,i); start_symbol = nr_get_ssb_start_symbol(frame_parms,i);
int slot = start_symbol/14; int slot = start_symbol/14;
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#define CONFIG_STRING_MACRLC_ULSCH_MAX_FRAME_INACTIVITY "ulsch_max_frame_inactivity" #define CONFIG_STRING_MACRLC_ULSCH_MAX_FRAME_INACTIVITY "ulsch_max_frame_inactivity"
#define CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10 "pusch_TargetSNRx10" #define CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10 "pusch_TargetSNRx10"
#define CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10 "pucch_TargetSNRx10" #define CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10 "pucch_TargetSNRx10"
#define CONFIG_STRING_MACRLC_UL_PRBBLACK_SNR_THRESHOLD "ul_prbblack_SNR_threshold"
#define CONFIG_STRING_MACRLC_PUCCHFAILURETHRES "pucch_FailureThres" #define CONFIG_STRING_MACRLC_PUCCHFAILURETHRES "pucch_FailureThres"
#define CONFIG_STRING_MACRLC_PUSCHFAILURETHRES "pusch_FailureThres" #define CONFIG_STRING_MACRLC_PUSCHFAILURETHRES "pusch_FailureThres"
#define CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER "dl_bler_target_upper" #define CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER "dl_bler_target_upper"
...@@ -96,6 +97,7 @@ ...@@ -96,6 +97,7 @@
{CONFIG_STRING_MACRLC_ULSCH_MAX_FRAME_INACTIVITY, NULL, 0, uptr:NULL, defintval:10, TYPE_UINT, 0}, \ {CONFIG_STRING_MACRLC_ULSCH_MAX_FRAME_INACTIVITY, NULL, 0, uptr:NULL, defintval:10, TYPE_UINT, 0}, \
{CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \
{CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:150, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:150, TYPE_INT, 0}, \
{CONFIG_STRING_MACRLC_UL_PRBBLACK_SNR_THRESHOLD, "SNR threshold to decide whether a PRB will be blacklisted or not", 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \
{CONFIG_STRING_MACRLC_PUCCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_PUCCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \
{CONFIG_STRING_MACRLC_PUSCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_PUSCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \
{CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER, "Upper threshold of BLER to decrease DL MCS", 0, dblptr:NULL, defdblval:0.15, TYPE_DOUBLE, 0}, \ {CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER, "Upper threshold of BLER to decrease DL MCS", 0, dblptr:NULL, defdblval:0.15, TYPE_DOUBLE, 0}, \
...@@ -128,17 +130,18 @@ ...@@ -128,17 +130,18 @@
#define MACRLC_ULSCH_MAX_FRAME_INACTIVITY 17 #define MACRLC_ULSCH_MAX_FRAME_INACTIVITY 17
#define MACRLC_PUSCHTARGETSNRX10_IDX 18 #define MACRLC_PUSCHTARGETSNRX10_IDX 18
#define MACRLC_PUCCHTARGETSNRX10_IDX 19 #define MACRLC_PUCCHTARGETSNRX10_IDX 19
#define MACRLC_PUCCHFAILURETHRES_IDX 20 #define MACRLC_UL_PRBBLACK_SNR_THRESHOLD_IDX 20
#define MACRLC_PUSCHFAILURETHRES_IDX 21 #define MACRLC_PUCCHFAILURETHRES_IDX 21
#define MACRLC_DL_BLER_TARGET_UPPER_IDX 22 #define MACRLC_PUSCHFAILURETHRES_IDX 22
#define MACRLC_DL_BLER_TARGET_LOWER_IDX 23 #define MACRLC_DL_BLER_TARGET_UPPER_IDX 23
#define MACRLC_DL_MAX_MCS_IDX 24 #define MACRLC_DL_BLER_TARGET_LOWER_IDX 24
#define MACRLC_UL_BLER_TARGET_UPPER_IDX 25 #define MACRLC_DL_MAX_MCS_IDX 25
#define MACRLC_UL_BLER_TARGET_LOWER_IDX 26 #define MACRLC_UL_BLER_TARGET_UPPER_IDX 26
#define MACRLC_UL_MAX_MCS_IDX 27 #define MACRLC_UL_BLER_TARGET_LOWER_IDX 27
#define MACRLC_HARQ_ROUND_MAX_IDX 28 #define MACRLC_UL_MAX_MCS_IDX 28
#define MACRLC_MIN_GRANT_PRB_IDX 29 #define MACRLC_HARQ_ROUND_MAX_IDX 29
#define MACRLC_MIN_GRANT_MCS_IDX 30 #define MACRLC_MIN_GRANT_PRB_IDX 30
#define MACRLC_MIN_GRANT_MCS_IDX 31
/*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/
#endif #endif
...@@ -828,6 +828,7 @@ void RCconfig_nr_macrlc() { ...@@ -828,6 +828,7 @@ void RCconfig_nr_macrlc() {
RC.nb_nr_mac_CC[j] = *(MacRLC_ParamList.paramarray[j][MACRLC_CC_IDX].iptr); RC.nb_nr_mac_CC[j] = *(MacRLC_ParamList.paramarray[j][MACRLC_CC_IDX].iptr);
RC.nrmac[j]->pusch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHTARGETSNRX10_IDX].iptr); RC.nrmac[j]->pusch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHTARGETSNRX10_IDX].iptr);
RC.nrmac[j]->pucch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHTARGETSNRX10_IDX].iptr); RC.nrmac[j]->pucch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHTARGETSNRX10_IDX].iptr);
RC.nrmac[j]->ul_prbblack_SNR_threshold = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_PRBBLACK_SNR_THRESHOLD_IDX].iptr);
RC.nrmac[j]->pucch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHFAILURETHRES_IDX].iptr); RC.nrmac[j]->pucch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHFAILURETHRES_IDX].iptr);
RC.nrmac[j]->pusch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHFAILURETHRES_IDX].iptr); RC.nrmac[j]->pusch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHFAILURETHRES_IDX].iptr);
......
...@@ -928,15 +928,23 @@ bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slo ...@@ -928,15 +928,23 @@ bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slo
bool srs_scheduled = false; bool srs_scheduled = false;
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
const NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id;
NR_SRS_Config_t *srs_config = NULL; NR_SRS_Config_t *srs_config = NULL;
if (mac->cg && if (ul_bwp_id > 0 && mac->ULbwp[ul_bwp_id-1]) {
mac->cg->spCellConfig && if (mac->ULbwp[ul_bwp_id-1]->bwp_Dedicated &&
mac->cg->spCellConfig->spCellConfigDedicated && mac->ULbwp[ul_bwp_id-1]->bwp_Dedicated->srs_Config) {
mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && srs_config = mac->ULbwp[ul_bwp_id-1]->bwp_Dedicated->srs_Config->choice.setup;
mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { }
} else if (mac->cg &&
mac->cg->spCellConfig &&
mac->cg->spCellConfig->spCellConfigDedicated &&
mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig &&
mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) {
srs_config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config->choice.setup; srs_config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config->choice.setup;
} else { }
if (!srs_config) {
return false; return false;
} }
...@@ -964,7 +972,6 @@ bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slo ...@@ -964,7 +972,6 @@ bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slo
continue; continue;
} }
NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id;
NR_BWP_t ubwp = ul_bwp_id > 0 && mac->ULbwp[ul_bwp_id-1] ? NR_BWP_t ubwp = ul_bwp_id > 0 && mac->ULbwp[ul_bwp_id-1] ?
mac->ULbwp[ul_bwp_id-1]->bwp_Common->genericParameters : mac->ULbwp[ul_bwp_id-1]->bwp_Common->genericParameters :
mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters; mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters;
......
...@@ -335,22 +335,13 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, int pusch_AntennaPorts, ...@@ -335,22 +335,13 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, int pusch_AntennaPorts,
cfg->num_tlv++; cfg->num_tlv++;
// SSB Table Configuration // SSB Table Configuration
int scs_scaling = 1<<(cfg->ssb_config.scs_common.value);
if (scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000)
scs_scaling = scs_scaling*3;
if (scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666)
scs_scaling = scs_scaling>>2;
uint32_t absolute_diff = (*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); uint32_t absolute_diff = (*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA);
const int scaling_5khz = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000 ? 3 : 1;
RC.nrmac[Mod_idP]->ssb_SubcarrierOffset = absolute_diff%(12*scs_scaling); int sco = (absolute_diff*scaling_5khz) % 24;
int sco = 31; // no SIB1 if(frequency_range == FR2)
if(get_softmodem_params()->sa) { sco >>= 1; // this assumes 120kHz SCS for SSB and subCarrierSpacingCommon (only option supported by OAI for
sco = RC.nrmac[Mod_idP]->ssb_SubcarrierOffset; const int scs_scaling = frequency_range == FR2 ? 1 << (*scc->ssbSubcarrierSpacing - 2) : 1 << *scc->ssbSubcarrierSpacing;
if(frequency_range == FR1) cfg->ssb_table.ssb_offset_point_a.value = absolute_diff/(12*scaling_5khz) - 10*scs_scaling; //absoluteFrequencySSB is the central frequency of SSB which is made by 20RBs in total
sco <<= cfg->ssb_config.scs_common.value; // 38.211 section 7.4.3.1 in FR1 it is expresses in terms of 15kHz SCS
}
cfg->ssb_table.ssb_offset_point_a.value = absolute_diff/(12*scs_scaling) - 10; //absoluteFrequencySSB is the central frequency of SSB which is made by 20RBs in total
cfg->ssb_table.ssb_offset_point_a.tl.tag = NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG; cfg->ssb_table.ssb_offset_point_a.tl.tag = NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG;
cfg->num_tlv++; cfg->num_tlv++;
cfg->ssb_table.ssb_period.value = *scc->ssb_periodicityServingCell; cfg->ssb_table.ssb_period.value = *scc->ssb_periodicityServingCell;
...@@ -360,6 +351,9 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, int pusch_AntennaPorts, ...@@ -360,6 +351,9 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, int pusch_AntennaPorts,
cfg->ssb_table.ssb_subcarrier_offset.tl.tag = NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG; cfg->ssb_table.ssb_subcarrier_offset.tl.tag = NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG;
cfg->num_tlv++; cfg->num_tlv++;
RC.nrmac[Mod_idP]->ssb_SubcarrierOffset = cfg->ssb_table.ssb_subcarrier_offset.value;
RC.nrmac[Mod_idP]->ssb_OffsetPointA = cfg->ssb_table.ssb_offset_point_a.value;
switch (scc->ssb_PositionsInBurst->present) { switch (scc->ssb_PositionsInBurst->present) {
case 1 : case 1 :
cfg->ssb_table.ssb_mask_list[0].ssb_mask.value = scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0]<<24; cfg->ssb_table.ssb_mask_list[0].ssb_mask.value = scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0]<<24;
......
...@@ -54,52 +54,6 @@ ...@@ -54,52 +54,6 @@
extern RAN_CONTEXT_t RC; extern RAN_CONTEXT_t RC;
uint16_t get_ssboffset_pointa(NR_ServingCellConfigCommon_t *scc,const long band) {
int ratio;
switch (*scc->ssbSubcarrierSpacing) {
case NR_SubcarrierSpacing_kHz15:
AssertFatal(band <= 95,
"Band %ld is not possible for SSB with 15 kHz SCS\n",
band);
// no band available above 3GHz using 15kHz
ratio = 3; // NRARFCN step is 5 kHz
break;
case NR_SubcarrierSpacing_kHz30:
AssertFatal(band <= 96,
"Band %ld is not possible for SSB with 30 kHz SCS\n",
band);
if (band == 46 || band == 48 || band == 77 ||
band == 78 || band == 79 || band == 96) // above 3GHz
ratio = 2; // NRARFCN step is 15 kHz
else
ratio = 6; // NRARFCN step is 5 kHz
break;
case NR_SubcarrierSpacing_kHz120:
AssertFatal(band >= 257,
"Band %ld is not possible for SSB with 120 kHz SCS\n",
band);
ratio = 2; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz240:
AssertFatal(band >= 257,
"Band %ld is not possible for SSB with 240 kHz SCS\n",
band);
ratio = 4; // NRARFCN step is 15 kHz
break;
default:
AssertFatal(1 == 0, "SCS %ld not allowed for SSB \n",
*scc->ssbSubcarrierSpacing);
}
const uint32_t ssb_offset0 = *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA;
return (ssb_offset0/(ratio*12) - 10); // absoluteFrequencySSB is the center of SSB
}
void schedule_ssb(frame_t frame, sub_frame_t slot, void schedule_ssb(frame_t frame, sub_frame_t slot,
NR_ServingCellConfigCommon_t *scc, NR_ServingCellConfigCommon_t *scc,
nfapi_nr_dl_tti_request_body_t *dl_req, nfapi_nr_dl_tti_request_body_t *dl_req,
...@@ -190,7 +144,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) ...@@ -190,7 +144,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
NR_SubcarrierSpacing_t scs = *scc->ssbSubcarrierSpacing; NR_SubcarrierSpacing_t scs = *scc->ssbSubcarrierSpacing;
const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
uint16_t offset_pointa = get_ssboffset_pointa(scc,band); const uint16_t offset_pointa = gNB->ssb_OffsetPointA;
uint8_t ssbSubcarrierOffset = gNB->ssb_SubcarrierOffset; uint8_t ssbSubcarrierOffset = gNB->ssb_SubcarrierOffset;
const BIT_STRING_t *shortBitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; const BIT_STRING_t *shortBitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap;
...@@ -207,8 +161,9 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) ...@@ -207,8 +161,9 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb); ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
if ((ssb_start_symbol/14) == rel_slot){ if ((ssb_start_symbol/14) == rel_slot){
const int prb_offset = offset_pointa >> scs;
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1)); schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1));
fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id); fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id);
if (get_softmodem_params()->sa == 1) { if (get_softmodem_params()->sa == 1) {
get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb], get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
frameP, frameP,
...@@ -221,7 +176,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) ...@@ -221,7 +176,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
band, band,
i_ssb, i_ssb,
ssb_frame_periodicity, ssb_frame_periodicity,
offset_pointa); prb_offset);
gNB->type0_PDCCH_CSS_config[i_ssb].active = true; gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
} }
} }
...@@ -235,8 +190,9 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) ...@@ -235,8 +190,9 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb); ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
if ((ssb_start_symbol/14) == rel_slot){ if ((ssb_start_symbol/14) == rel_slot){
const int prb_offset = offset_pointa >> scs;
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1)); schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1));
fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id); fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id);
if (get_softmodem_params()->sa == 1) { if (get_softmodem_params()->sa == 1) {
get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb], get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
frameP, frameP,
...@@ -249,7 +205,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) ...@@ -249,7 +205,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
band, band,
i_ssb, i_ssb,
ssb_frame_periodicity, ssb_frame_periodicity,
offset_pointa); prb_offset);
gNB->type0_PDCCH_CSS_config[i_ssb].active = true; gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
} }
} }
...@@ -264,8 +220,9 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) ...@@ -264,8 +220,9 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb); ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
if ((ssb_start_symbol/14) == rel_slot){ if ((ssb_start_symbol/14) == rel_slot){
const int prb_offset = offset_pointa >> (scs-2); // reference 60kHz
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1)); schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1));
fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id); fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id);
const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
// FR2 is only TDD, to be fixed for flexible TDD // FR2 is only TDD, to be fixed for flexible TDD
...@@ -286,7 +243,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) ...@@ -286,7 +243,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
band, band,
i_ssb, i_ssb,
ssb_frame_periodicity, ssb_frame_periodicity,
offset_pointa); prb_offset);
gNB->type0_PDCCH_CSS_config[i_ssb].active = true; gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
} }
} }
...@@ -306,7 +263,7 @@ void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframe ...@@ -306,7 +263,7 @@ void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframe
//---------------------------------------- //----------------------------------------
} }
void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, uint16_t symStart, int CC_id) { void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, int ssb_subcarrier_offset, uint16_t symStart, int CC_id) {
AssertFatal(*cc->ServingCellConfigCommon->ssbSubcarrierSpacing != AssertFatal(*cc->ServingCellConfigCommon->ssbSubcarrierSpacing !=
NR_SubcarrierSpacing_kHz240, NR_SubcarrierSpacing_kHz240,
...@@ -314,7 +271,8 @@ void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, uint16_t symStart ...@@ -314,7 +271,8 @@ void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, uint16_t symStart
uint16_t *vrb_map = cc[CC_id].vrb_map; uint16_t *vrb_map = cc[CC_id].vrb_map;
for (int rb = 0; rb < 20; rb++) const int extra_prb = ssb_subcarrier_offset > 0;
for (int rb = 0; rb < 20+extra_prb; rb++)
vrb_map[rbStart + rb] = SL_to_bitmap(symStart, 4); vrb_map[rbStart + rb] = SL_to_bitmap(symStart, 4);
} }
......
...@@ -40,15 +40,16 @@ void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int module_id, int CC_id,NR_U ...@@ -40,15 +40,16 @@ void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int module_id, int CC_id,NR_U
NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_BWP_t ubwp = sched_ctrl->active_ubwp ? const NR_SIB1_t *sib1 = nrmac->common_channels[0].sib1 ? nrmac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL;
sched_ctrl->active_ubwp->bwp_Common->genericParameters : const NR_BWP_t *genericParameters = get_ul_bwp_genericParameters(sched_ctrl->active_ubwp,
scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; scc,
sib1);
srs_pdu->rnti = UE->rnti; srs_pdu->rnti = UE->rnti;
srs_pdu->handle = 0; srs_pdu->handle = 0;
srs_pdu->bwp_size = NRRIV2BW(ubwp.locationAndBandwidth, MAX_BWP_SIZE);; srs_pdu->bwp_size = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);;
srs_pdu->bwp_start = NRRIV2PRBOFFSET(ubwp.locationAndBandwidth, MAX_BWP_SIZE);; srs_pdu->bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);;
srs_pdu->subcarrier_spacing = ubwp.subcarrierSpacing; srs_pdu->subcarrier_spacing = genericParameters->subcarrierSpacing;
srs_pdu->cyclic_prefix = 0; srs_pdu->cyclic_prefix = 0;
srs_pdu->num_ant_ports = srs_resource->nrofSRS_Ports; srs_pdu->num_ant_ports = srs_resource->nrofSRS_Ports;
srs_pdu->num_symbols = srs_resource->resourceMapping.nrofSymbols; srs_pdu->num_symbols = srs_resource->resourceMapping.nrofSymbols;
...@@ -122,18 +123,26 @@ void nr_schedule_srs(int module_id, frame_t frame) { ...@@ -122,18 +123,26 @@ void nr_schedule_srs(int module_id, frame_t frame) {
sched_ctrl->sched_srs.slot = -1; sched_ctrl->sched_srs.slot = -1;
sched_ctrl->sched_srs.srs_scheduled = false; sched_ctrl->sched_srs.srs_scheduled = false;
if(!UE->Msg4_ACKed || sched_ctrl->rrc_processing_timer > 0) { if((sched_ctrl->ul_failure == 1 && get_softmodem_params()->phy_test==0) ||
sched_ctrl->rrc_processing_timer > 0) {
continue; continue;
} }
NR_SRS_Config_t *srs_config = NULL; NR_SRS_Config_t *srs_config = NULL;
if (cg && if (sched_ctrl->active_ubwp) {
cg->spCellConfig && if (sched_ctrl->active_ubwp->bwp_Dedicated &&
cg->spCellConfig->spCellConfigDedicated && sched_ctrl->active_ubwp->bwp_Dedicated->srs_Config) {
cg->spCellConfig->spCellConfigDedicated->uplinkConfig && srs_config = sched_ctrl->active_ubwp->bwp_Dedicated->srs_Config->choice.setup;
cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { }
} else if (cg &&
cg->spCellConfig &&
cg->spCellConfig->spCellConfigDedicated &&
cg->spCellConfig->spCellConfigDedicated->uplinkConfig &&
cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) {
srs_config = cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config->choice.setup; srs_config = cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config->choice.setup;
} else { }
if (!srs_config) {
continue; continue;
} }
...@@ -163,14 +172,15 @@ void nr_schedule_srs(int module_id, frame_t frame) { ...@@ -163,14 +172,15 @@ void nr_schedule_srs(int module_id, frame_t frame) {
continue; continue;
} }
NR_BWP_t ubwp = sched_ctrl->active_ubwp ? const NR_SIB1_t *sib1 = nrmac->common_channels[0].sib1 ? nrmac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL;
sched_ctrl->active_ubwp->bwp_Common->genericParameters : const NR_BWP_t *genericParameters = get_ul_bwp_genericParameters(sched_ctrl->active_ubwp,
scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; scc,
sib1);
uint16_t period = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present]; uint16_t period = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present];
uint16_t offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p); uint16_t offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p);
int n_slots_frame = nr_slots_per_frame[ubwp.subcarrierSpacing]; const int n_slots_frame = nr_slots_per_frame[genericParameters->subcarrierSpacing];
// Check if UE will transmit the SRS in this frame // Check if UE will transmit the SRS in this frame
if ( ((frame - offset/n_slots_frame)*n_slots_frame)%period == 0) { if ( ((frame - offset/n_slots_frame)*n_slots_frame)%period == 0) {
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
extern void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_sched_ctrl_t *sched_ctrl); extern void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_sched_ctrl_t *sched_ctrl);
//#define SRS_IND_DEBUG
int get_dci_format(NR_UE_sched_ctrl_t *sched_ctrl) { int get_dci_format(NR_UE_sched_ctrl_t *sched_ctrl) {
int dci_format = sched_ctrl->search_space && sched_ctrl->search_space->searchSpaceType && int dci_format = sched_ctrl->search_space && sched_ctrl->search_space->searchSpaceType &&
...@@ -763,6 +765,56 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, ...@@ -763,6 +765,56 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
} }
} }
void handle_nr_srs_measurements(const module_id_t module_id,
const frame_t frame,
const sub_frame_t slot,
const rnti_t rnti,
const uint16_t timing_advance,
const uint8_t num_symbols,
const uint8_t wide_band_snr,
const uint8_t num_reported_symbols,
nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list) {
LOG_D(NR_MAC, "(%d.%d) Received SRS indication for rnti: 0x%04x\n", frame, slot, rnti);
#ifdef SRS_IND_DEBUG
LOG_I(NR_MAC, "frame = %i\n", frame);
LOG_I(NR_MAC, "slot = %i\n", slot);
LOG_I(NR_MAC, "rnti = 0x%04x\n", rnti);
LOG_I(NR_MAC, "timing_advance = %i\n", timing_advance);
LOG_I(NR_MAC, "num_symbols = %i\n", num_symbols);
LOG_I(NR_MAC, "wide_band_snr = %i (%i dB)\n", wide_band_snr, (wide_band_snr>>1)-64);
LOG_I(NR_MAC, "num_reported_symbols = %i\n", num_reported_symbols);
LOG_I(NR_MAC, "reported_symbol_list[0].num_rbs = %i\n", reported_symbol_list[0].num_rbs);
for(int rb = 0; rb < reported_symbol_list[0].num_rbs; rb++) {
LOG_I(NR_MAC, "reported_symbol_list[0].rb_list[%3i].rb_snr = %i (%i dB)\n",
rb, reported_symbol_list[0].rb_list[rb].rb_snr, (reported_symbol_list[0].rb_list[rb].rb_snr>>1)-64);
}
#endif
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, rnti);
if (!UE) {
LOG_W(NR_MAC, "Could not find UE for RNTI 0x%04x\n", rnti);
return;
}
gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
NR_mac_stats_t *stats = &UE->mac_stats;
stats->srs_wide_band_snr = (wide_band_snr>>1)-64;
const int ul_prbblack_SNR_threshold = nr_mac->ul_prbblack_SNR_threshold;
uint16_t *ulprbbl = nr_mac->ulprbbl;
memset(ulprbbl, 0, reported_symbol_list[0].num_rbs*sizeof(uint16_t));
for (int rb = 0; rb < reported_symbol_list[0].num_rbs; rb++) {
int snr = (reported_symbol_list[0].rb_list[rb].rb_snr>>1)-64;
if (snr < ul_prbblack_SNR_threshold) {
ulprbbl[rb] = 0x3FFF; // all symbols taken
}
LOG_D(NR_MAC, "ulprbbl[%3i] = 0x%x\n", rb, ulprbbl[rb]);
}
}
long get_K2(NR_ServingCellConfigCommon_t *scc, long get_K2(NR_ServingCellConfigCommon_t *scc,
NR_ServingCellConfigCommonSIB_t *scc_sib1, NR_ServingCellConfigCommonSIB_t *scc_sib1,
NR_BWP_Uplink_t *ubwp, NR_BWP_Uplink_t *ubwp,
......
...@@ -434,7 +434,7 @@ int binomial(int n, int k); ...@@ -434,7 +434,7 @@ int binomial(int n, int k);
bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot); bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot);
void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, uint16_t symStart, int CC_id); void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, int ssb_subcarrier_offset, uint16_t symStart, int CC_id);
/* \brief Function to indicate a received SDU on ULSCH. /* \brief Function to indicate a received SDU on ULSCH.
...@@ -470,9 +470,19 @@ void handle_nr_ul_harq(const int CC_idP, ...@@ -470,9 +470,19 @@ void handle_nr_ul_harq(const int CC_idP,
sub_frame_t slot, sub_frame_t slot,
const nfapi_nr_crc_t *crc_pdu); const nfapi_nr_crc_t *crc_pdu);
void handle_nr_srs_measurements(const module_id_t module_id,
const frame_t frame,
const sub_frame_t slot,
const rnti_t rnti,
const uint16_t timing_advance,
const uint8_t num_symbols,
const uint8_t wide_band_snr,
const uint8_t num_reported_symbols,
nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list);
int16_t ssb_index_from_prach(module_id_t module_idP, int16_t ssb_index_from_prach(module_id_t module_idP,
frame_t frameP, frame_t frameP,
sub_frame_t slotP, sub_frame_t slotP,
uint16_t preamble_index, uint16_t preamble_index,
uint8_t freq_index, uint8_t freq_index,
uint8_t symbol); uint8_t symbol);
......
...@@ -84,23 +84,23 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset ...@@ -84,23 +84,23 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
int num = 1; int num = 1;
const char *begin = output; const char *begin = output;
const char *end = output + strlen; const char *end = output + strlen;
pthread_mutex_lock(&gNB->UE_info.mutex); pthread_mutex_lock(&gNB->UE_info.mutex);
UE_iterator(gNB->UE_info.list, UE) { UE_iterator(gNB->UE_info.list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_mac_stats_t *stats = &UE->mac_stats; NR_mac_stats_t *stats = &UE->mac_stats;
const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0; const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0;
output += snprintf(output, output += snprintf(output,
end - output, end - output,
"UE RNTI %04x (%d) PH %d dB PCMAX %d dBm, average RSRP %d (%d meas)\n", "UE RNTI %04x (%d) PH %d dB PCMAX %d dBm, average RSRP %d (%d meas), UL-SNR %d dB\n",
UE->rnti, UE->rnti,
num++, num++,
sched_ctrl->ph, sched_ctrl->ph,
sched_ctrl->pcmax, sched_ctrl->pcmax,
avg_rsrp, avg_rsrp,
stats->num_rsrp_meas); stats->num_rsrp_meas,
stats->srs_wide_band_snr);
output += snprintf(output, output += snprintf(output,
end - output, end - output,
"UE %04x: CQI %d, RI %d, PMI (%d,%d)\n", "UE %04x: CQI %d, RI %d, PMI (%d,%d)\n",
...@@ -232,7 +232,6 @@ void mac_top_init_gNB(void) ...@@ -232,7 +232,6 @@ void mac_top_init_gNB(void)
// Initialize Linked-List for Active UEs // Initialize Linked-List for Active UEs
for (i = 0; i < RC.nb_nr_macrlc_inst; i++) { for (i = 0; i < RC.nb_nr_macrlc_inst; i++) {
nrmac = RC.nrmac[i]; nrmac = RC.nrmac[i];
nrmac->if_inst = NR_IF_Module_init(i); nrmac->if_inst = NR_IF_Module_init(i);
memset(&nrmac->UE_info, 0, sizeof(nrmac->UE_info)); memset(&nrmac->UE_info, 0, sizeof(nrmac->UE_info));
......
...@@ -693,6 +693,7 @@ typedef struct NR_mac_stats { ...@@ -693,6 +693,7 @@ typedef struct NR_mac_stats {
uint32_t pucch0_DTX; uint32_t pucch0_DTX;
int cumul_rsrp; int cumul_rsrp;
uint8_t num_rsrp_meas; uint8_t num_rsrp_meas;
int8_t srs_wide_band_snr;
} NR_mac_stats_t; } NR_mac_stats_t;
typedef struct NR_bler_options { typedef struct NR_bler_options {
...@@ -759,12 +760,15 @@ typedef struct gNB_MAC_INST_s { ...@@ -759,12 +760,15 @@ typedef struct gNB_MAC_INST_s {
int pusch_target_snrx10; int pusch_target_snrx10;
/// Pucch target SNR /// Pucch target SNR
int pucch_target_snrx10; int pucch_target_snrx10;
/// SNR threshold needed to put or not a PRB in the black list
int ul_prbblack_SNR_threshold;
/// PUCCH Failure threshold (compared to consecutive PUCCH DTX) /// PUCCH Failure threshold (compared to consecutive PUCCH DTX)
int pucch_failure_thres; int pucch_failure_thres;
/// PUSCH Failure threshold (compared to consecutive PUSCH DTX) /// PUSCH Failure threshold (compared to consecutive PUSCH DTX)
int pusch_failure_thres; int pusch_failure_thres;
/// Subcarrier Offset /// Subcarrier Offset
int ssb_SubcarrierOffset; int ssb_SubcarrierOffset;
int ssb_OffsetPointA;
/// SIB1 Time domain allocation /// SIB1 Time domain allocation
int sib1_tda; int sib1_tda;
int minRXTXTIMEpdsch; int minRXTXTIMEpdsch;
...@@ -773,7 +777,7 @@ typedef struct gNB_MAC_INST_s { ...@@ -773,7 +777,7 @@ typedef struct gNB_MAC_INST_s {
/// current PDU index (BCH,DLSCH) /// current PDU index (BCH,DLSCH)
uint16_t pdu_index[NFAPI_CC_MAX]; uint16_t pdu_index[NFAPI_CC_MAX];
int num_ulprbbl; int num_ulprbbl;
uint16_t ulprbbl[275]; uint16_t ulprbbl[MAX_BWP_SIZE];
/// NFAPI Config Request Structure /// NFAPI Config Request Structure
nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX]; nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX];
/// NFAPI DL Config Request Structure /// NFAPI DL Config Request Structure
......
...@@ -215,6 +215,41 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) ...@@ -215,6 +215,41 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info)
UL_info->crc_ind.number_crcs = 0; UL_info->crc_ind.number_crcs = 0;
} }
void handle_nr_srs(NR_UL_IND_t *UL_info) {
if(NFAPI_MODE == NFAPI_MODE_PNF) {
if (UL_info->srs_ind.number_of_pdus > 0) {
LOG_D(PHY,"PNF Sending UL_info->srs_ind.number_of_pdus: %d, SFN/SF:%d.%d \n",
UL_info->srs_ind.number_of_pdus, UL_info->frame, UL_info->slot);
oai_nfapi_nr_srs_indication(&UL_info->srs_ind);
UL_info->srs_ind.number_of_pdus = 0;
}
return;
}
const module_id_t module_id = UL_info->module_id;
const frame_t frame = UL_info->srs_ind.sfn;
const sub_frame_t slot = UL_info->srs_ind.slot;
const int num_srs = UL_info->srs_ind.number_of_pdus;
const nfapi_nr_srs_indication_pdu_t *srs_list = UL_info->srs_ind.pdu_list;
for (int i = 0; i < num_srs; i++) {
const nfapi_nr_srs_indication_pdu_t *srs_ind = &srs_list[i];
LOG_D(NR_PHY, "(%d.%d) UL_info->srs_ind.pdu_list[%d].rnti: 0x%04x\n", frame, slot, i, srs_ind->rnti);
handle_nr_srs_measurements(module_id,
frame,
slot,
srs_ind->rnti,
srs_ind->timing_advance,
srs_ind->num_symbols,
srs_ind->wide_band_snr,
srs_ind->num_reported_symbols,
srs_ind->reported_symbol_list);
}
UL_info->srs_ind.number_of_pdus = 0;
}
static void free_unqueued_nfapi_indications(nfapi_nr_rach_indication_t *rach_ind, static void free_unqueued_nfapi_indications(nfapi_nr_rach_indication_t *rach_ind,
nfapi_nr_uci_indication_t *uci_ind, nfapi_nr_uci_indication_t *uci_ind,
nfapi_nr_rx_data_indication_t *rx_ind, nfapi_nr_rx_data_indication_t *rx_ind,
...@@ -431,6 +466,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { ...@@ -431,6 +466,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) {
// clear UL DCI prior to handling ULSCH // clear UL DCI prior to handling ULSCH
mac->UL_dci_req[CC_id].numPdus = 0; mac->UL_dci_req[CC_id].numPdus = 0;
handle_nr_ulsch(UL_info); handle_nr_ulsch(UL_info);
handle_nr_srs(UL_info);
if (get_softmodem_params()->emulate_l1) { if (get_softmodem_params()->emulate_l1) {
free_unqueued_nfapi_indications(rach_ind, uci_ind, rx_ind, crc_ind); free_unqueued_nfapi_indications(rach_ind, uci_ind, rx_ind, crc_ind);
......
This diff is collapsed.
...@@ -114,6 +114,7 @@ void fill_initial_cellGroupConfig(int uid, ...@@ -114,6 +114,7 @@ void fill_initial_cellGroupConfig(int uid,
const gNB_RrcConfigurationReq *configuration); const gNB_RrcConfigurationReq *configuration);
void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
const int uid,
NR_UE_NR_Capability_t *uecap, NR_UE_NR_Capability_t *uecap,
const gNB_RrcConfigurationReq *configuration); const gNB_RrcConfigurationReq *configuration);
......
...@@ -138,7 +138,6 @@ void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, int uid, int nb_sl ...@@ -138,7 +138,6 @@ void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, int uid, int nb_sl
} }
} }
void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon, void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
NR_CSI_MeasConfig_t *csi_MeasConfig, NR_CSI_MeasConfig_t *csi_MeasConfig,
int uid, int uid,
...@@ -324,6 +323,130 @@ void config_csiim(int do_csirs, int dl_antenna_ports, int curr_bwp, ...@@ -324,6 +323,130 @@ void config_csiim(int do_csirs, int dl_antenna_ports, int curr_bwp,
csi_MeasConfig->csi_IM_ResourceSetToReleaseList = NULL; csi_MeasConfig->csi_IM_ResourceSetToReleaseList = NULL;
} }
// TODO: Implement to b_SRS = 1 and b_SRS = 2
long rrc_get_max_nr_csrs(const uint8_t max_rbs, const long b_SRS) {
if(b_SRS>0) {
LOG_E(NR_RRC,"rrc_get_max_nr_csrs(): Not implemented yet for b_SRS>0\n");
return 0; // This c_srs is always valid
}
const uint16_t m_SRS[64] = { 4, 8, 12, 16, 16, 20, 24, 24, 28, 32, 36, 40, 48, 48, 52, 56, 60, 64, 72, 72, 76, 80, 88,
96, 96, 104, 112, 120, 120, 120, 128, 128, 128, 132, 136, 144, 144, 144, 144, 152, 160,
160, 160, 168, 176, 184, 192, 192, 192, 192, 208, 216, 224, 240, 240, 240, 240, 256, 256,
256, 264, 272, 272, 272 };
long c_srs = 0;
uint16_t m = 4;
for(int c = 1; c<64; c++) {
if(m_SRS[c]>m && m_SRS[c]<max_rbs) {
c_srs = c;
m = m_SRS[c];
}
}
return c_srs;
}
void config_srs(NR_SetupRelease_SRS_Config_t *setup_release_srs_Config,
const NR_ServingCellConfigCommon_t *servingcellconfigcommon,
const int uid,
const int do_srs) {
setup_release_srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup;
NR_SRS_Config_t *srs_Config;
if (setup_release_srs_Config->choice.setup) {
srs_Config = setup_release_srs_Config->choice.setup;
if (srs_Config->srs_ResourceSetToReleaseList) {
free(srs_Config->srs_ResourceSetToReleaseList);
}
if (srs_Config->srs_ResourceSetToAddModList) {
free(srs_Config->srs_ResourceSetToAddModList);
}
if (srs_Config->srs_ResourceToReleaseList) {
free(srs_Config->srs_ResourceToReleaseList);
}
if (srs_Config->srs_ResourceToAddModList) {
free(srs_Config->srs_ResourceToAddModList);
}
free(srs_Config);
}
setup_release_srs_Config->choice.setup = calloc(1,sizeof(*setup_release_srs_Config->choice.setup));
srs_Config = setup_release_srs_Config->choice.setup;
srs_Config->srs_ResourceSetToReleaseList = NULL;
srs_Config->srs_ResourceSetToAddModList = calloc(1,sizeof(*srs_Config->srs_ResourceSetToAddModList));
NR_SRS_ResourceSet_t *srs_resset0 = calloc(1,sizeof(*srs_resset0));
srs_resset0->srs_ResourceSetId = 0;
srs_resset0->srs_ResourceIdList = calloc(1,sizeof(*srs_resset0->srs_ResourceIdList));
NR_SRS_ResourceId_t *srs_resset0_id = calloc(1,sizeof(*srs_resset0_id));
*srs_resset0_id = 0;
ASN_SEQUENCE_ADD(&srs_resset0->srs_ResourceIdList->list, srs_resset0_id);
srs_Config->srs_ResourceToReleaseList=NULL;
if (do_srs) {
srs_resset0->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_periodic;
srs_resset0->resourceType.choice.periodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.periodic));
srs_resset0->resourceType.choice.periodic->associatedCSI_RS = NULL;
} else {
srs_resset0->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_aperiodic;
srs_resset0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic));
srs_resset0->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger=1;
srs_resset0->resourceType.choice.aperiodic->csi_RS=NULL;
srs_resset0->resourceType.choice.aperiodic->slotOffset = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic->slotOffset));
*srs_resset0->resourceType.choice.aperiodic->slotOffset = 2;
srs_resset0->resourceType.choice.aperiodic->ext1 = NULL;
}
srs_resset0->usage=NR_SRS_ResourceSet__usage_codebook;
srs_resset0->alpha = calloc(1,sizeof(*srs_resset0->alpha));
*srs_resset0->alpha = NR_Alpha_alpha1;
srs_resset0->p0 = calloc(1,sizeof(*srs_resset0->p0));
*srs_resset0->p0 =-80;
srs_resset0->pathlossReferenceRS = NULL;
srs_resset0->srs_PowerControlAdjustmentStates = NULL;
ASN_SEQUENCE_ADD(&srs_Config->srs_ResourceSetToAddModList->list,srs_resset0);
srs_Config->srs_ResourceToReleaseList = NULL;
srs_Config->srs_ResourceToAddModList = calloc(1,sizeof(*srs_Config->srs_ResourceToAddModList));
NR_SRS_Resource_t *srs_res0=calloc(1,sizeof(*srs_res0));
srs_res0->srs_ResourceId = 0;
srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_port1;
srs_res0->ptrs_PortIndex = NULL;
srs_res0->transmissionComb.present = NR_SRS_Resource__transmissionComb_PR_n2;
srs_res0->transmissionComb.choice.n2 = calloc(1,sizeof(*srs_res0->transmissionComb.choice.n2));
srs_res0->transmissionComb.choice.n2->combOffset_n2 = 0;
srs_res0->transmissionComb.choice.n2->cyclicShift_n2 = 0;
srs_res0->resourceMapping.startPosition = 2 + uid%2;
srs_res0->resourceMapping.nrofSymbols = NR_SRS_Resource__resourceMapping__nrofSymbols_n1;
srs_res0->resourceMapping.repetitionFactor = NR_SRS_Resource__resourceMapping__repetitionFactor_n1;
srs_res0->freqDomainPosition = 0;
srs_res0->freqDomainShift = 0;
srs_res0->freqHopping.b_SRS = 0;
srs_res0->freqHopping.b_hop = 0;
srs_res0->freqHopping.c_SRS = servingcellconfigcommon ?
rrc_get_max_nr_csrs(
NRRIV2BW(servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 275),
srs_res0->freqHopping.b_SRS) : 0;
srs_res0->groupOrSequenceHopping = NR_SRS_Resource__groupOrSequenceHopping_neither;
if (do_srs) {
srs_res0->resourceType.present = NR_SRS_Resource__resourceType_PR_periodic;
srs_res0->resourceType.choice.periodic = calloc(1,sizeof(*srs_res0->resourceType.choice.periodic));
srs_res0->resourceType.choice.periodic->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl160;
srs_res0->resourceType.choice.periodic->periodicityAndOffset_p.choice.sl160 = 17 + (uid>1)*10; // 17/17/.../147/157 are mixed slots
} else {
srs_res0->resourceType.present = NR_SRS_Resource__resourceType_PR_aperiodic;
srs_res0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_res0->resourceType.choice.aperiodic));
}
srs_res0->sequenceId = 40;
srs_res0->spatialRelationInfo = calloc(1,sizeof(*srs_res0->spatialRelationInfo));
srs_res0->spatialRelationInfo->servingCellId = NULL;
srs_res0->spatialRelationInfo->referenceSignal.present = NR_SRS_SpatialRelationInfo__referenceSignal_PR_csi_RS_Index;
srs_res0->spatialRelationInfo->referenceSignal.choice.csi_RS_Index = 0;
ASN_SEQUENCE_ADD(&srs_Config->srs_ResourceToAddModList->list,srs_res0);
}
void prepare_sim_uecap(NR_UE_NR_Capability_t *cap, void prepare_sim_uecap(NR_UE_NR_Capability_t *cap,
NR_ServingCellConfigCommon_t *scc, NR_ServingCellConfigCommon_t *scc,
......
...@@ -134,6 +134,10 @@ void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon, ...@@ -134,6 +134,10 @@ void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
int do_csirs); int do_csirs);
void config_csiim(int do_csirs, int dl_antenna_ports, int curr_bwp, void config_csiim(int do_csirs, int dl_antenna_ports, int curr_bwp,
NR_CSI_MeasConfig_t *csi_MeasConfig); NR_CSI_MeasConfig_t *csi_MeasConfig);
void config_srs(NR_SetupRelease_SRS_Config_t *setup_release_srs_Config,
const NR_ServingCellConfigCommon_t *servingcellconfigcommon,
const int uid,
const int do_srs);
void set_dl_mcs_table(int scs, NR_UE_NR_Capability_t *cap, void set_dl_mcs_table(int scs, NR_UE_NR_Capability_t *cap,
NR_SpCellConfig_t *SpCellConfig, NR_SpCellConfig_t *SpCellConfig,
NR_BWP_DownlinkDedicated_t *bwp_Dedicated, NR_BWP_DownlinkDedicated_t *bwp_Dedicated,
......
...@@ -197,7 +197,7 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration ...@@ -197,7 +197,7 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration
} }
char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq *configuration) { char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq *configuration) {
protocol_ctxt_t ctxt; protocol_ctxt_t ctxt = { 0 };
gNB_RRC_INST *rrc=RC.nrrrc[gnb_mod_idP]; gNB_RRC_INST *rrc=RC.nrrrc[gnb_mod_idP];
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, gnb_mod_idP, GNB_FLAG_YES, NOT_A_RNTI, 0, 0,gnb_mod_idP); PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, gnb_mod_idP, GNB_FLAG_YES, NOT_A_RNTI, 0, 0,gnb_mod_idP);
LOG_I(NR_RRC, LOG_I(NR_RRC,
...@@ -1949,7 +1949,7 @@ int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP ...@@ -1949,7 +1949,7 @@ int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL, ue_context_pP,
NULL, NULL,
NULL, NULL,
NULL, NULL,
...@@ -3030,11 +3030,13 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC ...@@ -3030,11 +3030,13 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC
static int rrc_process_DU_DL(MessageDef *msg_p, const char *msg_name, instance_t instance) { static int rrc_process_DU_DL(MessageDef *msg_p, const char *msg_name, instance_t instance) {
NRDuDlReq_t * req=&NRDuDlReq(msg_p); NRDuDlReq_t * req=&NRDuDlReq(msg_p);
protocol_ctxt_t ctxt; protocol_ctxt_t ctxt = {
ctxt.rnti = req->rnti; .rnti = req->rnti,
ctxt.module_id = instance; .module_id = instance,
ctxt.instance = instance; .instance = instance,
ctxt.enb_flag = 1; .enb_flag = 1,
.eNB_index = instance
};
gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
struct rrc_gNB_ue_context_s *ue_context_p = struct rrc_gNB_ue_context_s *ue_context_p =
rrc_gNB_get_ue_context(rrc, ctxt.rnti); rrc_gNB_get_ue_context(rrc, ctxt.rnti);
...@@ -3285,11 +3287,13 @@ return 0; ...@@ -3285,11 +3287,13 @@ return 0;
static void rrc_DU_process_ue_context_setup_request(MessageDef *msg_p, const char *msg_name, instance_t instance){ static void rrc_DU_process_ue_context_setup_request(MessageDef *msg_p, const char *msg_name, instance_t instance){
f1ap_ue_context_setup_t * req=&F1AP_UE_CONTEXT_SETUP_REQ(msg_p); f1ap_ue_context_setup_t * req=&F1AP_UE_CONTEXT_SETUP_REQ(msg_p);
protocol_ctxt_t ctxt; protocol_ctxt_t ctxt = {
ctxt.rnti = req->rnti; .rnti = req->rnti,
ctxt.module_id = instance; .module_id = instance,
ctxt.instance = instance; .instance = instance,
ctxt.enb_flag = 1; .enb_flag = 1,
.eNB_index = instance
};
gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
gNB_MAC_INST *mac = RC.nrmac[ctxt.module_id]; gNB_MAC_INST *mac = RC.nrmac[ctxt.module_id];
struct rrc_gNB_ue_context_s *ue_context_p = struct rrc_gNB_ue_context_s *ue_context_p =
...@@ -3515,11 +3519,13 @@ static void rrc_DU_process_ue_context_setup_request(MessageDef *msg_p, const cha ...@@ -3515,11 +3519,13 @@ static void rrc_DU_process_ue_context_setup_request(MessageDef *msg_p, const cha
static void rrc_DU_process_ue_context_modification_request(MessageDef *msg_p, const char *msg_name, instance_t instance){ static void rrc_DU_process_ue_context_modification_request(MessageDef *msg_p, const char *msg_name, instance_t instance){
f1ap_ue_context_setup_t * req=&F1AP_UE_CONTEXT_MODIFICATION_REQ(msg_p); f1ap_ue_context_setup_t * req=&F1AP_UE_CONTEXT_MODIFICATION_REQ(msg_p);
protocol_ctxt_t ctxt; protocol_ctxt_t ctxt = {
ctxt.rnti = req->rnti; .rnti = req->rnti,
ctxt.module_id = instance; .module_id = instance,
ctxt.instance = instance; .instance = instance,
ctxt.enb_flag = 1; .enb_flag = 1,
.eNB_index = instance
};
gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
gNB_MAC_INST *mac = RC.nrmac[ctxt.module_id]; gNB_MAC_INST *mac = RC.nrmac[ctxt.module_id];
struct rrc_gNB_ue_context_s *ue_context_p = struct rrc_gNB_ue_context_s *ue_context_p =
...@@ -3664,11 +3670,13 @@ static void rrc_DU_process_ue_context_modification_request(MessageDef *msg_p, co ...@@ -3664,11 +3670,13 @@ static void rrc_DU_process_ue_context_modification_request(MessageDef *msg_p, co
static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const char *msg_name, instance_t instance){ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const char *msg_name, instance_t instance){
f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p); f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p);
protocol_ctxt_t ctxt; protocol_ctxt_t ctxt = {
ctxt.rnti = resp->rnti; .rnti = resp->rnti,
ctxt.module_id = instance; .module_id = instance,
ctxt.instance = instance; .instance = instance,
ctxt.enb_flag = 1; .enb_flag = 1,
.eNB_index = instance
};
gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context(rrc, ctxt.rnti); struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context(rrc, ctxt.rnti);
NR_CellGroupConfig_t *cellGroupConfig = NULL; NR_CellGroupConfig_t *cellGroupConfig = NULL;
...@@ -3721,12 +3729,13 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const ch ...@@ -3721,12 +3729,13 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const ch
static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, const char *msg_name, instance_t instance){ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, const char *msg_name, instance_t instance){
f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p); f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p);
protocol_ctxt_t ctxt; protocol_ctxt_t ctxt = {
ctxt.rnti = resp->rnti; .rnti = resp->rnti,
ctxt.module_id = instance; .module_id = instance,
ctxt.instance = instance; .instance = instance,
ctxt.enb_flag = 1; .enb_flag = 1,
ctxt.eNB_index = instance; .eNB_index = instance
};
gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context(rrc, ctxt.rnti); struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context(rrc, ctxt.rnti);
NR_CellGroupConfig_t *cellGroupConfig = NULL; NR_CellGroupConfig_t *cellGroupConfig = NULL;
......
...@@ -265,6 +265,7 @@ MACRLCs = ( ...@@ -265,6 +265,7 @@ MACRLCs = (
tr_n_preference = "local_RRC"; tr_n_preference = "local_RRC";
#pusch_TargetSNRx10 = 150; #pusch_TargetSNRx10 = 150;
#pucch_TargetSNRx10 = 200; #pucch_TargetSNRx10 = 200;
ul_prbblack_SNR_threshold = 10;
ulsch_max_frame_inactivity = 0; ulsch_max_frame_inactivity = 0;
} }
); );
......
...@@ -263,6 +263,7 @@ MACRLCs = ( ...@@ -263,6 +263,7 @@ MACRLCs = (
tr_n_preference = "local_RRC"; tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 150; pusch_TargetSNRx10 = 150;
pucch_TargetSNRx10 = 200; pucch_TargetSNRx10 = 200;
ul_prbblack_SNR_threshold = 10;
ulsch_max_frame_inactivity = 0; ulsch_max_frame_inactivity = 0;
} }
); );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment