Merge remote-tracking branch 'origin/develop-SRS-feedback' into integration_2022_wk40
This commit is contained in:
@@ -328,6 +328,7 @@ The following features are valid for the gNB and the 5G-NR UE.
|
||||
- HARQ procedures for uplink
|
||||
- Scheduler procedures for SRS reception
|
||||
- Periodic SRS reception
|
||||
- TPMI computation based on SRS up 4 antenna ports and 1 layer
|
||||
- MAC procedures to handle CSI measurement report
|
||||
- evalution of RSRP report
|
||||
- evaluation of CQI report
|
||||
|
||||
@@ -4060,4 +4060,42 @@ int nfapi_p7_update_checksum(uint8_t* buffer, uint32_t len);
|
||||
*/
|
||||
int nfapi_p7_update_transmit_timestamp(uint8_t* buffer, uint32_t timestamp);
|
||||
|
||||
/*! \brief Encodes a nfapi_nr_srs_normalized_channel_iq_matrix_t to a buffer
|
||||
*
|
||||
* \param pMessageBuf A pointer to a nfapi_nr_srs_normalized_channel_iq_matrix_t structure
|
||||
* \param pPackedBuf A pointer to the buffer that the nfapi_nr_srs_normalized_channel_iq_matrix_t will be packed into
|
||||
* \param packedBufLen The size of the buffer
|
||||
* \return number of bytes written to the buffer
|
||||
*/
|
||||
int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen);
|
||||
|
||||
/*! \brief Decodes a nfapi_nr_srs_normalized_channel_iq_matrix_t from a buffer
|
||||
*
|
||||
* \param pMessageBuf A pointer to an encoded nfapi_nr_srs_normalized_channel_iq_matrix_t
|
||||
* \param messageBufLen The size of the encoded nfapi_nr_srs_normalized_channel_iq_matrix_t
|
||||
* \param pUnpackedBuf A pointer to the nfapi_nr_srs_normalized_channel_iq_matrix_t
|
||||
* \param unpackedBufLen The size of nfapi_nr_srs_normalized_channel_iq_matrix_t structure.
|
||||
* \return 0 means success, -1 means failure.
|
||||
*/
|
||||
int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen);
|
||||
|
||||
/*! \brief Encodes a nfapi_nr_srs_beamforming_report_t to a buffer
|
||||
*
|
||||
* \param pMessageBuf A pointer to a nfapi_nr_srs_beamforming_report_t structure
|
||||
* \param pPackedBuf A pointer to the buffer that the nfapi_nr_srs_beamforming_report_t will be packed into
|
||||
* \param packedBufLen The size of the buffer
|
||||
* \return number of bytes written to the buffer
|
||||
*/
|
||||
int pack_nr_srs_beamforming_report(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen);
|
||||
|
||||
/*! \brief Decodes a nfapi_nr_srs_beamforming_report_t from a buffer
|
||||
*
|
||||
* \param pMessageBuf A pointer to an encoded nfapi_nr_srs_beamforming_report_t
|
||||
* \param messageBufLen The size of the encoded nfapi_nr_srs_beamforming_report_t
|
||||
* \param pUnpackedBuf A pointer to the nfapi_nr_srs_beamforming_report_t
|
||||
* \param unpackedBufLen The size of nfapi_nr_srs_beamforming_report_t structure.
|
||||
* \return 0 means success, -1 means failure.
|
||||
*/
|
||||
int unpack_nr_srs_beamforming_report(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen);
|
||||
|
||||
#endif /* _NFAPI_INTERFACE_H_ */
|
||||
|
||||
@@ -1107,17 +1107,15 @@ typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
nfapi_nr_dig_bf_interface_t* dig_bf_interface_list;
|
||||
|
||||
} nfapi_nr_ul_beamforming_number_of_prgs_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t num_prgs;
|
||||
uint16_t prg_size;
|
||||
//watchout: dig_bf_interface here, in table 3-43 it's dig_bf_interfaces
|
||||
uint8_t dig_bf_interface;
|
||||
nfapi_nr_ul_beamforming_number_of_prgs_t* prgs_list;//
|
||||
|
||||
uint8_t trp_scheme; // This field shall be set to 0, to identify that this table is used.
|
||||
uint16_t num_prgs; // Number of PRGs spanning this allocation. Value : 1->275
|
||||
uint16_t prg_size; // Size in RBs of a precoding resource block group (PRG) – to which the same digital beamforming gets applied. Value: 1->275
|
||||
uint8_t dig_bf_interface; // Number of logical antenna ports (parallel streams) resulting from the Rx combining. Value: 0->255
|
||||
nfapi_nr_ul_beamforming_number_of_prgs_t *prgs_list;
|
||||
} nfapi_nr_ul_beamforming_t;
|
||||
|
||||
typedef struct
|
||||
@@ -1292,6 +1290,28 @@ typedef struct
|
||||
|
||||
} nfapi_nr_pucch_pdu_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t srs_bandwidth_start; // PRB index for the start of SRS signal transmission. The PRB index is relative to the CRB0 or reference Point A. 3GPP TS 38.211, section 6.4.1.4.3. Value: 0->268
|
||||
uint8_t sequence_group; // Sequence group (u) as defined in 3GPP TS 38.211, section 6.4.1.4.2. Value: 0->29
|
||||
uint8_t sequence_number; // Sequence number (v) as defined in 3GPP TS 38.211, section 6.4.1.4.2 TS 38.211. Value: 0->1
|
||||
} nfapi_v4_srs_parameters_symbols_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t srs_bandwidth_size; // mSRS,b: Number of PRB’s that are sounded for each SRS symbol, per 3GPP TS 38.211, section 6.4.1.4.3. Value: 4->272
|
||||
nfapi_v4_srs_parameters_symbols_t *symbol_list;
|
||||
uint32_t usage; // Bitmap indicating the type of report(s) expected at L2 from the SRS signaled by this PDU. Bit positions: 0 – beamManagement; 1 – codebook; 2 – nonCodebook; 3 – antennaSwitching; 4 – 255: reserved. For each of this bit positions: 1 = requested; 0 = not requested. nUsage = sum(all bits in usage)
|
||||
uint8_t report_type[4]; // Interpretation of each Report Type depends on usage: beamManagement (1 = PRG SNR, 2-255 reserved); codebook (1 = PRG I and Q channel estimate, per srs Tx port and gNB antenna element, 2-255 reserved); nonCodebook (1 = PRG I and Q channel estimate, per SRI and gNB antenna element, 2-255 reserved); antennaSwitching (1 = SVD representation UE Rx and gNB sets of antenna element, 2-255 reserved); all (0 – no report required).
|
||||
uint8_t singular_Value_representation; // 0 – 8-bit dB; 1 – 16-bit linear; 255 – not applicable
|
||||
uint8_t iq_representation; // 0 – 16 bit; 1 – 32-bit; 255 - not applicable
|
||||
uint16_t prg_size; // 1-272; 0 – reserved
|
||||
uint8_t num_total_ue_antennas; // 1 … 16 in this release. This is the total number of UE antennas for the usage.
|
||||
uint32_t ue_antennas_in_this_srs_resource_set; // Bitmap of UE antenna indices for the SRS Resource set, to which the SRS Resource for this PDU corresponds.
|
||||
uint32_t sampled_ue_antennas; // Bitmap of UE antenna indices sampled by the SRS waveform corresponding to this PDU’s SRS Resource. Codebook: corresponds to antenna ports in SRS Resources; non-overlapping indices; Non-codebook: corresponds to SRIs; Antennas-switch: indices of UE Rx antennas in the total number of antennas.
|
||||
uint8_t report_scope; // Which antennas Report (in ReportType) should account for: Value: 0: ports in sampledUeAntennas (i.e. SRS Resource); 1: ports in ueAntennasInSrsResourceSet (i.e. SRS Resource set. For antSwith reports of SVD type, value 0 is only allowed if sampledUeAntennas = ueAntennasInSrsResourceSet.
|
||||
uint8_t num_ul_spatial_streams_ports; // In this release, L2 may set this number to 0 to leave spatial stream index assignment to L1 (e.g. L1 uses spatial streams reserved for SRS), regardless of the information in capability maxNumberUlSpatialStreams.
|
||||
uint8_t Ul_spatial_stream_ports[256]; // Number of ports used for signaling this SRS allocation. Value: 0 --> (max # spatial streams - 1, per TLV)
|
||||
} nfapi_v4_srs_parameters_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t rnti; // UE RNTI, Value: 1->65535
|
||||
uint32_t handle; // An opaque handling returned in the SRS.indication
|
||||
@@ -1317,6 +1337,7 @@ typedef struct {
|
||||
uint16_t t_srs; // SRS-Periodicity in slots [3GPP TS 38.211, Sec 6.4.1.4.4], Value: 1,2,3,4,5,8,10,16,20,32,40,64,80,160,320,640,1280,2560
|
||||
uint16_t t_offset; // Slot offset value [3GPP TS 38.211, Sec 6.4.1.4.3], Value:0->2559
|
||||
nfapi_nr_ul_beamforming_t beamforming;
|
||||
nfapi_v4_srs_parameters_t srs_parameters_v4;
|
||||
} nfapi_nr_srs_pdu_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -1660,33 +1681,63 @@ typedef struct
|
||||
} nfapi_nr_uci_indication_t;
|
||||
|
||||
|
||||
/// 5G PHY FAPI Specification: SRS indication - Section 3.4.10, Table 3-73
|
||||
/// 5G PHY FAPI Specification: SRS indication - Section 3.4.10
|
||||
|
||||
// Normalized channel I/Q matrix
|
||||
|
||||
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.
|
||||
} nfapi_nr_srs_indication_reported_symbol_resource_block_t;
|
||||
uint8_t normalized_iq_representation; // 0: 16-bit normalized complex number (iqSize = 2); 1: 32-bit normalized complex number (iqSize = 4)
|
||||
uint16_t num_gnb_antenna_elements; // Ng: Number of gNB antenna elements. Value: 0511
|
||||
uint16_t num_ue_srs_ports; // Nu: Number of sampled UE SRS ports. Value: 07
|
||||
uint16_t prg_size; // Size in RBs of a precoding resource block group (PRG) – to which the same digital beamforming gets applied. Value: 1->272
|
||||
uint16_t num_prgs; // Number of PRGs Np to be reported for this SRS PDU. Value: 0-> 272
|
||||
uint8_t channel_matrix[272*512*8*4]; // Array of (numPRGs*Nu*Ng) entries of the type denoted by iqRepresentation H{PRG pI} [ueAntenna uI, gNB antenna gI] = array[uI*Ng*Np + gI*Np + pI]; uI: 0…Nu-1 (UE antenna index); gI: 0…Ng-1 (gNB antenna index); pI: 0…Np-1 (PRG index)
|
||||
} nfapi_nr_srs_normalized_channel_iq_matrix_t;
|
||||
|
||||
// Beamforming report
|
||||
|
||||
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_t;
|
||||
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.
|
||||
} nfapi_nr_srs_reported_symbol_prgs_t;
|
||||
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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_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.
|
||||
nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list;
|
||||
uint16_t num_prgs; // Number of PRBs to be reported for this SRS PDU. Value: 0 -> 272.
|
||||
nfapi_nr_srs_reported_symbol_prgs_t *prg_list;
|
||||
} nfapi_nr_srs_reported_symbol_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t prg_size; // Size in RBs of a precoding resource block group (PRG) – to which the same digital beamforming gets applied. Value: 1->275
|
||||
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.
|
||||
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_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.
|
||||
nfapi_nr_srs_reported_symbol_t *prgs;
|
||||
} nfapi_nr_srs_beamforming_report_t;
|
||||
|
||||
// SRS indication
|
||||
|
||||
typedef struct {
|
||||
uint16_t tag; // 0: Report is carried directly in the value field; 3: The offset from the end of the control portion of the message to the beginning of the report. Other values are reserved.
|
||||
uint32_t length; // Length of the actual report in bytes, without the padding bytes.
|
||||
uint32_t value[16384]; // tag=0: Only the most significant bytes of the size indicated by ‘length’ field are valid. Remaining bytes are zero padded to the nearest 32-bit bit boundary; Tag=2 Offset from the end of the control portion of the message to the payload is in the value field. Occupies 32-bits.
|
||||
} nfapi_srs_report_tlv_t;
|
||||
|
||||
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.
|
||||
uint16_t timing_advance_offset; // Timing advance TA measured for the UE in multiples of 16 * 64 * Tc / (2^u) [TS 38.213, Section 4.2]. Value: 0 -> 63. 0xffff will be set if this field is invalid.
|
||||
int16_t timing_advance_offset_nsec; // Timing advance measured for the UE between the reference uplink time and the observed arrival time for the UE. Value: -16800 … +16800 nanoseconds. 0xffff should be set if this field is invalid.
|
||||
uint8_t srs_usage; // 0 – beamManagement; 1 – codebook; 2 – nonCodebook; 3 – antennaSwitching; 4 – 255: reserved; Note: This field matches the SRS usage field of the SRS PDU to which this report is linked.
|
||||
uint8_t report_type; // The type of report included in or pointed to by Report TLV depends on the SRS usage: Beam management (1: Beamforming report); Codebook (1: Normalized Channel I/Q Matrix); nonCodebook (1: Normalized Channel I/Q Matrix); antennaSwitch (1: Channel SVD Representation); all (0: null report)
|
||||
nfapi_srs_report_tlv_t *report_tlv;
|
||||
} nfapi_nr_srs_indication_pdu_t;
|
||||
|
||||
typedef struct {
|
||||
nfapi_p7_message_header_t header;
|
||||
uint16_t sfn; // SFN. Value: 0 -> 1023
|
||||
uint16_t slot; // Slot. Value: 0 -> 159
|
||||
uint8_t number_of_pdus; // Number of PDUs included in this message. Value: 0 -> 255
|
||||
nfapi_nr_srs_indication_pdu_t* pdu_list;
|
||||
uint16_t sfn; // SFN. Value: 0 -> 1023
|
||||
uint16_t slot; // Slot. Value: 0 -> 159
|
||||
uint16_t control_length; // Size of control portion of SRS indication. 0 if reports are included inline; >0 if reports are concatenated to the end of the message.
|
||||
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_t;
|
||||
|
||||
|
||||
|
||||
@@ -3099,42 +3099,131 @@ return 1;
|
||||
|
||||
//SRS INDICATION
|
||||
|
||||
static uint8_t pack_nr_srs_indication_body(nfapi_nr_srs_indication_pdu_t *value, uint8_t **ppWritePackedMsg, uint8_t *end)
|
||||
{
|
||||
if(!(push32(value->handle, ppWritePackedMsg, end) &&
|
||||
push16(value->rnti, ppWritePackedMsg, end) &&
|
||||
push16(value->timing_advance, ppWritePackedMsg, end) &&
|
||||
push8(value->num_symbols, ppWritePackedMsg, end) &&
|
||||
push8(value->wide_band_snr, ppWritePackedMsg, end) &&
|
||||
push8(value->num_reported_symbols, ppWritePackedMsg, end) &&
|
||||
push8(value->reported_symbol_list->num_rbs, ppWritePackedMsg, end)
|
||||
))
|
||||
return 0;
|
||||
for(int i = 0; i < value->reported_symbol_list->num_rbs; i++)
|
||||
{
|
||||
if (!push8(value->reported_symbol_list->rb_list[i].rb_snr, ppWritePackedMsg, end))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen) {
|
||||
|
||||
nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_normalized_channel_iq_matrix = (nfapi_nr_srs_normalized_channel_iq_matrix_t*)pMessageBuf;
|
||||
|
||||
uint8_t *pWritePackedMessage = pPackedBuf;
|
||||
uint8_t *end = pPackedBuf + packedBufLen;
|
||||
|
||||
if(!(push8(nr_srs_normalized_channel_iq_matrix->normalized_iq_representation, &pWritePackedMessage, end) &&
|
||||
push16(nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements, &pWritePackedMessage, end) &&
|
||||
push16(nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports, &pWritePackedMessage, end) &&
|
||||
push16(nr_srs_normalized_channel_iq_matrix->prg_size, &pWritePackedMessage, end) &&
|
||||
push16(nr_srs_normalized_channel_iq_matrix->num_prgs, &pWritePackedMessage, end))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t channel_matrix_size = nr_srs_normalized_channel_iq_matrix->num_prgs*nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports*nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements;
|
||||
if (nr_srs_normalized_channel_iq_matrix->normalized_iq_representation == 0) {
|
||||
channel_matrix_size <<= 1;
|
||||
} else {
|
||||
channel_matrix_size <<= 2;
|
||||
}
|
||||
|
||||
for(int i = 0; i < channel_matrix_size; i++) {
|
||||
if (!push8(nr_srs_normalized_channel_iq_matrix->channel_matrix[i], &pWritePackedMessage, end)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Message length
|
||||
uintptr_t msgHead = (uintptr_t)pPackedBuf;
|
||||
uintptr_t msgEnd = (uintptr_t)pWritePackedMessage;
|
||||
return (msgEnd-msgHead);
|
||||
}
|
||||
|
||||
static uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
|
||||
{
|
||||
nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg;
|
||||
static uint8_t pack_nr_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *prgs, uint8_t **ppWritePackedMsg, uint8_t *end) {
|
||||
|
||||
if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) &&
|
||||
push16(pNfapiMsg->slot , ppWritePackedMsg, end) &&
|
||||
push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end)
|
||||
))
|
||||
return 0;
|
||||
if(!push16(prgs->num_prgs, ppWritePackedMsg, end)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(int i=0; i<pNfapiMsg->number_of_pdus;i++)
|
||||
{
|
||||
if(!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end))
|
||||
return 0;
|
||||
}
|
||||
for(int i = 0; i < prgs->num_prgs; i++) {
|
||||
if (!push8(prgs->prg_list[i].rb_snr, ppWritePackedMsg, end)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pack_nr_srs_beamforming_report(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen) {
|
||||
|
||||
nfapi_nr_srs_beamforming_report_t *nr_srs_beamforming_report = (nfapi_nr_srs_beamforming_report_t*)pMessageBuf;
|
||||
|
||||
uint8_t *pWritePackedMessage = pPackedBuf;
|
||||
uint8_t *end = pPackedBuf + packedBufLen;
|
||||
|
||||
if(!(push16(nr_srs_beamforming_report->prg_size, &pWritePackedMessage, end) &&
|
||||
push8(nr_srs_beamforming_report->num_symbols, &pWritePackedMessage, end) &&
|
||||
push8(nr_srs_beamforming_report->wide_band_snr, &pWritePackedMessage, end) &&
|
||||
push8(nr_srs_beamforming_report->num_reported_symbols, &pWritePackedMessage, end))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!pack_nr_srs_reported_symbol(nr_srs_beamforming_report->prgs, &pWritePackedMessage, end)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Message length
|
||||
uintptr_t msgHead = (uintptr_t)pPackedBuf;
|
||||
uintptr_t msgEnd = (uintptr_t)pWritePackedMessage;
|
||||
return (msgEnd-msgHead);
|
||||
}
|
||||
|
||||
static uint8_t pack_nr_srs_report_tlv(nfapi_srs_report_tlv_t *report_tlv, uint8_t **ppWritePackedMsg, uint8_t *end) {
|
||||
|
||||
if(!(push16(report_tlv->tag, ppWritePackedMsg, end) &&
|
||||
push32(report_tlv->length, ppWritePackedMsg, end))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(int i = 0; i < report_tlv->length; i++) {
|
||||
if (!push32(report_tlv->value[i], ppWritePackedMsg, end)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t pack_nr_srs_indication_body(nfapi_nr_srs_indication_pdu_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) {
|
||||
|
||||
if(!(push32(value->handle, ppWritePackedMsg, end) &&
|
||||
push16(value->rnti, ppWritePackedMsg, end) &&
|
||||
push16(value->timing_advance_offset, ppWritePackedMsg, end) &&
|
||||
pushs16(value->timing_advance_offset_nsec, ppWritePackedMsg, end) &&
|
||||
push8(value->srs_usage, ppWritePackedMsg, end) &&
|
||||
push8(value->report_type, ppWritePackedMsg, end))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!pack_nr_srs_report_tlv(value->report_tlv,ppWritePackedMsg, end)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) {
|
||||
|
||||
nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg;
|
||||
|
||||
if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) &&
|
||||
push16(pNfapiMsg->slot , ppWritePackedMsg, end) &&
|
||||
push16(pNfapiMsg->control_length , ppWritePackedMsg, end) &&
|
||||
push8(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(int i=0; i<pNfapiMsg->number_of_pdus;i++) {
|
||||
if(!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg, end)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//RACH INDICATION
|
||||
@@ -5793,40 +5882,133 @@ return 1;
|
||||
|
||||
//SRS INDICATION
|
||||
|
||||
static uint8_t unpack_nr_srs_indication_body(nfapi_nr_srs_indication_pdu_t* value, uint8_t **ppReadPackedMsg, uint8_t *end)
|
||||
{
|
||||
if(!(pull32(ppReadPackedMsg, &value->handle, end) &&
|
||||
pull16(ppReadPackedMsg, &value->rnti, end) &&
|
||||
pull16(ppReadPackedMsg, &value->timing_advance, end) &&
|
||||
pull8(ppReadPackedMsg, &value->num_symbols, end) &&
|
||||
pull8(ppReadPackedMsg, &value->wide_band_snr, end) &&
|
||||
pull8(ppReadPackedMsg, &value->num_reported_symbols, end) &&
|
||||
pull16(ppReadPackedMsg, &value->reported_symbol_list->num_rbs, end)
|
||||
))
|
||||
return 0;
|
||||
for(int i = 0; i < value->reported_symbol_list->num_rbs; i++)
|
||||
{
|
||||
if (!pull8(ppReadPackedMsg, &value->reported_symbol_list->rb_list[i].rb_snr, end))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen) {
|
||||
|
||||
nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_normalized_channel_iq_matrix = (nfapi_nr_srs_normalized_channel_iq_matrix_t*)pUnpackedBuf;
|
||||
uint8_t *pReadPackedMessage = pMessageBuf;
|
||||
uint8_t *end = pMessageBuf + messageBufLen;
|
||||
|
||||
memset(pUnpackedBuf, 0, unpackedBufLen);
|
||||
|
||||
if(!(pull8(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->normalized_iq_representation, end) &&
|
||||
pull16(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements, end) &&
|
||||
pull16(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports, end) &&
|
||||
pull16(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->prg_size, end) &&
|
||||
pull16(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->num_prgs, end))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t channel_matrix_size = nr_srs_normalized_channel_iq_matrix->num_prgs*nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports*nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements;
|
||||
if (nr_srs_normalized_channel_iq_matrix->normalized_iq_representation == 0) {
|
||||
channel_matrix_size <<= 1;
|
||||
} else {
|
||||
channel_matrix_size <<= 2;
|
||||
}
|
||||
|
||||
for(int i = 0; i < channel_matrix_size; i++) {
|
||||
if (!pull8(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->channel_matrix[i], end)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_srs_indication_t *pNfapiMsg, nfapi_p7_codec_config_t* config)
|
||||
{
|
||||
if (!(pull16(ppReadPackedMsg,&pNfapiMsg->sfn , end) &&
|
||||
pull16(ppReadPackedMsg,&pNfapiMsg->slot , end) &&
|
||||
pull8(ppReadPackedMsg,&pNfapiMsg->number_of_pdus, end)
|
||||
))
|
||||
return 0;
|
||||
static uint8_t unpack_nr_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *prgs, uint8_t **ppReadPackedMsg, uint8_t *end) {
|
||||
|
||||
for(int i=0; i<pNfapiMsg->number_of_pdus;i++)
|
||||
{
|
||||
if (!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end))
|
||||
return 0;
|
||||
}
|
||||
if(!pull16(ppReadPackedMsg, &prgs->num_prgs, end)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
if(!prgs->prg_list) {
|
||||
prgs->prg_list = (nfapi_nr_srs_reported_symbol_prgs_t*) calloc(1, prgs->num_prgs*sizeof(nfapi_nr_srs_reported_symbol_prgs_t));
|
||||
}
|
||||
|
||||
for(int i = 0; i < prgs->num_prgs; i++) {
|
||||
if (!pull8(ppReadPackedMsg, &prgs->prg_list[i].rb_snr, end)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int unpack_nr_srs_beamforming_report(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen) {
|
||||
|
||||
nfapi_nr_srs_beamforming_report_t *nr_srs_beamforming_report = (nfapi_nr_srs_beamforming_report_t*)pUnpackedBuf;
|
||||
uint8_t *pReadPackedMessage = pMessageBuf;
|
||||
uint8_t *end = pMessageBuf + messageBufLen;
|
||||
|
||||
memset(pUnpackedBuf, 0, unpackedBufLen);
|
||||
|
||||
if(!(pull16(&pReadPackedMessage, &nr_srs_beamforming_report->prg_size, end) &&
|
||||
pull8(&pReadPackedMessage, &nr_srs_beamforming_report->num_symbols, end) &&
|
||||
pull8(&pReadPackedMessage, &nr_srs_beamforming_report->wide_band_snr, end) &&
|
||||
pull8(&pReadPackedMessage, &nr_srs_beamforming_report->num_reported_symbols, end))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!nr_srs_beamforming_report->prgs) {
|
||||
nr_srs_beamforming_report->prgs = (nfapi_nr_srs_reported_symbol_t*) calloc(1, sizeof(nfapi_nr_srs_reported_symbol_t));
|
||||
}
|
||||
|
||||
if(!unpack_nr_srs_reported_symbol(nr_srs_beamforming_report->prgs, &pReadPackedMessage, end)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t unpack_nr_srs_report_tlv(nfapi_srs_report_tlv_t *report_tlv, uint8_t **ppReadPackedMsg, uint8_t *end) {
|
||||
|
||||
if(!(pull16(ppReadPackedMsg, &report_tlv->tag, end) &&
|
||||
pull32(ppReadPackedMsg, &report_tlv->length, end))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(int i = 0; i < report_tlv->length; i++) {
|
||||
if (!pull32(ppReadPackedMsg, &report_tlv->value[i], end)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t unpack_nr_srs_indication_body(nfapi_nr_srs_indication_pdu_t *value, uint8_t **ppReadPackedMsg, uint8_t *end) {
|
||||
|
||||
if(!(pull32(ppReadPackedMsg, &value->handle, end) &&
|
||||
pull16(ppReadPackedMsg, &value->rnti, end) &&
|
||||
pull16(ppReadPackedMsg, &value->timing_advance_offset, end) &&
|
||||
pulls16(ppReadPackedMsg, &value->timing_advance_offset_nsec, end) &&
|
||||
pull8(ppReadPackedMsg, &value->srs_usage, end) &&
|
||||
pull8(ppReadPackedMsg, &value->report_type, end))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!unpack_nr_srs_report_tlv(value->report_tlv, ppReadPackedMsg, end)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_srs_indication_t *pNfapiMsg, nfapi_p7_codec_config_t* config) {
|
||||
|
||||
if (!(pull16(ppReadPackedMsg,&pNfapiMsg->sfn, end) &&
|
||||
pull16(ppReadPackedMsg,&pNfapiMsg->slot, end) &&
|
||||
pull16(ppReadPackedMsg,&pNfapiMsg->control_length, end) &&
|
||||
pull8(ppReadPackedMsg,&pNfapiMsg->number_of_pdus, end))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(int i=0; i<pNfapiMsg->number_of_pdus; i++) {
|
||||
if (!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//NR RACH
|
||||
|
||||
@@ -89,7 +89,7 @@ __attribute__((always_inline)) inline c16_t c32x16cumulVectVectWithSteps(c16_t *
|
||||
|
||||
int localOffset1=*offset1;
|
||||
int localOffset2=*offset2;
|
||||
c32_t cumul={0};
|
||||
c32_t cumul={0};
|
||||
for (int i=0; i<N; i++) {
|
||||
cumul=c32x16maddShift(in1[localOffset1], in2[localOffset2], cumul, 15);
|
||||
localOffset1+=step1;
|
||||
@@ -202,14 +202,14 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
//------------------------------------------------//
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
|
||||
|
||||
for (int i = 0; i < (6 * nb_rb_pusch); i++) {
|
||||
LOG_I(PHY, "In %s: %d + j*(%d)\n", __FUNCTION__, pilot[i].r,pilot[i].i);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
const uint8_t b_shift = pusch_pdu->nrOfLayers == 1;
|
||||
|
||||
|
||||
for (int aarx=0; aarx<gNB->frame_parms.nb_antennas_rx; aarx++) {
|
||||
c16_t *rxdataF = (c16_t *)&gNB->common_vars.rxdataF[aarx][symbol_offset];
|
||||
c16_t *ul_ch = &ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset];
|
||||
@@ -221,20 +221,20 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
LOG_I(PHY, "In %s bwp_start_subcarrier %d, k0 %d, first_carrier %d, nb_rb_pusch %d\n", __FUNCTION__, bwp_start_subcarrier, k0, gNB->frame_parms.first_carrier_offset, nb_rb_pusch);
|
||||
LOG_I(PHY, "In %s ul_ch addr %p nushift %d\n", __FUNCTION__, ul_ch, nushift);
|
||||
#endif
|
||||
|
||||
|
||||
if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && chest_freq == 0) {
|
||||
c16_t *pil = pilot;
|
||||
c16_t *pil = pilot;
|
||||
int re_offset = k0;
|
||||
LOG_D(PHY,"PUSCH estimation DMRS type 1, Freq-domain interpolation");
|
||||
// For configuration type 1: k = 4*n + 2*k' + delta,
|
||||
// where k' is 0 or 1, and delta is in Table 6.4.1.1.3-1 from TS 38.211
|
||||
int pilot_cnt = 0;
|
||||
int delta = nr_pusch_dmrs_delta(pusch_dmrs_type1, p);
|
||||
|
||||
|
||||
for (int n = 0; n < 3*nb_rb_pusch; n++) {
|
||||
// LS estimation
|
||||
c32_t ch = {0};
|
||||
|
||||
|
||||
for (int k_line = 0; k_line <= 1; k_line++) {
|
||||
re_offset = (k0 + (n << 2) + (k_line << 1) + delta) % symbolSize;
|
||||
ch=c32x16maddShift(*pil,
|
||||
@@ -243,9 +243,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
15+b_shift);
|
||||
pil++;
|
||||
}
|
||||
|
||||
|
||||
c16_t ch16= {.r=(int16_t)ch.r, .i=(int16_t)ch.i};
|
||||
|
||||
|
||||
// Channel interpolation
|
||||
for (int k_line = 0; k_line <= 1; k_line++) {
|
||||
#ifdef DEBUG_PUSCH
|
||||
@@ -254,7 +254,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
printf("pilot %4u: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d)\n",
|
||||
pilot_cnt, pil->r, pil->i, rxF->r, rxF->i, ch.r, ch.i);
|
||||
#endif
|
||||
|
||||
|
||||
if (pilot_cnt == 0) {
|
||||
c16multaddVectRealComplex(fl, &ch16, ul_ch, 8);
|
||||
} else if (pilot_cnt == 1) {
|
||||
@@ -270,7 +270,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
} else {
|
||||
c16multaddVectRealComplex(fm, &ch16, ul_ch, 8);
|
||||
}
|
||||
|
||||
|
||||
pilot_cnt++;
|
||||
}
|
||||
}
|
||||
@@ -365,7 +365,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
ch_offset++;
|
||||
re_offset = (re_offset + 1)%symbolSize;
|
||||
}
|
||||
|
||||
|
||||
// Treat last pilot specially (right edge)
|
||||
c16_t ch_l=c16mulShift(*pil,
|
||||
rxdataF[soffset+nushift+re_offset],
|
||||
@@ -381,7 +381,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
ul_ch);
|
||||
__m128i *ul_ch_128 = (__m128i *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset];
|
||||
ul_ch_128[0] = _mm_slli_epi16 (ul_ch_128[0], 2);
|
||||
}
|
||||
}
|
||||
|
||||
else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB
|
||||
LOG_D(PHY,"PUSCH estimation DMRS type 1, no Freq-domain interpolation\n");
|
||||
@@ -389,7 +389,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
int pil_offset = 0;
|
||||
int re_offset = k0;
|
||||
c16_t ch;
|
||||
|
||||
|
||||
// First PRB
|
||||
ch=c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6);
|
||||
|
||||
@@ -428,20 +428,20 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
}
|
||||
// Last PRB
|
||||
ch=c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6);
|
||||
|
||||
|
||||
#if NO_INTERP
|
||||
for (c16_t *end=ul_ch+12; ul_ch<end; ul_ch++)
|
||||
*ul_ch=ch;
|
||||
#else
|
||||
ul_ch[3].r += (ch.r * 1365)>>15; // 1/12*16384
|
||||
ul_ch[3].i += (ch.i * 1365)>>15; // 1/12*16384
|
||||
|
||||
|
||||
ul_ch += 4;
|
||||
c16multaddVectRealComplex(filt8_avlip3,
|
||||
ch,
|
||||
ul_ch,
|
||||
8);
|
||||
|
||||
|
||||
ul_ch += 8;
|
||||
c16multaddVectRealComplex(filt8_avlip6,
|
||||
ch,
|
||||
@@ -529,19 +529,19 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
ch0=c32x16mulShift(*pil, rxdataF[nushift+re_offset], 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
|
||||
|
||||
ch=c16x32div(ch0, 4);
|
||||
#if NO_INTERP
|
||||
for (c16_t *end=ul_ch+12; ul_ch<end; ul_ch++)
|
||||
@@ -554,7 +554,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
c16multaddVectRealComplex(filt8_avlip6, &ch, ul_ch, 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
ul_ch = &ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset];
|
||||
|
||||
@@ -727,13 +727,9 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
|
||||
const nr_srs_info_t *nr_srs_info,
|
||||
const int32_t **srs_generated_signal,
|
||||
int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)],
|
||||
int32_t srs_ls_estimated_channel[][1<<srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)],
|
||||
int32_t srs_estimated_channel_freq[][1<<srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)],
|
||||
int32_t srs_estimated_channel_time[][1<<srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size],
|
||||
int32_t srs_estimated_channel_time_shifted[][1<<srs_pdu->num_ant_ports][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) {
|
||||
|
||||
@@ -753,11 +749,12 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
|
||||
fd_cdm = 2;
|
||||
}
|
||||
|
||||
c16_t srs_ls_estimated_channel[frame_parms->ofdm_symbol_size*(1<<srs_pdu->num_symbols)];
|
||||
uint32_t noise_power_per_rb[srs_pdu->bwp_size];
|
||||
int16_t ch_real[frame_parms->nb_antennas_rx*N_ap*M_sc_b_SRS];
|
||||
int16_t ch_imag[frame_parms->nb_antennas_rx*N_ap*M_sc_b_SRS];
|
||||
int16_t noise_real[frame_parms->nb_antennas_rx*N_ap*M_sc_b_SRS];
|
||||
int16_t noise_imag[frame_parms->nb_antennas_rx*N_ap*M_sc_b_SRS];
|
||||
|
||||
int16_t ls_estimated[2];
|
||||
|
||||
uint8_t mem_offset = ((16 - ((long)&srs_estimated_channel_freq[0][0][subcarrier_offset + nr_srs_info->k_0_p[0][0]])) & 0xF) >> 2; // >> 2 <=> /sizeof(int32_t)
|
||||
@@ -772,7 +769,7 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
|
||||
|
||||
for (int p_index = 0; p_index < N_ap; p_index++) {
|
||||
|
||||
memset(srs_ls_estimated_channel[ant][p_index], 0, frame_parms->ofdm_symbol_size*(1<<srs_pdu->num_symbols)*sizeof(int32_t));
|
||||
memset(srs_ls_estimated_channel, 0, frame_parms->ofdm_symbol_size*(1<<srs_pdu->num_symbols)*sizeof(c16_t));
|
||||
memset(srs_est, 0, (frame_parms->ofdm_symbol_size*(1<<srs_pdu->num_symbols) + mem_offset)*sizeof(int32_t));
|
||||
|
||||
#ifdef SRS_DEBUG
|
||||
@@ -815,7 +812,8 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
|
||||
}
|
||||
}
|
||||
|
||||
srs_ls_estimated_channel[ant][p_index][subcarrier] = ls_estimated[0] + (((int32_t)ls_estimated[1] << 16) & 0xFFFF0000);
|
||||
srs_ls_estimated_channel[subcarrier].r = ls_estimated[0];
|
||||
srs_ls_estimated_channel[subcarrier].i = ls_estimated[1];
|
||||
|
||||
#ifdef SRS_DEBUG
|
||||
int subcarrier_log = subcarrier-subcarrier_offset;
|
||||
@@ -828,8 +826,8 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
|
||||
}
|
||||
LOG_I(NR_PHY,"(%4i) %6i\t%6i | %6i\t%6i | %6i\t%6i\n",
|
||||
subcarrier_log,
|
||||
(int16_t)(srs_generated_signal[p_index][subcarrier] & 0xFFFF), (int16_t)((srs_generated_signal[p_index][subcarrier] >> 16) & 0xFFFF),
|
||||
(int16_t)(srs_received_signal[ant][subcarrier] & 0xFFFF), (int16_t)((srs_received_signal[ant][subcarrier] >> 16) & 0xFFFF),
|
||||
((c16_t*)srs_generated_signal[p_index])[subcarrier].r, ((c16_t*)srs_generated_signal[p_index])[subcarrier].i,
|
||||
((c16_t*)srs_received_signal[ant])[subcarrier].r, ((c16_t*)srs_received_signal[ant])[subcarrier].i,
|
||||
ls_estimated[0], ls_estimated[1]);
|
||||
#endif
|
||||
|
||||
@@ -896,8 +894,8 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
|
||||
for (int k = 0; k < M_sc_b_SRS; k++) {
|
||||
ch_real[base_idx+k] = ((c16_t*)srs_estimated_channel_freq[ant][p_index])[subcarrier].r;
|
||||
ch_imag[base_idx+k] = ((c16_t*)srs_estimated_channel_freq[ant][p_index])[subcarrier].i;
|
||||
noise_real[base_idx+k] = abs(((c16_t*)srs_ls_estimated_channel[ant][p_index])[subcarrier].r - ch_real[base_idx+k]);
|
||||
noise_imag[base_idx+k] = abs(((c16_t*)srs_ls_estimated_channel[ant][p_index])[subcarrier].i - ch_imag[base_idx+k]);
|
||||
noise_real[base_idx+k] = abs(srs_ls_estimated_channel[subcarrier].r - ch_real[base_idx+k]);
|
||||
noise_imag[base_idx+k] = abs(srs_ls_estimated_channel[subcarrier].i - ch_imag[base_idx+k]);
|
||||
subcarrier += K_TC;
|
||||
if (subcarrier >= frame_parms->ofdm_symbol_size) {
|
||||
subcarrier=subcarrier-frame_parms->ofdm_symbol_size;
|
||||
@@ -924,10 +922,10 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
|
||||
|
||||
LOG_I(NR_PHY,"(%4i) %6i\t%6i | %6i\t%6i | %6i\t%6i\n",
|
||||
subcarrier_log,
|
||||
(int16_t)(srs_ls_estimated_channel[ant][p_index][subcarrier]&0xFFFF),
|
||||
(int16_t)((srs_ls_estimated_channel[ant][p_index][subcarrier]>>16)&0xFFFF),
|
||||
(int16_t)(srs_estimated_channel_freq[ant][p_index][subcarrier]&0xFFFF),
|
||||
(int16_t)((srs_estimated_channel_freq[ant][p_index][subcarrier]>>16)&0xFFFF),
|
||||
srs_ls_estimated_channel[subcarrier].r,
|
||||
srs_ls_estimated_channel[subcarrier].i,
|
||||
((c16_t*)srs_estimated_channel_freq[ant][p_index])[subcarrier].r,
|
||||
((c16_t*)srs_estimated_channel_freq[ant][p_index])[subcarrier].i,
|
||||
noise_real[base_idx+(k/K_TC)], noise_imag[base_idx+(k/K_TC)]);
|
||||
|
||||
// Subcarrier increment
|
||||
@@ -955,21 +953,21 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
|
||||
} // for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++)
|
||||
|
||||
// Compute signal power
|
||||
*signal_power = calc_power(ch_real,frame_parms->nb_antennas_rx*N_ap*M_sc_b_SRS)
|
||||
+ calc_power(ch_imag,frame_parms->nb_antennas_rx*N_ap*M_sc_b_SRS);
|
||||
uint32_t signal_power = calc_power(ch_real,frame_parms->nb_antennas_rx*N_ap*M_sc_b_SRS)
|
||||
+ calc_power(ch_imag,frame_parms->nb_antennas_rx*N_ap*M_sc_b_SRS);
|
||||
|
||||
#ifdef SRS_DEBUG
|
||||
LOG_I(NR_PHY,"signal_power = %u\n", *signal_power);
|
||||
LOG_I(NR_PHY,"signal_power = %u\n", signal_power);
|
||||
#endif
|
||||
|
||||
if (*signal_power == 0) {
|
||||
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 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);
|
||||
|
||||
@@ -1001,7 +999,7 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
|
||||
|
||||
noise_power_per_rb[rb] = max(sum_re2 / n_noise_est - (sum_re / n_noise_est) * (sum_re / n_noise_est) +
|
||||
sum_im2 / n_noise_est - (sum_im / n_noise_est) * (sum_im / n_noise_est), 1);
|
||||
snr_per_rb[rb] = dB_fixed((int32_t)((*signal_power<<factor_bits)/noise_power_per_rb[rb])) - factor_dB;
|
||||
snr_per_rb[rb] = dB_fixed((int32_t)((signal_power<<factor_bits)/noise_power_per_rb[rb])) - factor_dB;
|
||||
|
||||
#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]);
|
||||
@@ -1009,13 +1007,13 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
|
||||
|
||||
} // for (int rb = 0; rb < m_SRS_b; rb++)
|
||||
|
||||
*noise_power = max(calc_power(noise_real,frame_parms->nb_antennas_rx*N_ap*M_sc_b_SRS)
|
||||
+ calc_power(noise_imag,frame_parms->nb_antennas_rx*N_ap*M_sc_b_SRS), 1);
|
||||
uint32_t noise_power = max(calc_power(noise_real,frame_parms->nb_antennas_rx*N_ap*M_sc_b_SRS)
|
||||
+ calc_power(noise_imag,frame_parms->nb_antennas_rx*N_ap*M_sc_b_SRS), 1);
|
||||
|
||||
*snr = dB_fixed((int32_t)((*signal_power<<factor_bits)/(*noise_power))) - factor_dB;
|
||||
*snr = dB_fixed((int32_t)((signal_power<<factor_bits)/(noise_power))) - factor_dB;
|
||||
|
||||
#ifdef SRS_DEBUG
|
||||
LOG_I(NR_PHY,"noise_power = %u, SNR = %i dB\n", *noise_power, *snr);
|
||||
LOG_I(NR_PHY,"noise_power = %u, SNR = %i dB\n", noise_power, *snr);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -73,13 +73,9 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
|
||||
const nr_srs_info_t *nr_srs_info,
|
||||
const int32_t **srs_generated_signal,
|
||||
int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)],
|
||||
int32_t srs_ls_estimated_channel[][1<<srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)],
|
||||
int32_t srs_estimated_channel_freq[][1<<srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size*(1<<srs_pdu->num_symbols)],
|
||||
int32_t srs_estimated_channel_time[][1<<srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size],
|
||||
int32_t srs_estimated_channel_time_shifted[][1<<srs_pdu->num_ant_ports][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
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
#define mulhi_s1_int16(a,b) vshlq_n_s16(vqdmulhq_s16(a,b),1)
|
||||
#define adds_int16(a,b) vqaddq_s16(a,b)
|
||||
#define mullo_int16(a,b) vmulq_s16(a,b)
|
||||
#define _mm_empty()
|
||||
#define _mm_empty()
|
||||
#define _m_empty()
|
||||
#endif
|
||||
|
||||
@@ -74,6 +74,11 @@ extern "C" {
|
||||
float i;
|
||||
} cf_t;
|
||||
|
||||
typedef struct complex8 {
|
||||
int8_t r;
|
||||
int8_t i;
|
||||
} c8_t;
|
||||
|
||||
typedef struct complex16 {
|
||||
int16_t r;
|
||||
int16_t i;
|
||||
@@ -98,14 +103,14 @@ extern "C" {
|
||||
.i = (int16_t)((a.r * b.i + a.i * b.r) >> Shift)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
__attribute__((always_inline)) inline c16_t c16divShift(const c16_t a, const c16_t b, const int Shift) {
|
||||
return (c16_t) {
|
||||
.r = (int16_t)((a.r * b.r + a.i * b.i) >> Shift),
|
||||
.i = (int16_t)((a.r * b.i - a.i * b.r) >> Shift)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
__attribute__((always_inline)) inline c16_t c16maddShift(const c16_t a, const c16_t b, c16_t c, const int Shift) {
|
||||
return (c16_t) {
|
||||
.r = (int16_t)(((a.r * b.r - a.i * b.i ) >> Shift) + c.r),
|
||||
@@ -136,8 +141,8 @@ extern "C" {
|
||||
|
||||
|
||||
// On N complex numbers
|
||||
// y.r += (x * alpha.r) >> 14
|
||||
// y.i += (x * alpha.i) >> 14
|
||||
// y.r += (x * alpha.r) >> 14
|
||||
// y.i += (x * alpha.i) >> 14
|
||||
// See regular C implementation at the end
|
||||
__attribute__((always_inline)) inline void c16multaddVectRealComplex(const int16_t *x,
|
||||
const c16_t *alpha,
|
||||
@@ -153,7 +158,7 @@ extern "C" {
|
||||
10,11,10+16,11+16,
|
||||
12,13,12+16,13+16,
|
||||
14,15,14+16,15+16};
|
||||
|
||||
|
||||
__m256i alpha256= _mm256_set1_epi32(*(int32_t *)alpha);
|
||||
__m128i *x128=(__m128i *)x;
|
||||
__m128i *y128=(__m128i *)y;
|
||||
@@ -169,11 +174,11 @@ extern "C" {
|
||||
*y128= _mm_adds_epi16(_mm256_extracti128_si256(x_mul_alpha_x2,1),*y128);
|
||||
y128++;
|
||||
x128++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#elif defined(__x86_64__) || defined(__i386__) || defined(__arm__)
|
||||
uint32_t i;
|
||||
|
||||
|
||||
// do 8 multiplications at a time
|
||||
simd_q15_t alpha_r_128,alpha_i_128,yr,yi,*x_128=(simd_q15_t*)x,*y_128=(simd_q15_t*)y;
|
||||
int j;
|
||||
@@ -199,7 +204,7 @@ extern "C" {
|
||||
y_128[j] = adds_int16(y_128[j],yint.val[0]);
|
||||
j++;
|
||||
y_128[j] = adds_int16(y_128[j],yint.val[1]);
|
||||
|
||||
|
||||
j++;
|
||||
#endif
|
||||
}
|
||||
@@ -260,7 +265,7 @@ __attribute__((always_inline)) inline void multadd_real_four_symbols_vector_comp
|
||||
_mm_storeu_si128((simd_q15_t*)y, y_128);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*!\fn void multadd_complex_vector_real_scalar(int16_t *x,int16_t alpha,int16_t *y,uint8_t zero_flag,uint32_t N)
|
||||
This function performs componentwise multiplication and accumulation of a real scalar and a complex vector.
|
||||
@param x Vector input (Q1.15) in the format |Re0 Im0|Re1 Im 1| ...
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
|
||||
#define NB_RX_ANTENNAS_MAX 64
|
||||
|
||||
#define TC_NSEC_x32768 16667
|
||||
|
||||
typedef enum {TDD=1,FDD=0} frame_type_t;
|
||||
|
||||
|
||||
@@ -584,27 +584,77 @@ void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
|
||||
|
||||
}
|
||||
|
||||
int fill_srs_reported_symbol_list(nfapi_nr_srs_indication_reported_symbol_t *reported_symbol_list,
|
||||
int fill_srs_reported_symbol_list(nfapi_nr_srs_reported_symbol_t *prgs,
|
||||
const nfapi_nr_srs_pdu_t *srs_pdu,
|
||||
const int N_RB_UL,
|
||||
const int8_t *snr_per_rb,
|
||||
const int srs_est) {
|
||||
|
||||
reported_symbol_list->num_rbs = srs_bandwidth_config[srs_pdu->config_index][srs_pdu->bandwidth_index][0];
|
||||
prgs->num_prgs = srs_pdu->beamforming.num_prgs;
|
||||
|
||||
if (!reported_symbol_list->rb_list) {
|
||||
reported_symbol_list->rb_list = (nfapi_nr_srs_indication_reported_symbol_resource_block_t*) calloc(1, N_RB_UL*sizeof(nfapi_nr_srs_indication_reported_symbol_resource_block_t));
|
||||
if (!prgs->prg_list) {
|
||||
prgs->prg_list = (nfapi_nr_srs_reported_symbol_prgs_t*) calloc(1, N_RB_UL*sizeof(nfapi_nr_srs_reported_symbol_prgs_t));
|
||||
}
|
||||
|
||||
for(int rb = 0; rb < reported_symbol_list->num_rbs; rb++) {
|
||||
for(int prg_idx = 0; prg_idx < prgs->num_prgs; prg_idx++) {
|
||||
if (srs_est<0) {
|
||||
reported_symbol_list->rb_list[rb].rb_snr = 0xFF;
|
||||
} else if (snr_per_rb[rb] < -64) {
|
||||
reported_symbol_list->rb_list[rb].rb_snr = 0;
|
||||
} else if (snr_per_rb[rb] > 63) {
|
||||
reported_symbol_list->rb_list[rb].rb_snr = 0xFE;
|
||||
prgs->prg_list[prg_idx].rb_snr = 0xFF;
|
||||
} else if (snr_per_rb[prg_idx] < -64) {
|
||||
prgs->prg_list[prg_idx].rb_snr = 0;
|
||||
} else if (snr_per_rb[prg_idx] > 63) {
|
||||
prgs->prg_list[prg_idx].rb_snr = 0xFE;
|
||||
} else {
|
||||
reported_symbol_list->rb_list[rb].rb_snr = (snr_per_rb[rb] + 64)<<1;
|
||||
prgs->prg_list[prg_idx].rb_snr = (snr_per_rb[prg_idx] + 64) << 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fill_srs_channel_matrix(uint8_t *channel_matrix,
|
||||
const nfapi_nr_srs_pdu_t *srs_pdu,
|
||||
const nr_srs_info_t *nr_srs_info,
|
||||
const uint8_t normalized_iq_representation,
|
||||
const uint16_t num_gnb_antenna_elements,
|
||||
const uint16_t num_ue_srs_ports,
|
||||
const uint16_t prg_size,
|
||||
const uint16_t num_prgs,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const int32_t srs_estimated_channel_freq[][1<<srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size*(1<<srs_pdu->num_symbols)]) {
|
||||
|
||||
const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*NR_NB_SC_PER_RB;
|
||||
const uint16_t step = prg_size*NR_NB_SC_PER_RB;
|
||||
|
||||
c16_t *channel_matrix16 = (c16_t*)channel_matrix;
|
||||
c8_t *channel_matrix8 = (c8_t*)channel_matrix;
|
||||
|
||||
for(int uI = 0; uI < num_ue_srs_ports; uI++) {
|
||||
for(int gI = 0; gI < num_gnb_antenna_elements; gI++) {
|
||||
|
||||
uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[uI][0];
|
||||
if (subcarrier>frame_parms->ofdm_symbol_size) {
|
||||
subcarrier -= frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
for(int pI = 0; pI < num_prgs; pI++) {
|
||||
|
||||
c16_t *srs_estimated_channel16 = (c16_t *)&srs_estimated_channel_freq[gI][uI][subcarrier];
|
||||
uint16_t index = uI*num_gnb_antenna_elements*num_prgs + gI*num_prgs + pI;
|
||||
|
||||
if (normalized_iq_representation == 0) {
|
||||
channel_matrix8[index].r = (int8_t)(srs_estimated_channel16->r>>8);
|
||||
channel_matrix8[index].i = (int8_t)(srs_estimated_channel16->i>>8);
|
||||
} else {
|
||||
channel_matrix16[index].r = srs_estimated_channel16->r;
|
||||
channel_matrix16[index].i = srs_estimated_channel16->i;
|
||||
}
|
||||
|
||||
// Subcarrier increment
|
||||
subcarrier += step;
|
||||
if (subcarrier >= frame_parms->ofdm_symbol_size) {
|
||||
subcarrier=subcarrier-frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,29 +846,24 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0;i<NUMBER_OF_NR_SRS_MAX;i++) {
|
||||
for (int i = 0; i < NUMBER_OF_NR_SRS_MAX; i++) {
|
||||
NR_gNB_SRS_t *srs = gNB->srs[i];
|
||||
if (srs) {
|
||||
if ((srs->active == 1) && (srs->frame == frame_rx) && (srs->slot == slot_rx)) {
|
||||
|
||||
LOG_D(NR_PHY, "(%d.%d) gNB is waiting for SRS, id = %i\n", frame_rx, slot_rx, i);
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu;
|
||||
uint8_t N_symb_SRS = 1<<srs_pdu->num_symbols;
|
||||
int32_t srs_received_signal[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size*N_symb_SRS];
|
||||
int32_t srs_ls_estimated_channel[frame_parms->nb_antennas_rx][1<<srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size*N_symb_SRS];
|
||||
int32_t srs_estimated_channel_freq[frame_parms->nb_antennas_rx][1<<srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size*N_symb_SRS] __attribute__ ((aligned(32)));
|
||||
int32_t srs_estimated_channel_time[frame_parms->nb_antennas_rx][1<<srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size] __attribute__ ((aligned(32)));
|
||||
int32_t srs_estimated_channel_time_shifted[frame_parms->nb_antennas_rx][1<<srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size];
|
||||
uint32_t noise_power_per_rb[srs_pdu->bwp_size];
|
||||
uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols;
|
||||
int32_t srs_received_signal[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size * N_symb_SRS];
|
||||
int32_t srs_estimated_channel_freq[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32)));
|
||||
int32_t srs_estimated_channel_time[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
int32_t srs_estimated_channel_time_shifted[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size];
|
||||
int8_t snr_per_rb[srs_pdu->bwp_size];
|
||||
uint32_t signal_power;
|
||||
uint32_t noise_power;
|
||||
int8_t snr;
|
||||
|
||||
// At least currently, the configuration is constant, so it is enough to generate the sequence just once.
|
||||
if(gNB->nr_srs_info[i]->srs_generated_signal_bits == 0) {
|
||||
if (gNB->nr_srs_info[i]->srs_generated_signal_bits == 0) {
|
||||
generate_srs_nr(srs_pdu, frame_parms, gNB->nr_srs_info[i]->srs_generated_signal, 0, gNB->nr_srs_info[i], AMP, frame_rx, slot_rx);
|
||||
}
|
||||
|
||||
@@ -830,15 +875,11 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
|
||||
slot_rx,
|
||||
srs_pdu,
|
||||
gNB->nr_srs_info[i],
|
||||
(const int32_t **) gNB->nr_srs_info[i]->srs_generated_signal,
|
||||
(const int32_t **)gNB->nr_srs_info[i]->srs_generated_signal,
|
||||
srs_received_signal,
|
||||
srs_ls_estimated_channel,
|
||||
srs_estimated_channel_freq,
|
||||
srs_estimated_channel_time,
|
||||
srs_estimated_channel_time_shifted,
|
||||
&signal_power,
|
||||
noise_power_per_rb,
|
||||
&noise_power,
|
||||
snr_per_rb,
|
||||
&snr);
|
||||
}
|
||||
@@ -870,31 +911,143 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
|
||||
nfapi_nr_srs_indication_pdu_t *srs_indication = &gNB->srs_pdu_list[gNB->UL_INFO.srs_ind.number_of_pdus];
|
||||
srs_indication->handle = srs_pdu->handle;
|
||||
srs_indication->rnti = srs_pdu->rnti;
|
||||
srs_indication->timing_advance = srs_est >= 0 ? nr_est_timing_advance_srs(frame_parms, srs_estimated_channel_time[0]) : 0xFFFF;
|
||||
srs_indication->num_symbols = 1 << srs_pdu->num_symbols;
|
||||
srs_indication->wide_band_snr = srs_est >= 0 ? (snr + 64) << 1 : 0xFF; // 0xFF will be set if this field is invalid
|
||||
srs_indication->num_reported_symbols = 1 << srs_pdu->num_symbols;
|
||||
if (!srs_indication->reported_symbol_list) {
|
||||
srs_indication->reported_symbol_list = (nfapi_nr_srs_indication_reported_symbol_t *)calloc(1, srs_indication->num_reported_symbols * sizeof(nfapi_nr_srs_indication_reported_symbol_t));
|
||||
srs_indication->timing_advance_offset = srs_est >= 0 ? nr_est_timing_advance_srs(frame_parms, srs_estimated_channel_time[0]) : 0xFFFF;
|
||||
srs_indication->timing_advance_offset_nsec = srs_est >= 0 ? (int16_t)((((int32_t)srs_indication->timing_advance_offset - 31) * ((int32_t)TC_NSEC_x32768)) >> 15) : 0xFFFF;
|
||||
switch (srs_pdu->srs_parameters_v4.usage) {
|
||||
case 0:
|
||||
LOG_W(NR_PHY, "SRS report was not requested by MAC\n");
|
||||
return 0;
|
||||
case 1 << NR_SRS_ResourceSet__usage_beamManagement:
|
||||
srs_indication->srs_usage = NR_SRS_ResourceSet__usage_beamManagement;
|
||||
break;
|
||||
case 1 << NR_SRS_ResourceSet__usage_codebook:
|
||||
srs_indication->srs_usage = NR_SRS_ResourceSet__usage_codebook;
|
||||
break;
|
||||
case 1 << NR_SRS_ResourceSet__usage_nonCodebook:
|
||||
srs_indication->srs_usage = NR_SRS_ResourceSet__usage_nonCodebook;
|
||||
break;
|
||||
case 1 << NR_SRS_ResourceSet__usage_antennaSwitching:
|
||||
srs_indication->srs_usage = NR_SRS_ResourceSet__usage_antennaSwitching;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_PHY, "Invalid srs_pdu->srs_parameters_v4.usage %i\n", srs_pdu->srs_parameters_v4.usage);
|
||||
}
|
||||
fill_srs_reported_symbol_list(&srs_indication->reported_symbol_list[0], srs_pdu, frame_parms->N_RB_UL, snr_per_rb, srs_est);
|
||||
|
||||
gNB->UL_INFO.srs_ind.number_of_pdus += 1;
|
||||
srs_indication->report_type = srs_pdu->srs_parameters_v4.report_type[0];
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_PHY, "gNB->UL_INFO.srs_ind.sfn = %i\n", gNB->UL_INFO.srs_ind.sfn);
|
||||
LOG_I(NR_PHY, "gNB->UL_INFO.srs_ind.slot = %i\n", gNB->UL_INFO.srs_ind.slot);
|
||||
LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].rnti = 0x%04x\n", num_srs, gNB->srs_pdu_list[num_srs].rnti);
|
||||
LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].timing_advance = %i\n", num_srs, gNB->srs_pdu_list[num_srs].timing_advance);
|
||||
LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].num_symbols = %i\n", num_srs, gNB->srs_pdu_list[num_srs].num_symbols);
|
||||
LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].wide_band_snr = %i\n", num_srs, gNB->srs_pdu_list[num_srs].wide_band_snr);
|
||||
LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].num_reported_symbols = %i\n", num_srs, gNB->srs_pdu_list[num_srs].num_reported_symbols);
|
||||
LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].reported_symbol_list[0].num_rbs = %i\n", num_srs, gNB->srs_pdu_list[num_srs].reported_symbol_list[0].num_rbs);
|
||||
for (int rb = 0; rb < gNB->srs_pdu_list[num_srs].reported_symbol_list[0].num_rbs; rb++) {
|
||||
LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].reported_symbol_list[0].rb_list[%3i].rb_snr = %i\n", num_srs, rb, gNB->srs_pdu_list[num_srs].reported_symbol_list[0].rb_list[rb].rb_snr);
|
||||
LOG_I(NR_PHY, "srs_indication->rnti = %04x\n", srs_indication->rnti);
|
||||
LOG_I(NR_PHY, "srs_indication->timing_advance = %i\n", srs_indication->timing_advance_offset);
|
||||
LOG_I(NR_PHY, "srs_indication->timing_advance_offset_nsec = %i\n", srs_indication->timing_advance_offset_nsec);
|
||||
LOG_I(NR_PHY, "srs_indication->srs_usage = %i\n", srs_indication->srs_usage);
|
||||
LOG_I(NR_PHY, "srs_indication->report_type = %i\n", srs_indication->report_type);
|
||||
#endif
|
||||
|
||||
if (!srs_indication->report_tlv) {
|
||||
srs_indication->report_tlv = (nfapi_srs_report_tlv_t *)calloc(1, sizeof(nfapi_srs_report_tlv_t));
|
||||
}
|
||||
srs_indication->report_tlv->tag = 0;
|
||||
srs_indication->report_tlv->length = 0;
|
||||
|
||||
switch (srs_indication->srs_usage) {
|
||||
case NR_SRS_ResourceSet__usage_beamManagement: {
|
||||
nfapi_nr_srs_beamforming_report_t nr_srs_beamforming_report;
|
||||
nr_srs_beamforming_report.prg_size = srs_pdu->beamforming.prg_size;
|
||||
nr_srs_beamforming_report.num_symbols = 1 << srs_pdu->num_symbols;
|
||||
nr_srs_beamforming_report.wide_band_snr = srs_est >= 0 ? (snr + 64) << 1 : 0xFF; // 0xFF will be set if this field is invalid
|
||||
nr_srs_beamforming_report.num_reported_symbols = 1 << srs_pdu->num_symbols;
|
||||
nr_srs_beamforming_report.prgs = (nfapi_nr_srs_reported_symbol_t *)calloc(1, nr_srs_beamforming_report.num_reported_symbols * sizeof(nfapi_nr_srs_reported_symbol_t));
|
||||
fill_srs_reported_symbol_list(&nr_srs_beamforming_report.prgs[0], srs_pdu, frame_parms->N_RB_UL, snr_per_rb, srs_est);
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_PHY, "nr_srs_beamforming_report.prg_size = %i\n", nr_srs_beamforming_report.prg_size);
|
||||
LOG_I(NR_PHY, "nr_srs_beamforming_report.num_symbols = %i\n", nr_srs_beamforming_report.num_symbols);
|
||||
LOG_I(NR_PHY, "nr_srs_beamforming_report.wide_band_snr = %i (%i dB)\n", nr_srs_beamforming_report.wide_band_snr, (nr_srs_beamforming_report.wide_band_snr >> 1) - 64);
|
||||
LOG_I(NR_PHY, "nr_srs_beamforming_report.num_reported_symbols = %i\n", nr_srs_beamforming_report.num_reported_symbols);
|
||||
LOG_I(NR_PHY, "nr_srs_beamforming_report.prgs[0].num_prgs = %i\n", nr_srs_beamforming_report.prgs[0].num_prgs);
|
||||
for (int prg_idx = 0; prg_idx < nr_srs_beamforming_report.prgs[0].num_prgs; prg_idx++) {
|
||||
LOG_I(NR_PHY,
|
||||
"nr_srs_beamforming_report.prgs[0].prg_list[%3i].rb_snr = %i (%i dB)\n",
|
||||
prg_idx,
|
||||
nr_srs_beamforming_report.prgs[0].prg_list[prg_idx].rb_snr,
|
||||
(nr_srs_beamforming_report.prgs[0].prg_list[prg_idx].rb_snr >> 1) - 64);
|
||||
}
|
||||
#endif
|
||||
|
||||
srs_indication->report_tlv->length = pack_nr_srs_beamforming_report(&nr_srs_beamforming_report, srs_indication->report_tlv->value, 16384 * sizeof(uint32_t));
|
||||
break;
|
||||
}
|
||||
|
||||
case NR_SRS_ResourceSet__usage_codebook: {
|
||||
nfapi_nr_srs_normalized_channel_iq_matrix_t nr_srs_normalized_channel_iq_matrix;
|
||||
nr_srs_normalized_channel_iq_matrix.normalized_iq_representation = srs_pdu->srs_parameters_v4.iq_representation;
|
||||
nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements = gNB->frame_parms.nb_antennas_rx;
|
||||
nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports = srs_pdu->srs_parameters_v4.num_total_ue_antennas;
|
||||
nr_srs_normalized_channel_iq_matrix.prg_size = srs_pdu->srs_parameters_v4.prg_size;
|
||||
nr_srs_normalized_channel_iq_matrix.num_prgs = srs_pdu->srs_parameters_v4.srs_bandwidth_size / srs_pdu->srs_parameters_v4.prg_size;
|
||||
fill_srs_channel_matrix(nr_srs_normalized_channel_iq_matrix.channel_matrix,
|
||||
srs_pdu,
|
||||
gNB->nr_srs_info[i],
|
||||
nr_srs_normalized_channel_iq_matrix.normalized_iq_representation,
|
||||
nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements,
|
||||
nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports,
|
||||
nr_srs_normalized_channel_iq_matrix.prg_size,
|
||||
nr_srs_normalized_channel_iq_matrix.num_prgs,
|
||||
&gNB->frame_parms,
|
||||
srs_estimated_channel_freq);
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_PHY, "nr_srs_normalized_channel_iq_matrix.normalized_iq_representation = %i\n", nr_srs_normalized_channel_iq_matrix.normalized_iq_representation);
|
||||
LOG_I(NR_PHY, "nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements = %i\n", nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements);
|
||||
LOG_I(NR_PHY, "nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports = %i\n", nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports);
|
||||
LOG_I(NR_PHY, "nr_srs_normalized_channel_iq_matrix.prg_size = %i\n", nr_srs_normalized_channel_iq_matrix.prg_size);
|
||||
LOG_I(NR_PHY, "nr_srs_normalized_channel_iq_matrix.num_prgs = %i\n", nr_srs_normalized_channel_iq_matrix.num_prgs);
|
||||
c16_t *channel_matrix16 = (c16_t *)nr_srs_normalized_channel_iq_matrix.channel_matrix;
|
||||
c8_t *channel_matrix8 = (c8_t *)nr_srs_normalized_channel_iq_matrix.channel_matrix;
|
||||
for (int uI = 0; uI < nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports; uI++) {
|
||||
for (int gI = 0; gI < nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements; gI++) {
|
||||
for (int pI = 0; pI < nr_srs_normalized_channel_iq_matrix.num_prgs; pI++) {
|
||||
uint16_t index =
|
||||
uI * nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements * nr_srs_normalized_channel_iq_matrix.num_prgs + gI * nr_srs_normalized_channel_iq_matrix.num_prgs + pI;
|
||||
LOG_I(NR_PHY,
|
||||
"(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n",
|
||||
uI,
|
||||
gI,
|
||||
pI,
|
||||
nr_srs_normalized_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].r : channel_matrix16[index].r,
|
||||
nr_srs_normalized_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].i : channel_matrix16[index].i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
srs_indication->report_tlv->length = pack_nr_srs_normalized_channel_iq_matrix(&nr_srs_normalized_channel_iq_matrix,
|
||||
srs_indication->report_tlv->value,
|
||||
16384 * sizeof(uint32_t));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case NR_SRS_ResourceSet__usage_nonCodebook:
|
||||
case NR_SRS_ResourceSet__usage_antennaSwitching:
|
||||
LOG_W(NR_PHY, "PHY procedures for this SRS usage are not implemented yet!\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1 == 0, "Invalid SRS usage\n");
|
||||
}
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_PHY, "srs_indication->report_tlv->tag = %i\n", srs_indication->report_tlv->tag);
|
||||
LOG_I(NR_PHY, "srs_indication->report_tlv->length = %i\n", srs_indication->report_tlv->length);
|
||||
char *value = (char *)srs_indication->report_tlv->value;
|
||||
for (int b = 0; b < srs_indication->report_tlv->length; b++) {
|
||||
LOG_I(NR_PHY, "value[%i] = 0x%02x\n", b, value[b] & 0xFF);
|
||||
}
|
||||
#endif
|
||||
|
||||
gNB->UL_INFO.srs_ind.number_of_pdus += 1;
|
||||
srs->active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,25 +5,73 @@ int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { re
|
||||
int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { return(0); }
|
||||
int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); }
|
||||
//int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); }
|
||||
int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); }
|
||||
int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); }
|
||||
int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); }
|
||||
int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); }
|
||||
int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); }
|
||||
int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); }
|
||||
int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); }
|
||||
int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); }
|
||||
int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); }
|
||||
int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
int32_t get_uldl_offset(int nr_bandP) { return(0); }
|
||||
NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return(NULL);}
|
||||
int pack_nr_srs_beamforming_report(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t get_uldl_offset(int nr_bandP)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
NR_IF_Module_t *NR_IF_Module_init(int Mod_id)
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
nfapi_mode_t nfapi_mod;
|
||||
nfapi_mode_t nfapi_getmode(void) {
|
||||
nfapi_mode_t nfapi_getmode(void)
|
||||
{
|
||||
return nfapi_mod;
|
||||
}
|
||||
void nfapi_setmode(nfapi_mode_t nfapi_mode) {}
|
||||
void nfapi_setmode(nfapi_mode_t nfapi_mode)
|
||||
{
|
||||
}
|
||||
|
||||
int dummy_nr_ue_dl_indication(nr_downlink_indication_t *dl_info) { return(0); }
|
||||
int dummy_nr_ue_dl_indication(nr_downlink_indication_t *dl_info)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(0); }
|
||||
void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind,
|
||||
fapi_nr_dci_indication_t *dci_ind,
|
||||
|
||||
@@ -540,5 +540,29 @@ typedef struct nr_csi_report {
|
||||
int N2;
|
||||
} nr_csi_report_t;
|
||||
|
||||
typedef enum {
|
||||
NR_SRS_SRI_0 = 0,
|
||||
NR_SRS_SRI_1,
|
||||
NR_SRS_SRI_2,
|
||||
NR_SRS_SRI_3,
|
||||
NR_SRS_SRI_0_1,
|
||||
NR_SRS_SRI_0_2,
|
||||
NR_SRS_SRI_0_3,
|
||||
NR_SRS_SRI_1_2,
|
||||
NR_SRS_SRI_1_3,
|
||||
NR_SRS_SRI_2_3,
|
||||
NR_SRS_SRI_0_1_2,
|
||||
NR_SRS_SRI_0_1_3,
|
||||
NR_SRS_SRI_0_2_3,
|
||||
NR_SRS_SRI_1_2_3,
|
||||
NR_SRS_SRI_0_1_2_3
|
||||
} nr_srs_sri_t;
|
||||
|
||||
typedef struct nr_srs_feedback {
|
||||
uint8_t sri;
|
||||
uint8_t ul_ri;
|
||||
uint8_t tpmi;
|
||||
} nr_srs_feedback_t;
|
||||
|
||||
#endif /*__LAYER2_MAC_H__ */
|
||||
|
||||
|
||||
@@ -312,6 +312,80 @@ const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[16][4]={
|
||||
{1,0,2,6} // row index 16
|
||||
};
|
||||
|
||||
// TS 38.211 - Table 6.3.1.5-1: Precoding matrix W for single-layer transmission using two antenna ports, 'n' = -1 and 'o' = -j
|
||||
const char table_38211_6_3_1_5_1[6][2][1] = {
|
||||
{{'1'}, {'0'}}, // tpmi 0
|
||||
{{'0'}, {'1'}}, // tpmi 1
|
||||
{{'1'}, {'1'}}, // tpmi 2
|
||||
{{'1'}, {'n'}}, // tpmi 3
|
||||
{{'1'}, {'j'}}, // tpmi 4
|
||||
{{'1'}, {'o'}} // tpmi 5
|
||||
};
|
||||
|
||||
// TS 38.211 - Table 6.3.1.5-2: Precoding matrix W for single-layer transmission using four antenna ports with transform precoding enabled, 'n' = -1 and 'o' = -j
|
||||
const char table_38211_6_3_1_5_2[28][4][1] = {
|
||||
{{'1'}, {'0'}, {'0'}, {'0'}}, // tpmi 0
|
||||
{{'0'}, {'1'}, {'0'}, {'0'}}, // tpmi 1
|
||||
{{'0'}, {'0'}, {'1'}, {'0'}}, // tpmi 2
|
||||
{{'0'}, {'0'}, {'0'}, {'1'}}, // tpmi 3
|
||||
{{'1'}, {'0'}, {'1'}, {'0'}}, // tpmi 4
|
||||
{{'1'}, {'0'}, {'n'}, {'0'}}, // tpmi 5
|
||||
{{'1'}, {'0'}, {'j'}, {'0'}}, // tpmi 6
|
||||
{{'1'}, {'0'}, {'o'}, {'0'}}, // tpmi 7
|
||||
{{'0'}, {'1'}, {'0'}, {'1'}}, // tpmi 8
|
||||
{{'0'}, {'1'}, {'0'}, {'n'}}, // tpmi 9
|
||||
{{'0'}, {'1'}, {'0'}, {'j'}}, // tpmi 10
|
||||
{{'0'}, {'1'}, {'0'}, {'o'}}, // tpmi 11
|
||||
{{'1'}, {'1'}, {'1'}, {'n'}}, // tpmi 12
|
||||
{{'1'}, {'1'}, {'j'}, {'j'}}, // tpmi 13
|
||||
{{'1'}, {'1'}, {'n'}, {'1'}}, // tpmi 14
|
||||
{{'1'}, {'1'}, {'o'}, {'o'}}, // tpmi 15
|
||||
{{'1'}, {'j'}, {'1'}, {'j'}}, // tpmi 16
|
||||
{{'1'}, {'j'}, {'j'}, {'1'}}, // tpmi 17
|
||||
{{'1'}, {'j'}, {'n'}, {'o'}}, // tpmi 18
|
||||
{{'1'}, {'j'}, {'o'}, {'n'}}, // tpmi 19
|
||||
{{'1'}, {'n'}, {'1'}, {'1'}}, // tpmi 20
|
||||
{{'1'}, {'n'}, {'j'}, {'o'}}, // tpmi 21
|
||||
{{'1'}, {'n'}, {'n'}, {'n'}}, // tpmi 22
|
||||
{{'1'}, {'n'}, {'o'}, {'j'}}, // tpmi 23
|
||||
{{'1'}, {'o'}, {'1'}, {'o'}}, // tpmi 24
|
||||
{{'1'}, {'o'}, {'j'}, {'n'}}, // tpmi 25
|
||||
{{'1'}, {'o'}, {'n'}, {'j'}}, // tpmi 26
|
||||
{{'1'}, {'o'}, {'o'}, {'1'}} // tpmi 27
|
||||
};
|
||||
|
||||
// TS 38.211 - Table 6.3.1.5-3: Precoding matrix W for single-layer transmission using four antenna ports with transform precoding disabled, 'n' = -1 and 'o' = -j
|
||||
const char table_38211_6_3_1_5_3[28][4][1] = {
|
||||
{{'1'}, {'0'}, {'0'}, {'0'}}, // tpmi 0
|
||||
{{'0'}, {'1'}, {'0'}, {'0'}}, // tpmi 1
|
||||
{{'0'}, {'0'}, {'1'}, {'0'}}, // tpmi 2
|
||||
{{'0'}, {'0'}, {'0'}, {'1'}}, // tpmi 3
|
||||
{{'1'}, {'0'}, {'1'}, {'0'}}, // tpmi 4
|
||||
{{'1'}, {'0'}, {'n'}, {'0'}}, // tpmi 5
|
||||
{{'1'}, {'0'}, {'j'}, {'0'}}, // tpmi 6
|
||||
{{'1'}, {'0'}, {'o'}, {'0'}}, // tpmi 7
|
||||
{{'0'}, {'1'}, {'0'}, {'1'}}, // tpmi 8
|
||||
{{'0'}, {'1'}, {'0'}, {'n'}}, // tpmi 9
|
||||
{{'0'}, {'1'}, {'0'}, {'j'}}, // tpmi 10
|
||||
{{'0'}, {'1'}, {'0'}, {'o'}}, // tpmi 11
|
||||
{{'1'}, {'1'}, {'1'}, {'1'}}, // tpmi 12
|
||||
{{'1'}, {'1'}, {'j'}, {'j'}}, // tpmi 13
|
||||
{{'1'}, {'1'}, {'n'}, {'n'}}, // tpmi 14
|
||||
{{'1'}, {'1'}, {'o'}, {'o'}}, // tpmi 15
|
||||
{{'1'}, {'j'}, {'1'}, {'j'}}, // tpmi 16
|
||||
{{'1'}, {'j'}, {'j'}, {'n'}}, // tpmi 17
|
||||
{{'1'}, {'j'}, {'n'}, {'o'}}, // tpmi 18
|
||||
{{'1'}, {'j'}, {'o'}, {'1'}}, // tpmi 19
|
||||
{{'1'}, {'n'}, {'1'}, {'n'}}, // tpmi 20
|
||||
{{'1'}, {'n'}, {'j'}, {'o'}}, // tpmi 21
|
||||
{{'1'}, {'n'}, {'n'}, {'1'}}, // tpmi 22
|
||||
{{'1'}, {'n'}, {'o'}, {'j'}}, // tpmi 23
|
||||
{{'1'}, {'o'}, {'1'}, {'o'}}, // tpmi 24
|
||||
{{'1'}, {'o'}, {'j'}, {'1'}}, // tpmi 25
|
||||
{{'1'}, {'o'}, {'n'}, {'j'}}, // tpmi 26
|
||||
{{'1'}, {'o'}, {'o'}, {'n'}} // tpmi 27
|
||||
};
|
||||
|
||||
void get_info_from_tda_tables(int default_abc,
|
||||
int tda,
|
||||
int dmrs_TypeA_Position,
|
||||
@@ -1956,6 +2030,46 @@ int32_t table_6_4_1_1_3_4_pusch_dmrs_positions_l [12][8] = {
|
||||
{0, 3072, -1, -1, 3, 1539, -1, -1}, //14 // (DMRS l' position)
|
||||
};
|
||||
|
||||
// TS 38.212
|
||||
uint16_t table_7_3_1_1_2_2_1layer[28] = {0, 1, 2, 3, 12, 13, 14, 15, 16, 17, 18, 19, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
uint16_t table_7_3_1_1_2_2_2layers[22] = {4, 5, 6, 7, 8, 9, 20, 21, 22, 23, 24, 25, 26, 27, 48, 49, 50, 51, 52, 53, 54, 55};
|
||||
uint16_t table_7_3_1_1_2_2_3layers[7] = {10, 28, 29, 56, 57, 58, 59};
|
||||
uint16_t table_7_3_1_1_2_2_4layers[5] = {11, 30, 31, 60, 61};
|
||||
uint16_t table_7_3_1_1_2_2B_1layer[16] = {0, 1, 2, 3, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 24, 25};
|
||||
uint16_t table_7_3_1_1_2_2B_2layers[14] = {4, 5, 6, 7, 8, 9, 13, 26, 27, 28, 29, 30, 31, 32};
|
||||
uint16_t table_7_3_1_1_2_2B_3layers[3] = {10, 14, 33};
|
||||
uint16_t table_7_3_1_1_2_2B_4layers[3] = {11, 34, 35};
|
||||
uint16_t table_7_3_1_1_2_2A_1layer[16] = {0, 1, 2, 3, 12, 13, 14, 15, 16, 17, 18, 19, 20, 10, 21, 22};
|
||||
uint16_t table_7_3_1_1_2_2A_2layers[14] = {4, 5, 6, 7, 8, 9, 11, 23, 24, 25, 26, 27, 28, 29};
|
||||
uint16_t table_7_3_1_1_2_3A[16] = {0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 4, 14, 15};
|
||||
uint16_t table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[6] = {0, 1, 3, 4, 5, 6};
|
||||
uint16_t table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[3] = {2, 7, 8};
|
||||
uint16_t table_7_3_1_1_2_4A_1layer[3] = {0, 1, 3};
|
||||
uint16_t table_7_3_1_1_2_28[3][15] = {
|
||||
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
uint16_t table_7_3_1_1_2_29[3][15] = {
|
||||
{0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0},
|
||||
};
|
||||
uint16_t table_7_3_1_1_2_30[3][15] = {
|
||||
{0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 6, 0, 0, 0, 0},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0},
|
||||
};
|
||||
uint16_t table_7_3_1_1_2_31[3][15] = {
|
||||
{0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 6, 0, 0, 0, 0},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
|
||||
};
|
||||
uint16_t table_7_3_1_1_2_32[3][15] = {
|
||||
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
void get_delta_arfcn(int i, uint32_t nrarfcn, uint64_t N_OFFs){
|
||||
|
||||
@@ -2599,13 +2713,18 @@ uint8_t get_pusch_nb_antenna_ports(NR_PUSCH_Config_t *pusch_Config,
|
||||
n_antenna_port = *pusch_Config->maxRank;
|
||||
}
|
||||
else {
|
||||
if(srs_config != NULL && srs_resource_indicator.nbits > 0) {
|
||||
uint8_t sri = srs_resource_indicator.nbits > 0 ? srs_resource_indicator.val : 0;
|
||||
if(srs_config != NULL) {
|
||||
for(int rs = 0; rs < srs_config->srs_ResourceSetToAddModList->list.count; rs++) {
|
||||
NR_SRS_ResourceSet_t *srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
|
||||
if(srs_resource_set->usage == NR_SRS_ResourceSet__usage_codebook) {
|
||||
NR_SRS_Resource_t *srs_resource = srs_config->srs_ResourceToAddModList->list.array[srs_resource_indicator.val];
|
||||
AssertFatal(srs_resource != NULL,"SRS resource indicated by DCI does not exist\n");
|
||||
n_antenna_port = 1<<srs_resource->nrofSRS_Ports;
|
||||
// When multiple SRS resources are configured by SRS-ResourceSet with usage set to 'codebook',
|
||||
// the UE shall expect that higher layer parameters nrofSRS-Ports in SRS-Resource in SRS-ResourceSet
|
||||
// shall be configured with the same value for all these SRS resources.
|
||||
if (srs_resource_set->usage == NR_SRS_ResourceSet__usage_codebook) {
|
||||
NR_SRS_Resource_t *srs_resource = srs_config->srs_ResourceToAddModList->list.array[sri];
|
||||
AssertFatal(srs_resource != NULL, "SRS resource indicated by DCI does not exist\n");
|
||||
n_antenna_port = 1 << srs_resource->nrofSRS_Ports;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2613,6 +2732,372 @@ uint8_t get_pusch_nb_antenna_ports(NR_PUSCH_Config_t *pusch_Config,
|
||||
return n_antenna_port;
|
||||
}
|
||||
|
||||
// #define DEBUG_SRS_RESOURCE_IND
|
||||
uint8_t compute_srs_resource_indicator(NR_PUSCH_ServingCellConfig_t *pusch_servingcellconfig,
|
||||
NR_PUSCH_Config_t *pusch_Config,
|
||||
NR_SRS_Config_t *srs_config,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
uint16_t *val)
|
||||
{
|
||||
uint8_t nbits = 0;
|
||||
|
||||
// SRI occupies a number of bits which is dependent upon the uplink transmission scheme, and it is used to determine
|
||||
// the antenna ports and uplink transmission beam to use for PUSCH transmission. In the case of codebook based
|
||||
// transmission, the SRI is used to select between SRS Resources belonging to different antenna panels
|
||||
// (kind of directional antenna). There can be up to 2 SRS Resources (2 antenna panels). In the case of non-codebook
|
||||
// based transmission, the SRI is used to select one or more SRS Resources from a set of N_SRS resources. The number
|
||||
// of SRS Resources selected corresponds to the number of layers (rank) to be transmitted.
|
||||
if (val) {
|
||||
*val = 0;
|
||||
}
|
||||
|
||||
if (srs_config && pusch_Config && pusch_Config->txConfig != NULL) {
|
||||
|
||||
if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook) {
|
||||
|
||||
#ifdef DEBUG_SRS_RESOURCE_IND
|
||||
LOG_I(NR_MAC, "*pusch_Config->txConfig = NR_PUSCH_Config__txConfig_codebook\n");
|
||||
#endif
|
||||
|
||||
// TS 38.212 - Section 7.3.1.1.2: SRS resource indicator has ceil(log2(N_SRS)) bits according to
|
||||
// Tables 7.3.1.1.2-32, 7.3.1.1.2-32A and 7.3.1.1.2-32B if the higher layer parameter txConfig = codebook,
|
||||
// where N_SRS is the number of configured SRS resources in the SRS resource set configured by higher layer
|
||||
// parameter srs-ResourceSetToAddModList, and associated with the higher layer parameter usage of value codeBook.
|
||||
int count = 0;
|
||||
for (int i=0; i<srs_config->srs_ResourceSetToAddModList->list.count; i++) {
|
||||
if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_codebook) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count>0) {
|
||||
nbits = ceil(log2(count));
|
||||
if (val && srs_feedback && nbits > 0) {
|
||||
*val = table_7_3_1_1_2_32[count-2][srs_feedback->sri];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SRS_RESOURCE_IND
|
||||
LOG_I(NR_MAC, "srs_config->srs_ResourceSetToAddModList->list.count = %i\n", srs_config->srs_ResourceSetToAddModList->list.count);
|
||||
LOG_I(NR_MAC, "count = %i\n", count);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
#ifdef DEBUG_SRS_RESOURCE_IND
|
||||
LOG_I(NR_MAC, "*pusch_Config->txConfig = NR_PUSCH_Config__txConfig_nonCodebook\n");
|
||||
#endif
|
||||
|
||||
// TS 38.212 - Section 7.3.1.1.2: SRS resource indicator has ceil(log2(sum(k = 1 until min(Lmax,N_SRS) of binomial(N_SRS,k))))
|
||||
// bits according to Tables 7.3.1.1.2-28/29/30/31 if the higher layer parameter txConfig = nonCodebook, where
|
||||
// N_SRS is the number of configured SRS resources in the SRS resource set configured by higher layer parameter
|
||||
// srs-ResourceSetToAddModList, and associated with the higher layer parameter usage of value nonCodeBook and:
|
||||
//
|
||||
// - if UE supports operation with maxMIMO-Layers and the higher layer parameter maxMIMO-Layers of
|
||||
// PUSCH-ServingCellConfig of the serving cell is configured, Lmax is given by that parameter;
|
||||
//
|
||||
// - otherwise, Lmax is given by the maximum number of layers for PUSCH supported by the UE for the serving cell
|
||||
// for non-codebook based operation.
|
||||
int Lmax = 0;
|
||||
if (pusch_servingcellconfig != NULL) {
|
||||
if (pusch_servingcellconfig->ext1->maxMIMO_Layers != NULL) {
|
||||
Lmax = *pusch_servingcellconfig->ext1->maxMIMO_Layers;
|
||||
} else {
|
||||
AssertFatal(1 == 0, "MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n");
|
||||
}
|
||||
} else {
|
||||
AssertFatal(1 == 0, "MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n");
|
||||
}
|
||||
int lmin = 0;
|
||||
int lsum = 0;
|
||||
int count = 0;
|
||||
for (int i = 0; i < srs_config->srs_ResourceSetToAddModList->list.count; i++) {
|
||||
if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_nonCodebook) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
lmin = count < Lmax ? count : Lmax;
|
||||
for (int k=1;k<=lmin;k++) {
|
||||
lsum += binomial(count,k);
|
||||
}
|
||||
if (lsum>0) {
|
||||
nbits = ceil(log2(lsum));
|
||||
if (val && srs_feedback && nbits > 0) {
|
||||
switch(Lmax) {
|
||||
case 1:
|
||||
*val = table_7_3_1_1_2_28[count-2][srs_feedback->sri];
|
||||
break;
|
||||
case 2:
|
||||
*val = table_7_3_1_1_2_29[count-2][srs_feedback->sri];
|
||||
break;
|
||||
case 3:
|
||||
*val = table_7_3_1_1_2_30[count-2][srs_feedback->sri];
|
||||
break;
|
||||
case 4:
|
||||
*val = table_7_3_1_1_2_31[count-2][srs_feedback->sri];
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC, "%s (%d) - Invalid Lmax %d\n", __FUNCTION__, __LINE__, Lmax);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SRS_RESOURCE_IND
|
||||
LOG_I(NR_MAC, "srs_config->srs_ResourceSetToAddModList->list.count = %i\n", srs_config->srs_ResourceSetToAddModList->list.count);
|
||||
LOG_I(NR_MAC, "count = %i\n", count);
|
||||
LOG_I(NR_MAC, "Lmax = %i\n", Lmax);
|
||||
LOG_I(NR_MAC, "lsum = %i\n", lsum);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nbits;
|
||||
}
|
||||
|
||||
uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config,
|
||||
NR_SRS_Config_t *srs_config,
|
||||
dci_field_t srs_resource_indicator,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
const uint8_t *nrOfLayers,
|
||||
uint16_t *val) {
|
||||
|
||||
// It is only applicable to codebook based transmission. This field occupies 0 bits for non-codebook based
|
||||
// transmission. It also occupies 0 bits for codebook based transmission using a single antenna port.
|
||||
uint8_t nbits = 0;
|
||||
if (val) {
|
||||
*val = 0;
|
||||
}
|
||||
|
||||
uint8_t pusch_antenna_ports = get_pusch_nb_antenna_ports(pusch_Config, srs_config, srs_resource_indicator);
|
||||
if ((pusch_Config && pusch_Config->txConfig != NULL && *pusch_Config->txConfig == NR_PUSCH_Config__txConfig_nonCodebook) ||
|
||||
pusch_antenna_ports == 1) {
|
||||
return nbits;
|
||||
}
|
||||
|
||||
long max_rank = *pusch_Config->maxRank;
|
||||
long *ul_FullPowerTransmission = pusch_Config->ext1 ? pusch_Config->ext1->ul_FullPowerTransmission_r16 : NULL;
|
||||
long *codebookSubset = pusch_Config->codebookSubset;
|
||||
|
||||
if (pusch_antenna_ports == 2) {
|
||||
|
||||
if (max_rank == 1) {
|
||||
// - 1 or 3 bits according to Table 7.3.1.1.2-5 for 2 antenna ports, if txConfig = codebook, ul-FullPowerTransmission
|
||||
// is not configured or configured to fullpowerMode2 or configured to fullpower, and according to whether transform
|
||||
// precoder is enabled or disabled, and the values of higher layer parameters maxRank and codebookSubset;
|
||||
// - 2 bits according to Table 7.3.1.1.2-5A for 2 antenna ports, if txConfig = codebook, ul-FullPowerTransmission =
|
||||
// fullpowerMode1, maxRank=1, and according to whether transform precoder is enabled or disabled, and the values
|
||||
// of higher layer parameter codebookSubset;
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
nbits = 2;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 2,"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
*val = srs_feedback->tpmi;
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 1;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 1,"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
*val = srs_feedback->tpmi;
|
||||
}
|
||||
} else {
|
||||
nbits = 3;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 5,"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
*val = srs_feedback->tpmi;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// - 2 or 4 bits according to Table 7.3.1.1.2-4 for 2 antenna ports, if txConfig = codebook, ul-FullPowerTransmission
|
||||
// is not configured or configured to fullpowerMode2 or configured to fullpower, and according to whether transform
|
||||
// precoder is enabled or disabled, and the values of higher layer parameters maxRank and codebookSubset;
|
||||
// - 2 bits according to Table 7.3.1.1.2-4A for 2 antenna ports, if txConfig = codebook, ul-FullPowerTransmission =
|
||||
// fullpowerMode1, transform precoder is disabled, maxRank=2, and codebookSubset=nonCoherent;
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
nbits = 2;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 2) || (*nrOfLayers==2 && srs_feedback->tpmi == 0),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
*val = *nrOfLayers==1 ? table_7_3_1_1_2_4A_1layer[srs_feedback->tpmi] : 2;
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 2;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 1) || (*nrOfLayers==2 && srs_feedback->tpmi == 0),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
*val = *nrOfLayers==1 ? srs_feedback->tpmi : 2;
|
||||
}
|
||||
} else {
|
||||
nbits = 4;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 5) || (*nrOfLayers==2 && srs_feedback->tpmi <= 2),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
*val = *nrOfLayers==1 ? table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[srs_feedback->tpmi] :
|
||||
table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[srs_feedback->tpmi];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (pusch_antenna_ports == 4) {
|
||||
|
||||
if (max_rank == 1) {
|
||||
// - 2, 4, or 5 bits according to Table 7.3.1.1.2-3 for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission
|
||||
// is not configured or configured to fullpowerMode2 or configured to fullpower, and according to whether transform
|
||||
// precoder is enabled or disabled, and the values of higher layer parameters maxRank, and codebookSubset;
|
||||
// - 3 or 4 bits according to Table 7.3.1.1.2-3A for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission =
|
||||
// fullpowerMode1, maxRank=1, and according to whether transform precoder is enabled or disabled, and the values
|
||||
// of higher layer parameter codebookSubset;
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 3;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 3 || srs_feedback->tpmi == 13, "TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
}
|
||||
} else {
|
||||
nbits = 4;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 15, "TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
}
|
||||
}
|
||||
if (val && srs_feedback) {
|
||||
*val = table_7_3_1_1_2_3A[srs_feedback->tpmi];
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 2;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 3, "TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
}
|
||||
} else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) {
|
||||
nbits = 4;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 11, "TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
}
|
||||
} else {
|
||||
nbits = 5;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 27, "TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
}
|
||||
}
|
||||
if (val && srs_feedback) {
|
||||
*val = srs_feedback->tpmi;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// - 4, 5, or 6 bits according to Table 7.3.1.1.2-2 for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission
|
||||
// is not configured or configured to fullpowerMode2 or configured to fullpower, and according to whether transform
|
||||
// precoder is enabled or disabled, and the values of higher layer parameters maxRank, and codebookSubset;
|
||||
// - 4 or 5 bits according to Table 7.3.1.1.2-2A for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission =
|
||||
// fullpowerMode1, maxRank=2, transform precoder is disabled, and according to the values of higher layer parameter
|
||||
// codebookSubset;
|
||||
// - 4 or 6 bits according to Table 7.3.1.1.2-2B for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission =
|
||||
// fullpowerMode1, maxRank=3 or 4, transform precoder is disabled, and according to the values of higher layer
|
||||
// parameter codebookSubset;
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
if (max_rank == 2) {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 4;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && (srs_feedback->tpmi <= 3 || srs_feedback->tpmi==13)) || (*nrOfLayers==2 && srs_feedback->tpmi <= 6),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
}
|
||||
} else {
|
||||
nbits = 5;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 15) || (*nrOfLayers==2 && srs_feedback->tpmi <= 13),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
}
|
||||
}
|
||||
if (val && srs_feedback) {
|
||||
*val = *nrOfLayers==1 ? table_7_3_1_1_2_2A_1layer[srs_feedback->tpmi] : table_7_3_1_1_2_2A_2layers[srs_feedback->tpmi];
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 4;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && (srs_feedback->tpmi <= 3 || srs_feedback->tpmi == 13)) || (*nrOfLayers==2 && srs_feedback->tpmi <= 6) ||
|
||||
(*nrOfLayers==3 && srs_feedback->tpmi <= 1) || (*nrOfLayers==4 && srs_feedback->tpmi == 0),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
}
|
||||
} else {
|
||||
nbits = 6;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 15) || (*nrOfLayers==2 && srs_feedback->tpmi <= 13) ||
|
||||
(*nrOfLayers==3 && srs_feedback->tpmi <= 2) || (*nrOfLayers==4 && srs_feedback->tpmi <= 2),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
}
|
||||
}
|
||||
if (val && srs_feedback) {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
*val = table_7_3_1_1_2_2B_1layer[srs_feedback->tpmi];
|
||||
break;
|
||||
case 2:
|
||||
*val = table_7_3_1_1_2_2B_2layers[srs_feedback->tpmi];
|
||||
break;
|
||||
case 3:
|
||||
*val = table_7_3_1_1_2_2B_3layers[srs_feedback->tpmi];
|
||||
break;
|
||||
case 4:
|
||||
*val = table_7_3_1_1_2_2B_4layers[srs_feedback->tpmi];
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 4;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 3) || (*nrOfLayers==2 && srs_feedback->tpmi <= 5) ||
|
||||
(*nrOfLayers==3 && srs_feedback->tpmi == 0) || (*nrOfLayers==4 && srs_feedback->tpmi == 0),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
}
|
||||
} else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) {
|
||||
nbits = 5;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 11) || (*nrOfLayers==2 && srs_feedback->tpmi <= 13) ||
|
||||
(*nrOfLayers==3 && srs_feedback->tpmi <= 2) || (*nrOfLayers==4 && srs_feedback->tpmi <= 2),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
}
|
||||
} else {
|
||||
nbits = 6;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 28) || (*nrOfLayers==2 && srs_feedback->tpmi <= 22) ||
|
||||
(*nrOfLayers==3 && srs_feedback->tpmi <= 7) || (*nrOfLayers==4 && srs_feedback->tpmi <= 5),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
}
|
||||
}
|
||||
if (val && srs_feedback) {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
*val = table_7_3_1_1_2_2_1layer[srs_feedback->tpmi];
|
||||
break;
|
||||
case 2:
|
||||
*val = table_7_3_1_1_2_2_2layers[srs_feedback->tpmi];
|
||||
break;
|
||||
case 3:
|
||||
*val = table_7_3_1_1_2_2_3layers[srs_feedback->tpmi];
|
||||
break;
|
||||
case 4:
|
||||
*val = table_7_3_1_1_2_2_4layers[srs_feedback->tpmi];
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nbits;
|
||||
}
|
||||
|
||||
uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDownlinkBWP,
|
||||
const NR_BWP_UplinkCommon_t *initialUplinkBWP,
|
||||
const NR_CellGroupConfig_t *cg,
|
||||
@@ -2629,6 +3114,11 @@ uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDownlinkBWP,
|
||||
long rbg_size_config;
|
||||
int num_entries = 0;
|
||||
|
||||
NR_UplinkConfig_t *uplinkConfig = NULL;
|
||||
if (cg && cg->spCellConfig && cg->spCellConfig->spCellConfigDedicated) {
|
||||
uplinkConfig = cg->spCellConfig->spCellConfigDedicated->uplinkConfig;
|
||||
}
|
||||
|
||||
const NR_BWP_DownlinkDedicated_t *bwpd = NULL;
|
||||
const NR_BWP_UplinkDedicated_t *ubwpd = NULL;
|
||||
const NR_BWP_DownlinkCommon_t *bwpc = NULL;
|
||||
@@ -2640,23 +3130,21 @@ uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDownlinkBWP,
|
||||
NR_SRS_Config_t *srs_config = NULL;
|
||||
if(bwp_id > 0) {
|
||||
AssertFatal(cg!=NULL,"Cellgroup is null and bwp_id!=0");
|
||||
bwpd=cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated;
|
||||
bwpc=cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Common;
|
||||
ubwpd=cg->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated;
|
||||
ubwpc=cg->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Common;
|
||||
bwpd = cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated;
|
||||
bwpc = cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Common;
|
||||
ubwpd = uplinkConfig ? uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated : NULL;
|
||||
ubwpc = uplinkConfig ? uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Common : NULL;
|
||||
pdsch_Config = (bwpd->pdsch_Config) ? bwpd->pdsch_Config->choice.setup : NULL;
|
||||
pdcch_Config = (bwpd->pdcch_Config) ? bwpd->pdcch_Config->choice.setup : NULL;
|
||||
pucch_Config = (ubwpd->pucch_Config) ? ubwpd->pucch_Config->choice.setup : NULL;
|
||||
pusch_Config = (ubwpd->pusch_Config) ? ubwpd->pusch_Config->choice.setup : NULL;
|
||||
srs_config = (ubwpd->srs_Config) ? ubwpd->srs_Config->choice.setup : NULL;
|
||||
}
|
||||
else if (cg){
|
||||
} else if (cg) {
|
||||
bwpc = initialDownlinkBWP;
|
||||
ubwpc = initialUplinkBWP;
|
||||
bwpd = cg->spCellConfig && cg->spCellConfig->spCellConfigDedicated ?
|
||||
cg->spCellConfig->spCellConfigDedicated->initialDownlinkBWP : NULL;
|
||||
ubwpd = cg->spCellConfig && cg->spCellConfig->spCellConfigDedicated && cg->spCellConfig->spCellConfigDedicated->uplinkConfig ?
|
||||
cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP : NULL;
|
||||
ubwpd = uplinkConfig ? uplinkConfig->initialUplinkBWP : NULL;
|
||||
pdsch_Config = (bwpd && bwpd->pdsch_Config) ? bwpd->pdsch_Config->choice.setup : NULL;
|
||||
pdcch_Config = (bwpd && bwpd->pdcch_Config) ? bwpd->pdcch_Config->choice.setup : NULL;
|
||||
pucch_Config = (ubwpd && ubwpd->pucch_Config) ? ubwpd->pucch_Config->choice.setup : NULL;
|
||||
@@ -2739,101 +3227,35 @@ uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDownlinkBWP,
|
||||
size += 1;
|
||||
}
|
||||
// 1st DAI
|
||||
if (cg->physicalCellGroupConfig &&
|
||||
cg->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook==NR_PhysicalCellGroupConfig__pdsch_HARQ_ACK_Codebook_dynamic)
|
||||
if (cg->physicalCellGroupConfig && cg->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook == NR_PhysicalCellGroupConfig__pdsch_HARQ_ACK_Codebook_dynamic)
|
||||
dci_pdu->dai[0].nbits = 2;
|
||||
else
|
||||
dci_pdu->dai[0].nbits = 1;
|
||||
size += dci_pdu->dai[0].nbits;
|
||||
LOG_D(NR_MAC,"DAI1 nbits %d\n",dci_pdu->dai[0].nbits);
|
||||
LOG_D(NR_MAC, "DAI1 nbits %d\n", dci_pdu->dai[0].nbits);
|
||||
// 2nd DAI
|
||||
if (cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig &&
|
||||
cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup &&
|
||||
cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { //TODO not sure about that
|
||||
if (cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig && cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup
|
||||
&& cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { // TODO not sure about that
|
||||
dci_pdu->dai[1].nbits = 2;
|
||||
size += dci_pdu->dai[1].nbits;
|
||||
}
|
||||
// SRS resource indicator
|
||||
if (srs_config &&
|
||||
pusch_Config &&
|
||||
pusch_Config->txConfig != NULL){
|
||||
int count=0;
|
||||
if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook){
|
||||
for (int i=0; i<srs_config->srs_ResourceSetToAddModList->list.count; i++) {
|
||||
if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_codebook)
|
||||
count++;
|
||||
}
|
||||
if (count>1) {
|
||||
dci_pdu->srs_resource_indicator.nbits = 1;
|
||||
size += dci_pdu->srs_resource_indicator.nbits;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int lmin,Lmax = 0;
|
||||
int lsum = 0;
|
||||
if ( cg->spCellConfig->spCellConfigDedicated->uplinkConfig &&
|
||||
cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig != NULL) {
|
||||
if ( cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers != NULL)
|
||||
Lmax = *cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers;
|
||||
else
|
||||
AssertFatal(1==0,"MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n");
|
||||
}
|
||||
else
|
||||
AssertFatal(1==0,"MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n");
|
||||
for (int i=0; i<srs_config->srs_ResourceSetToAddModList->list.count; i++) {
|
||||
if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_nonCodebook)
|
||||
count++;
|
||||
if (count < Lmax) lmin = count;
|
||||
else lmin = Lmax;
|
||||
for (int k=1;k<=lmin;k++) {
|
||||
lsum += binomial(count,k);
|
||||
}
|
||||
}
|
||||
dci_pdu->srs_resource_indicator.nbits = (int)ceil(log2(lsum));
|
||||
size += dci_pdu->srs_resource_indicator.nbits;
|
||||
}
|
||||
} else dci_pdu->srs_resource_indicator.nbits = 0;
|
||||
LOG_D(NR_MAC,"dci_pdu->srs_resource_indicator.nbits %d\n",dci_pdu->srs_resource_indicator.nbits);
|
||||
NR_PUSCH_ServingCellConfig_t *pusch_servingcellconfig = uplinkConfig && uplinkConfig->pusch_ServingCellConfig ? uplinkConfig->pusch_ServingCellConfig->choice.setup : NULL;
|
||||
dci_pdu->srs_resource_indicator.nbits = compute_srs_resource_indicator(pusch_servingcellconfig, pusch_Config, srs_config, NULL, NULL);
|
||||
size += dci_pdu->srs_resource_indicator.nbits;
|
||||
LOG_D(NR_MAC, "dci_pdu->srs_resource_indicator.nbits %d\n", dci_pdu->srs_resource_indicator.nbits);
|
||||
// Precoding info and number of layers
|
||||
long transformPrecoder = get_transformPrecoding(initialUplinkBWP, pusch_Config, ubwpd, (uint8_t*)&format, rnti_type, 0);
|
||||
|
||||
uint8_t pusch_antenna_ports = get_pusch_nb_antenna_ports(pusch_Config, srs_config, dci_pdu->srs_resource_indicator);
|
||||
|
||||
dci_pdu->precoding_information.nbits=0;
|
||||
if (pusch_Config &&
|
||||
pusch_Config->txConfig != NULL){
|
||||
if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook){
|
||||
if (pusch_antenna_ports > 1) {
|
||||
if (pusch_antenna_ports == 4) {
|
||||
if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && (*pusch_Config->maxRank>1))
|
||||
dci_pdu->precoding_information.nbits = 6-(*pusch_Config->codebookSubset);
|
||||
else {
|
||||
if(*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent)
|
||||
dci_pdu->precoding_information.nbits = 2;
|
||||
else
|
||||
dci_pdu->precoding_information.nbits = 5-(*pusch_Config->codebookSubset);
|
||||
}
|
||||
}
|
||||
else {
|
||||
AssertFatal(pusch_antenna_ports==2,"Not valid number of antenna ports");
|
||||
if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && (*pusch_Config->maxRank==2))
|
||||
dci_pdu->precoding_information.nbits = 4-(*pusch_Config->codebookSubset);
|
||||
else
|
||||
dci_pdu->precoding_information.nbits = 3-(*pusch_Config->codebookSubset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dci_pdu->precoding_information.nbits = compute_precoding_information(pusch_Config, srs_config, dci_pdu->srs_resource_indicator, NULL, NULL, NULL);
|
||||
size += dci_pdu->precoding_information.nbits;
|
||||
LOG_D(NR_MAC,"dci_pdu->precoding_informaiton.nbits=%d\n",dci_pdu->precoding_information.nbits);
|
||||
LOG_D(NR_MAC, "dci_pdu->precoding_informaiton.nbits=%d\n", dci_pdu->precoding_information.nbits);
|
||||
// Antenna ports
|
||||
long transformPrecoder = get_transformPrecoding(initialUplinkBWP, pusch_Config, ubwpd, (uint8_t *)&format, rnti_type, 0);
|
||||
NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = NULL;
|
||||
int xa=0;
|
||||
int xb=0;
|
||||
if(pusch_Config &&
|
||||
pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL){
|
||||
int xa = 0;
|
||||
int xb = 0;
|
||||
if (pusch_Config && pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL) {
|
||||
NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup;
|
||||
xa = ul_ant_bits(NR_DMRS_UplinkConfig,transformPrecoder);
|
||||
xa = ul_ant_bits(NR_DMRS_UplinkConfig, transformPrecoder);
|
||||
}
|
||||
if(pusch_Config &&
|
||||
pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL){
|
||||
|
||||
@@ -64,6 +64,19 @@ int is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,slo
|
||||
|
||||
int is_nr_UL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slotP, frame_type_t frame_type);
|
||||
|
||||
uint8_t compute_srs_resource_indicator(NR_PUSCH_ServingCellConfig_t *pusch_servingcellconfig,
|
||||
NR_PUSCH_Config_t *pusch_Config,
|
||||
NR_SRS_Config_t *srs_config,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
uint16_t *val);
|
||||
|
||||
uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config,
|
||||
NR_SRS_Config_t *srs_config,
|
||||
dci_field_t srs_resource_indicator,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
const uint8_t *nrOfLayers,
|
||||
uint16_t *val);
|
||||
|
||||
uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDLBWP,
|
||||
const NR_BWP_UplinkCommon_t *initialULBWP,
|
||||
const NR_CellGroupConfig_t *cg,
|
||||
|
||||
@@ -143,4 +143,7 @@ extern const float table_38213_13_12_c3[16];
|
||||
|
||||
extern const int32_t table_38213_10_1_1_c2[5];
|
||||
|
||||
extern const char table_38211_6_3_1_5_1[6][2][1];
|
||||
extern const char table_38211_6_3_1_5_2[28][4][1];
|
||||
extern const char table_38211_6_3_1_5_3[28][4][1];
|
||||
#endif //DEF_H
|
||||
|
||||
@@ -830,6 +830,7 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t
|
||||
scc,
|
||||
pusch_pdu,
|
||||
&uldci_payload,
|
||||
NULL,
|
||||
ra->Msg3_tda_id,
|
||||
ra->msg3_TPC,
|
||||
&ra->UL_BWP);
|
||||
|
||||
@@ -882,6 +882,7 @@ void config_uldci(const NR_SIB1_t *sib1,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
int time_domain_assignment,
|
||||
uint8_t tpc,
|
||||
NR_UE_UL_BWP_t *ul_bwp) {
|
||||
@@ -916,13 +917,14 @@ void config_uldci(const NR_SIB1_t *sib1,
|
||||
pusch_Config->txConfig != NULL) {
|
||||
AssertFatal(*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook,
|
||||
"Non Codebook configuration non supported\n");
|
||||
dci_pdu_rel15->srs_resource_indicator.val = 0; // taking resource 0 for SRS
|
||||
compute_srs_resource_indicator(ul_bwp->pusch_servingcellconfig, pusch_Config, ul_bwp->srs_Config, srs_feedback, &dci_pdu_rel15->srs_resource_indicator.val);
|
||||
}
|
||||
dci_pdu_rel15->precoding_information.val= 0;
|
||||
if (pusch_pdu->nrOfLayers == 2)
|
||||
dci_pdu_rel15->precoding_information.val = 4;
|
||||
else if (pusch_pdu->nrOfLayers == 4)
|
||||
dci_pdu_rel15->precoding_information.val = 11;
|
||||
compute_precoding_information(pusch_Config,
|
||||
ul_bwp->srs_Config,
|
||||
dci_pdu_rel15->srs_resource_indicator,
|
||||
srs_feedback,
|
||||
&pusch_pdu->nrOfLayers,
|
||||
&dci_pdu_rel15->precoding_information.val);
|
||||
|
||||
// antenna_ports.val = 0 for transform precoder is disabled, dmrs-Type=1, maxLength=1, Rank=1/2/3/4
|
||||
// Antenna Ports
|
||||
@@ -1018,7 +1020,7 @@ int nr_get_pucch_resource(NR_ControlResourceSet_t *coreset,
|
||||
// This function configures pucch pdu fapi structure
|
||||
void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
NR_UE_info_t* UE,
|
||||
NR_UE_info_t *UE,
|
||||
uint8_t pucch_resource,
|
||||
uint16_t O_csi,
|
||||
uint16_t O_ack,
|
||||
@@ -2456,6 +2458,12 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
||||
false);
|
||||
}
|
||||
|
||||
void reset_srs_stats(NR_UE_info_t *UE) {
|
||||
if (UE) {
|
||||
UE->mac_stats.srs_stats[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup)
|
||||
{
|
||||
@@ -2522,6 +2530,8 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf
|
||||
create_nr_list(&sched_ctrl->feedback_ul_harq, 16);
|
||||
create_nr_list(&sched_ctrl->retrans_ul_harq, 16);
|
||||
|
||||
reset_srs_stats(UE);
|
||||
|
||||
pthread_mutex_lock(&UE_info->mutex);
|
||||
int i;
|
||||
for(i=0; i<MAX_MOBILES_PER_GNB; i++) {
|
||||
@@ -2929,6 +2939,8 @@ void nr_mac_update_timers(module_id_t module_id,
|
||||
if (sched_ctrl->rrc_processing_timer == 0) {
|
||||
LOG_I(NR_MAC, "(%d.%d) De-activating RRC processing timer for UE %04x\n", frame, slot, UE->rnti);
|
||||
|
||||
reset_srs_stats(UE);
|
||||
|
||||
NR_CellGroupConfig_t *cg = NULL;
|
||||
uper_decode(NULL,
|
||||
&asn_DEF_NR_CellGroupConfig, //might be added prefix later
|
||||
|
||||
@@ -35,7 +35,12 @@
|
||||
|
||||
extern RAN_CONTEXT_t RC;
|
||||
|
||||
void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int module_id, int CC_id,NR_UE_info_t* UE, NR_SRS_Resource_t *srs_resource) {
|
||||
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 };
|
||||
|
||||
void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int module_id, int CC_id,NR_UE_info_t* UE, NR_SRS_ResourceSet_t *srs_resource_set, NR_SRS_Resource_t *srs_resource) {
|
||||
|
||||
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
|
||||
|
||||
@@ -74,9 +79,22 @@ void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int module_id, int CC_id,NR_U
|
||||
srs_pdu->resource_type = srs_resource->resourceType.present - 1;
|
||||
srs_pdu->t_srs = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present];
|
||||
srs_pdu->t_offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p);
|
||||
|
||||
// TODO: This should be completed
|
||||
srs_pdu->srs_parameters_v4.srs_bandwidth_size = m_SRS[srs_pdu->config_index];
|
||||
srs_pdu->srs_parameters_v4.usage = 1<<srs_resource_set->usage;
|
||||
srs_pdu->srs_parameters_v4.report_type[0] = 1;
|
||||
srs_pdu->srs_parameters_v4.iq_representation = 1;
|
||||
srs_pdu->srs_parameters_v4.prg_size = 1;
|
||||
srs_pdu->srs_parameters_v4.num_total_ue_antennas = 1<<srs_pdu->num_ant_ports;
|
||||
if (srs_resource_set->usage == NR_SRS_ResourceSet__usage_beamManagement) {
|
||||
srs_pdu->beamforming.trp_scheme = 0;
|
||||
srs_pdu->beamforming.num_prgs = m_SRS[srs_pdu->config_index];
|
||||
srs_pdu->beamforming.prg_size = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_fill_nfapi_srs(int module_id, int CC_id, NR_UE_info_t* UE, sub_frame_t slot, NR_SRS_Resource_t *srs_resource) {
|
||||
void nr_fill_nfapi_srs(int module_id, int CC_id, NR_UE_info_t* UE, sub_frame_t slot, NR_SRS_ResourceSet_t *srs_resource_set, NR_SRS_Resource_t *srs_resource) {
|
||||
|
||||
nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_id]->UL_tti_req_ahead[0][slot];
|
||||
AssertFatal(future_ul_tti_req->n_pdus <
|
||||
@@ -88,7 +106,7 @@ void nr_fill_nfapi_srs(int module_id, int CC_id, NR_UE_info_t* UE, sub_frame_t s
|
||||
memset(srs_pdu, 0, sizeof(nfapi_nr_srs_pdu_t));
|
||||
future_ul_tti_req->n_pdus += 1;
|
||||
|
||||
nr_configure_srs(srs_pdu, module_id, CC_id, UE, srs_resource);
|
||||
nr_configure_srs(srs_pdu, module_id, CC_id, UE, srs_resource_set, srs_resource);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@@ -158,7 +176,7 @@ void nr_schedule_srs(int module_id, frame_t frame) {
|
||||
// Check if UE will transmit the SRS in this frame
|
||||
if ( ((frame - offset/n_slots_frame)*n_slots_frame)%period == 0) {
|
||||
LOG_D(NR_MAC,"Scheduling SRS reception for %d.%d\n", frame, offset%n_slots_frame);
|
||||
nr_fill_nfapi_srs(module_id, CC_id, UE, offset%n_slots_frame, srs_resource);
|
||||
nr_fill_nfapi_srs(module_id, CC_id, UE, offset%n_slots_frame, srs_resource_set, srs_resource);
|
||||
sched_ctrl->sched_srs.frame = frame;
|
||||
sched_ctrl->sched_srs.slot = offset%n_slots_frame;
|
||||
sched_ctrl->sched_srs.srs_scheduled = true;
|
||||
|
||||
@@ -786,60 +786,460 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t calc_power_complex(const int16_t *x, const int16_t *y, const uint32_t size) {
|
||||
|
||||
// Real part value
|
||||
int64_t sum_x = 0;
|
||||
int64_t sum_x2 = 0;
|
||||
for(int k = 0; k<size; k++) {
|
||||
sum_x = sum_x + x[k];
|
||||
sum_x2 = sum_x2 + x[k]*x[k];
|
||||
}
|
||||
uint32_t power_re = sum_x2/size - (sum_x/size)*(sum_x/size);
|
||||
|
||||
// Imaginary part power
|
||||
int64_t sum_y = 0;
|
||||
int64_t sum_y2 = 0;
|
||||
for(int k = 0; k<size; k++) {
|
||||
sum_y = sum_y + y[k];
|
||||
sum_y2 = sum_y2 + y[k]*y[k];
|
||||
}
|
||||
uint32_t power_im = sum_y2/size - (sum_y/size)*(sum_y/size);
|
||||
|
||||
return power_re+power_im;
|
||||
}
|
||||
|
||||
c16_t nr_h_times_w(c16_t h, char w) {
|
||||
c16_t output;
|
||||
switch (w) {
|
||||
case '0': // 0
|
||||
output.r = 0;
|
||||
output.i = 0;
|
||||
break;
|
||||
case '1': // 1
|
||||
output.r = h.r;
|
||||
output.i = h.i;
|
||||
break;
|
||||
case 'n': // -1
|
||||
output.r = -h.r;
|
||||
output.i = -h.i;
|
||||
break;
|
||||
case 'j': // j
|
||||
output.r = -h.i;
|
||||
output.i = h.r;
|
||||
break;
|
||||
case 'o': // -j
|
||||
output.r = h.i;
|
||||
output.i = -h.r;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid precoder value %c\n", w);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
uint8_t get_max_tpmi(const NR_PUSCH_Config_t *pusch_Config,
|
||||
const uint16_t num_ue_srs_ports,
|
||||
const uint8_t *nrOfLayers,
|
||||
int *additional_max_tpmi) {
|
||||
|
||||
uint8_t max_tpmi = 0;
|
||||
|
||||
if ((pusch_Config && pusch_Config->txConfig != NULL && *pusch_Config->txConfig == NR_PUSCH_Config__txConfig_nonCodebook) ||
|
||||
num_ue_srs_ports == 1) {
|
||||
return max_tpmi;
|
||||
}
|
||||
|
||||
long max_rank = *pusch_Config->maxRank;
|
||||
long *ul_FullPowerTransmission = pusch_Config->ext1 ? pusch_Config->ext1->ul_FullPowerTransmission_r16 : NULL;
|
||||
long *codebookSubset = pusch_Config->codebookSubset;
|
||||
|
||||
if (num_ue_srs_ports == 2) {
|
||||
|
||||
if (max_rank == 1) {
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
max_tpmi = 2;
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
max_tpmi = 1;
|
||||
} else {
|
||||
max_tpmi = 5;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
max_tpmi = *nrOfLayers == 1 ? 2 : 0;
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
max_tpmi = *nrOfLayers == 1 ? 1 : 0;
|
||||
} else {
|
||||
max_tpmi = *nrOfLayers == 1 ? 5 : 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (num_ue_srs_ports == 4) {
|
||||
|
||||
if (max_rank == 1) {
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
max_tpmi = 3;
|
||||
*additional_max_tpmi = 13;
|
||||
} else {
|
||||
max_tpmi = 15;
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
max_tpmi = 3;
|
||||
} else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) {
|
||||
max_tpmi = 11;
|
||||
} else {
|
||||
max_tpmi = 27;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
if (max_rank == 2) {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
max_tpmi = *nrOfLayers == 1 ? 3 : 6;
|
||||
if (*nrOfLayers == 1) {
|
||||
*additional_max_tpmi = 13;
|
||||
}
|
||||
} else {
|
||||
max_tpmi = *nrOfLayers == 1 ? 15 : 13;
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
max_tpmi = 3;
|
||||
*additional_max_tpmi = 13;
|
||||
break;
|
||||
case 2:
|
||||
max_tpmi = 6;
|
||||
break;
|
||||
case 3:
|
||||
max_tpmi = 1;
|
||||
break;
|
||||
case 4:
|
||||
max_tpmi = 0;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
}
|
||||
} else {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
max_tpmi = 15;
|
||||
break;
|
||||
case 2:
|
||||
max_tpmi = 13;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
max_tpmi = 2;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
max_tpmi = 3;
|
||||
break;
|
||||
case 2:
|
||||
max_tpmi = 5;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
max_tpmi = 0;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
}
|
||||
} else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
max_tpmi = 11;
|
||||
break;
|
||||
case 2:
|
||||
max_tpmi = 13;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
max_tpmi = 2;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
}
|
||||
} else {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
max_tpmi = 28;
|
||||
break;
|
||||
case 2:
|
||||
max_tpmi = 22;
|
||||
break;
|
||||
case 3:
|
||||
max_tpmi = 7;
|
||||
break;
|
||||
case 4:
|
||||
max_tpmi = 5;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return max_tpmi;
|
||||
}
|
||||
|
||||
void get_precoder_matrix_coef(char *w,
|
||||
const uint8_t ul_ri,
|
||||
const uint16_t num_ue_srs_ports,
|
||||
const uint8_t transform_precoding,
|
||||
const uint8_t tpmi,
|
||||
const uint8_t uI) {
|
||||
if (ul_ri == 0) {
|
||||
if (num_ue_srs_ports == 2) {
|
||||
*w = *table_38211_6_3_1_5_1[tpmi][uI];
|
||||
} else {
|
||||
if (transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled) {
|
||||
*w = *table_38211_6_3_1_5_2[tpmi][uI];
|
||||
} else {
|
||||
*w = *table_38211_6_3_1_5_3[tpmi][uI];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AssertFatal(1==0,"Function get_precoder_matrix_coef() does not support %i layers yet!\n", ul_ri+1);
|
||||
}
|
||||
}
|
||||
|
||||
int nr_srs_tpmi_estimation(const NR_PUSCH_Config_t *pusch_Config,
|
||||
const uint8_t transform_precoding,
|
||||
const uint8_t *channel_matrix,
|
||||
const uint8_t normalized_iq_representation,
|
||||
const uint16_t num_gnb_antenna_elements,
|
||||
const uint16_t num_ue_srs_ports,
|
||||
const uint16_t prg_size,
|
||||
const uint16_t num_prgs,
|
||||
const uint8_t ul_ri) {
|
||||
|
||||
uint8_t tpmi_sel = 0;
|
||||
int16_t precoded_channel_matrix_re[num_prgs*num_gnb_antenna_elements];
|
||||
int16_t precoded_channel_matrix_im[num_prgs*num_gnb_antenna_elements];
|
||||
c16_t *channel_matrix16 = (c16_t*)channel_matrix;
|
||||
uint32_t max_precoded_signal_power = 0;
|
||||
int additional_max_tpmi = -1;
|
||||
char w;
|
||||
|
||||
uint8_t max_tpmi = get_max_tpmi(pusch_Config,
|
||||
num_ue_srs_ports,
|
||||
&ul_ri,
|
||||
&additional_max_tpmi);
|
||||
|
||||
uint8_t end_tpmi_loop = additional_max_tpmi > max_tpmi ? additional_max_tpmi : max_tpmi;
|
||||
|
||||
// channel_matrix x precoder_matrix
|
||||
// [ (gI=0,uI=0) (gI=0,uI=1) ... (gI=0,uI=num_ue_srs_ports-1) ] x [uI=0]
|
||||
// [ (gI=1,uI=0) (gI=1,uI=1) ... (gI=1,uI=num_ue_srs_ports-1) ] [uI=1]
|
||||
// [ (gI=2,uI=0) (gI=2,uI=1) ... (gI=2,uI=num_ue_srs_ports-1) ] [uI=2]
|
||||
// ... ...
|
||||
|
||||
for(uint8_t tpmi = 0; tpmi<=end_tpmi_loop; tpmi++) {
|
||||
|
||||
if (tpmi > max_tpmi) {
|
||||
tpmi = end_tpmi_loop;
|
||||
}
|
||||
|
||||
for(int pI = 0; pI <num_prgs; pI++) {
|
||||
for(int gI = 0; gI < num_gnb_antenna_elements; gI++) {
|
||||
|
||||
uint16_t index_gI_pI = gI*num_prgs + pI;
|
||||
precoded_channel_matrix_re[index_gI_pI] = 0;
|
||||
precoded_channel_matrix_im[index_gI_pI] = 0;
|
||||
|
||||
for(int uI = 0; uI < num_ue_srs_ports; uI++) {
|
||||
|
||||
uint16_t index = uI*num_gnb_antenna_elements*num_prgs + index_gI_pI;
|
||||
get_precoder_matrix_coef(&w, ul_ri, num_ue_srs_ports, transform_precoding, tpmi, uI);
|
||||
c16_t h_times_w = nr_h_times_w(channel_matrix16[index], w);
|
||||
|
||||
precoded_channel_matrix_re[index_gI_pI] += h_times_w.r;
|
||||
precoded_channel_matrix_im[index_gI_pI] += h_times_w.i;
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_MAC, "(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n",
|
||||
uI, gI, pI, channel_matrix16[index].r, channel_matrix16[index].i);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_MAC, "(gI %i, pI %i) precoded_channel_coef --> real %i, imag %i\n",
|
||||
gI, pI, precoded_channel_matrix_re[index_gI_pI], precoded_channel_matrix_im[index_gI_pI]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t precoded_signal_power = calc_power_complex(precoded_channel_matrix_re,
|
||||
precoded_channel_matrix_im,
|
||||
num_prgs*num_gnb_antenna_elements);
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_MAC, "(tpmi %i) precoded_signal_power = %i\n", tpmi, precoded_signal_power);
|
||||
#endif
|
||||
|
||||
if (precoded_signal_power > max_precoded_signal_power) {
|
||||
max_precoded_signal_power = precoded_signal_power;
|
||||
tpmi_sel = tpmi;
|
||||
}
|
||||
}
|
||||
|
||||
return tpmi_sel;
|
||||
}
|
||||
|
||||
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)
|
||||
const nfapi_nr_srs_indication_pdu_t *srs_ind)
|
||||
{
|
||||
LOG_D(NR_MAC, "(%d.%d) Received SRS indication for rnti: 0x%04x\n", frame, slot, rnti);
|
||||
LOG_D(NR_MAC, "(%d.%d) Received SRS indication for UE %04x\n", frame, slot, srs_ind->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);
|
||||
}
|
||||
LOG_I(NR_MAC, "srs_ind->rnti = %04x\n", srs_ind->rnti);
|
||||
LOG_I(NR_MAC, "srs_ind->timing_advance_offset = %i\n", srs_ind->timing_advance_offset);
|
||||
LOG_I(NR_MAC, "srs_ind->timing_advance_offset_nsec = %i\n", srs_ind->timing_advance_offset_nsec);
|
||||
LOG_I(NR_MAC, "srs_ind->srs_usage = %i\n", srs_ind->srs_usage);
|
||||
LOG_I(NR_MAC, "srs_ind->report_type = %i\n", srs_ind->report_type);
|
||||
#endif
|
||||
|
||||
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, rnti);
|
||||
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, srs_ind->rnti);
|
||||
if (!UE) {
|
||||
LOG_E(NR_MAC, "Could not find UE for RNTI %04x\n", rnti);
|
||||
LOG_W(NR_MAC, "Could not find UE for RNTI %04x\n", srs_ind->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wide_band_snr == 0xFF) {
|
||||
LOG_W(NR_MAC, "Invalid wide_band_snr for RNTI %04x\n", rnti);
|
||||
if (srs_ind->timing_advance_offset == 0xFFFF) {
|
||||
LOG_W(NR_MAC, "Invalid timing advance offset for RNTI %04x\n", srs_ind->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
int wide_band_snr_dB = (wide_band_snr >> 1) - 64;
|
||||
|
||||
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_dB;
|
||||
|
||||
const int ul_prbblack_SNR_threshold = nr_mac->ul_prbblack_SNR_threshold;
|
||||
uint16_t *ulprbbl = nr_mac->ulprbbl;
|
||||
switch (srs_ind->srs_usage) {
|
||||
case NR_SRS_ResourceSet__usage_beamManagement: {
|
||||
nfapi_nr_srs_beamforming_report_t nr_srs_beamforming_report;
|
||||
unpack_nr_srs_beamforming_report(srs_ind->report_tlv->value,
|
||||
srs_ind->report_tlv->length,
|
||||
&nr_srs_beamforming_report,
|
||||
sizeof(nfapi_nr_srs_beamforming_report_t));
|
||||
|
||||
memset(ulprbbl, 0, reported_symbol_list[0].num_rbs * sizeof(uint16_t));
|
||||
if (nr_srs_beamforming_report.wide_band_snr == 0xFF) {
|
||||
LOG_W(NR_MAC, "Invalid wide_band_snr for RNTI %04x\n", srs_ind->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
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 < wide_band_snr_dB - ul_prbblack_SNR_threshold) {
|
||||
ulprbbl[rb] = 0x3FFF; // all symbols taken
|
||||
int wide_band_snr_dB = (nr_srs_beamforming_report.wide_band_snr >> 1) - 64;
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_MAC, "nr_srs_beamforming_report.prg_size = %i\n", nr_srs_beamforming_report.prg_size);
|
||||
LOG_I(NR_MAC, "nr_srs_beamforming_report.num_symbols = %i\n", nr_srs_beamforming_report.num_symbols);
|
||||
LOG_I(NR_MAC, "nr_srs_beamforming_report.wide_band_snr = %i (%i dB)\n", nr_srs_beamforming_report.wide_band_snr, wide_band_snr_dB);
|
||||
LOG_I(NR_MAC, "nr_srs_beamforming_report.num_reported_symbols = %i\n", nr_srs_beamforming_report.num_reported_symbols);
|
||||
LOG_I(NR_MAC, "nr_srs_beamforming_report.prgs[0].num_prgs = %i\n", nr_srs_beamforming_report.prgs[0].num_prgs);
|
||||
for (int prg_idx = 0; prg_idx < nr_srs_beamforming_report.prgs[0].num_prgs; prg_idx++) {
|
||||
LOG_I(NR_MAC,
|
||||
"nr_srs_beamforming_report.prgs[0].prg_list[%3i].rb_snr = %i (%i dB)\n",
|
||||
prg_idx,
|
||||
nr_srs_beamforming_report.prgs[0].prg_list[prg_idx].rb_snr,
|
||||
(nr_srs_beamforming_report.prgs[0].prg_list[prg_idx].rb_snr >> 1) - 64);
|
||||
}
|
||||
#endif
|
||||
|
||||
sprintf(stats->srs_stats, "UL-SNR %i dB", wide_band_snr_dB);
|
||||
|
||||
const int ul_prbblack_SNR_threshold = nr_mac->ul_prbblack_SNR_threshold;
|
||||
uint16_t *ulprbbl = nr_mac->ulprbbl;
|
||||
|
||||
uint8_t num_rbs = nr_srs_beamforming_report.prg_size * nr_srs_beamforming_report.prgs[0].num_prgs;
|
||||
memset(ulprbbl, 0, num_rbs * sizeof(uint16_t));
|
||||
for (int rb = 0; rb < num_rbs; rb++) {
|
||||
int snr = (nr_srs_beamforming_report.prgs[0].prg_list[rb / nr_srs_beamforming_report.prg_size].rb_snr >> 1) - 64;
|
||||
if (snr < wide_band_snr_dB - ul_prbblack_SNR_threshold) {
|
||||
ulprbbl[rb] = 0x3FFF; // all symbols taken
|
||||
}
|
||||
LOG_D(NR_MAC, "ulprbbl[%3i] = 0x%x\n", rb, ulprbbl[rb]);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
LOG_D(NR_MAC, "ulprbbl[%3i] = 0x%x\n", rb, ulprbbl[rb]);
|
||||
|
||||
case NR_SRS_ResourceSet__usage_codebook: {
|
||||
nfapi_nr_srs_normalized_channel_iq_matrix_t nr_srs_normalized_channel_iq_matrix;
|
||||
unpack_nr_srs_normalized_channel_iq_matrix(srs_ind->report_tlv->value,
|
||||
srs_ind->report_tlv->length,
|
||||
&nr_srs_normalized_channel_iq_matrix,
|
||||
sizeof(nfapi_nr_srs_normalized_channel_iq_matrix_t));
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_MAC, "nr_srs_normalized_channel_iq_matrix.normalized_iq_representation = %i\n", nr_srs_normalized_channel_iq_matrix.normalized_iq_representation);
|
||||
LOG_I(NR_MAC, "nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements = %i\n", nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements);
|
||||
LOG_I(NR_MAC, "nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports = %i\n", nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports);
|
||||
LOG_I(NR_MAC, "nr_srs_normalized_channel_iq_matrix.prg_size = %i\n", nr_srs_normalized_channel_iq_matrix.prg_size);
|
||||
LOG_I(NR_MAC, "nr_srs_normalized_channel_iq_matrix.num_prgs = %i\n", nr_srs_normalized_channel_iq_matrix.num_prgs);
|
||||
c16_t *channel_matrix16 = (c16_t *)nr_srs_normalized_channel_iq_matrix.channel_matrix;
|
||||
c8_t *channel_matrix8 = (c8_t *)nr_srs_normalized_channel_iq_matrix.channel_matrix;
|
||||
for (int uI = 0; uI < nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports; uI++) {
|
||||
for (int gI = 0; gI < nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements; gI++) {
|
||||
for (int pI = 0; pI < nr_srs_normalized_channel_iq_matrix.num_prgs; pI++) {
|
||||
uint16_t index = uI * nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements * nr_srs_normalized_channel_iq_matrix.num_prgs + gI * nr_srs_normalized_channel_iq_matrix.num_prgs + pI;
|
||||
LOG_I(NR_MAC,
|
||||
"(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n",
|
||||
uI,
|
||||
gI,
|
||||
pI,
|
||||
nr_srs_normalized_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].r : channel_matrix16[index].r,
|
||||
nr_srs_normalized_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].i : channel_matrix16[index].i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: This should be improved
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
|
||||
sched_ctrl->srs_feedback.sri = NR_SRS_SRI_0;
|
||||
sched_ctrl->srs_feedback.ul_ri = 0; // TODO: Compute this
|
||||
sched_ctrl->srs_feedback.tpmi = nr_srs_tpmi_estimation(current_BWP->pusch_Config,
|
||||
current_BWP->transform_precoding,
|
||||
nr_srs_normalized_channel_iq_matrix.channel_matrix,
|
||||
nr_srs_normalized_channel_iq_matrix.normalized_iq_representation,
|
||||
nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements,
|
||||
nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports,
|
||||
nr_srs_normalized_channel_iq_matrix.prg_size,
|
||||
nr_srs_normalized_channel_iq_matrix.num_prgs,
|
||||
sched_ctrl->srs_feedback.ul_ri);
|
||||
sprintf(stats->srs_stats, "UL-RI %d, TPMI %d", sched_ctrl->srs_feedback.ul_ri + 1, sched_ctrl->srs_feedback.tpmi);
|
||||
break;
|
||||
}
|
||||
|
||||
case NR_SRS_ResourceSet__usage_nonCodebook:
|
||||
case NR_SRS_ResourceSet__usage_antennaSwitching:
|
||||
LOG_W(NR_MAC, "MAC procedures for this SRS usage are not implemented yet!\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1 == 0, "Invalid SRS usage\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1851,9 +2251,11 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot)
|
||||
scc,
|
||||
pusch_pdu,
|
||||
&uldci_payload,
|
||||
&sched_ctrl->srs_feedback,
|
||||
sched_pusch->time_domain_allocation,
|
||||
UE->UE_sched_ctrl.tpc0,
|
||||
current_BWP);
|
||||
|
||||
fill_dci_pdu_rel15(scc,
|
||||
cg,
|
||||
&UE->current_DL_BWP,
|
||||
|
||||
@@ -189,6 +189,7 @@ void config_uldci(const NR_SIB1_t *sib1,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
int time_domain_assignment,
|
||||
uint8_t tpc,
|
||||
NR_UE_UL_BWP_t *ul_bwp);
|
||||
@@ -441,12 +442,7 @@ void handle_nr_ul_harq(const int CC_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);
|
||||
const nfapi_nr_srs_indication_pdu_t *srs_ind);
|
||||
|
||||
int16_t ssb_index_from_prach(module_id_t module_idP,
|
||||
frame_t frameP,
|
||||
|
||||
@@ -93,14 +93,14 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE RNTI %04x (%d) PH %d dB PCMAX %d dBm, average RSRP %d (%d meas), UL-SNR %d dB\n",
|
||||
"UE RNTI %04x (%d) PH %d dB PCMAX %d dBm, average RSRP %d (%d meas)\n",
|
||||
UE->rnti,
|
||||
num++,
|
||||
sched_ctrl->ph,
|
||||
sched_ctrl->pcmax,
|
||||
avg_rsrp,
|
||||
stats->num_rsrp_meas,
|
||||
stats->srs_wide_band_snr);
|
||||
stats->num_rsrp_meas);
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: CQI %d, RI %d, PMI (%d,%d)\n",
|
||||
@@ -110,6 +110,10 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
||||
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x1,
|
||||
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x2);
|
||||
|
||||
if (stats->srs_stats[0] != '\0') {
|
||||
output += snprintf(output, end - output, "UE %04x: %s\n", UE->rnti, stats->srs_stats);
|
||||
}
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: dlsch_rounds ", UE->rnti);
|
||||
|
||||
@@ -634,7 +634,7 @@ typedef struct {
|
||||
NR_list_t feedback_ul_harq;
|
||||
/// UL HARQ processes that await retransmission
|
||||
NR_list_t retrans_ul_harq;
|
||||
NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl;// MAC CE related information
|
||||
NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl; // MAC CE related information
|
||||
/// number of active DL LCs
|
||||
uint8_t dl_lc_num;
|
||||
/// order in which DLSCH scheduler should allocate LCs
|
||||
@@ -642,6 +642,9 @@ typedef struct {
|
||||
|
||||
/// Timer for RRC processing procedures
|
||||
uint32_t rrc_processing_timer;
|
||||
|
||||
/// sri, ul_ri and tpmi based on SRS
|
||||
nr_srs_feedback_t srs_feedback;
|
||||
} NR_UE_sched_ctrl_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -668,7 +671,7 @@ typedef struct NR_mac_stats {
|
||||
uint32_t pucch0_DTX;
|
||||
int cumul_rsrp;
|
||||
uint8_t num_rsrp_meas;
|
||||
int8_t srs_wide_band_snr;
|
||||
char srs_stats[50]; // Statistics may differ depending on SRS usage
|
||||
} NR_mac_stats_t;
|
||||
|
||||
typedef struct NR_bler_options {
|
||||
|
||||
@@ -239,12 +239,7 @@ void handle_nr_srs(NR_UL_IND_t *UL_info) {
|
||||
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);
|
||||
&srs_list[i]);
|
||||
}
|
||||
|
||||
UL_info->srs_ind.number_of_pdus = 0;
|
||||
|
||||
@@ -1002,9 +1002,10 @@ void fill_initial_SpCellConfig(int uid,
|
||||
|
||||
SpCellConfig->spCellConfigDedicated = calloc(1,sizeof(*SpCellConfig->spCellConfigDedicated));
|
||||
SpCellConfig->spCellConfigDedicated->uplinkConfig = calloc(1,sizeof(*SpCellConfig->spCellConfigDedicated->uplinkConfig));
|
||||
NR_UplinkConfig_t *uplinkConfig = SpCellConfig->spCellConfigDedicated->uplinkConfig;
|
||||
|
||||
NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1,sizeof(*initialUplinkBWP));
|
||||
SpCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP = initialUplinkBWP;
|
||||
uplinkConfig->initialUplinkBWP = initialUplinkBWP;
|
||||
initialUplinkBWP->pucch_Config = calloc(1,sizeof(*initialUplinkBWP->pucch_Config));
|
||||
initialUplinkBWP->pucch_Config->present = NR_SetupRelease_PUCCH_Config_PR_setup;
|
||||
NR_PUCCH_Config_t *pucch_Config = calloc(1,sizeof(*pucch_Config));
|
||||
@@ -1090,9 +1091,15 @@ void fill_initial_SpCellConfig(int uid,
|
||||
pusch_Config->uci_OnPUSCH=NULL;
|
||||
pusch_Config->tp_pi2BPSK=NULL;
|
||||
|
||||
long maxMIMO_Layers = uplinkConfig &&
|
||||
uplinkConfig->pusch_ServingCellConfig &&
|
||||
uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1 &&
|
||||
uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers ?
|
||||
*uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers : 1;
|
||||
|
||||
// We are using do_srs = 0 here because the periodic SRS will only be enabled in update_cellGroupConfig() if do_srs == 1
|
||||
initialUplinkBWP->srs_Config = calloc(1,sizeof(*initialUplinkBWP->srs_Config));
|
||||
config_srs(initialUplinkBWP->srs_Config, NULL, curr_bwp, uid, 0, 0);
|
||||
config_srs(initialUplinkBWP->srs_Config, NULL, curr_bwp, uid, 0, maxMIMO_Layers, 0);
|
||||
|
||||
scheduling_request_config(scc, pucch_Config);
|
||||
|
||||
@@ -1216,7 +1223,7 @@ void fill_initial_SpCellConfig(int uid,
|
||||
n_ul_bwp = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count;
|
||||
}
|
||||
if(n_ul_bwp>0) {
|
||||
SpCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList = calloc(1,sizeof(*SpCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList));
|
||||
uplinkConfig->uplinkBWP_ToAddModList = calloc(1,sizeof(*uplinkConfig->uplinkBWP_ToAddModList));
|
||||
for (int bwp_loop = 0; bwp_loop < n_ul_bwp; bwp_loop++) {
|
||||
NR_BWP_Uplink_t *ubwp = calloc(1, sizeof(*ubwp));
|
||||
config_uplinkBWP(ubwp, bwp_loop, true, uid,
|
||||
@@ -1224,13 +1231,12 @@ void fill_initial_SpCellConfig(int uid,
|
||||
servingcellconfigdedicated,
|
||||
scc,
|
||||
NULL);
|
||||
ASN_SEQUENCE_ADD(&SpCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list, ubwp);
|
||||
ASN_SEQUENCE_ADD(&uplinkConfig->uplinkBWP_ToAddModList->list, ubwp);
|
||||
}
|
||||
SpCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = calloc(1,sizeof(*SpCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id));
|
||||
*SpCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id ? *servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id : 1;
|
||||
uplinkConfig->firstActiveUplinkBWP_Id = calloc(1,sizeof(*uplinkConfig->firstActiveUplinkBWP_Id));
|
||||
*uplinkConfig->firstActiveUplinkBWP_Id = servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id ? *servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id : 1;
|
||||
}
|
||||
|
||||
|
||||
SpCellConfig->spCellConfigDedicated->csi_MeasConfig=calloc(1,sizeof(*SpCellConfig->spCellConfigDedicated->csi_MeasConfig));
|
||||
SpCellConfig->spCellConfigDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup;
|
||||
|
||||
@@ -1585,6 +1591,12 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
|
||||
|
||||
if(scc) {
|
||||
int curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,MAX_BWP_SIZE);
|
||||
NR_UplinkConfig_t *uplinkConfig = SpCellConfig && SpCellConfig->spCellConfigDedicated ? SpCellConfig->spCellConfigDedicated->uplinkConfig : NULL;
|
||||
long maxMIMO_Layers = uplinkConfig &&
|
||||
uplinkConfig->pusch_ServingCellConfig &&
|
||||
uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1 &&
|
||||
uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers ?
|
||||
*uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers : 1;
|
||||
// SRS configuration
|
||||
if (configuration->do_SRS &&
|
||||
SpCellConfig &&
|
||||
@@ -1600,6 +1612,7 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
|
||||
curr_bwp,
|
||||
uid,
|
||||
0,
|
||||
maxMIMO_Layers,
|
||||
configuration->do_SRS);
|
||||
}
|
||||
|
||||
@@ -1625,6 +1638,7 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
|
||||
bwp_size,
|
||||
uid,
|
||||
i+1,
|
||||
maxMIMO_Layers,
|
||||
configuration->do_SRS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,8 +356,9 @@ void config_srs(NR_SetupRelease_SRS_Config_t *setup_release_srs_Config,
|
||||
const int curr_bwp,
|
||||
const int uid,
|
||||
const int res_id,
|
||||
const int do_srs) {
|
||||
|
||||
const long maxMIMO_Layers,
|
||||
const int do_srs)
|
||||
{
|
||||
setup_release_srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup;
|
||||
|
||||
NR_SRS_Config_t *srs_Config;
|
||||
@@ -419,26 +420,45 @@ void config_srs(NR_SetupRelease_SRS_Config_t *setup_release_srs_Config,
|
||||
NR_SRS_Resource_t *srs_res0=calloc(1,sizeof(*srs_res0));
|
||||
srs_res0->srs_ResourceId = res_id;
|
||||
srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_port1;
|
||||
// if (uecap &&
|
||||
// uecap->featureSets &&
|
||||
// uecap->featureSets->featureSetsUplink &&
|
||||
// uecap->featureSets->featureSetsUplink->list.count > 0) {
|
||||
// NR_FeatureSetUplink_t *ul_feature_setup = uecap->featureSets->featureSetsUplink->list.array[0];
|
||||
// switch (ul_feature_setup->supportedSRS_Resources->maxNumberSRS_Ports_PerResource) {
|
||||
// case NR_SRS_Resources__maxNumberSRS_Ports_PerResource_n1:
|
||||
// srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_port1;
|
||||
// break;
|
||||
// case NR_SRS_Resources__maxNumberSRS_Ports_PerResource_n2:
|
||||
// srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_ports2;
|
||||
// break;
|
||||
// case NR_SRS_Resources__maxNumberSRS_Ports_PerResource_n4:
|
||||
// srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_ports4;
|
||||
// break;
|
||||
// default:
|
||||
// LOG_E(NR_RRC, "Max Number of SRS Ports Per Resource %ld is invalid!\n",
|
||||
// ul_feature_setup->supportedSRS_Resources->maxNumberSRS_Ports_PerResource);
|
||||
// }
|
||||
// }
|
||||
if (do_srs) {
|
||||
long nrofSRS_Ports = 1;
|
||||
if (uecap &&
|
||||
uecap->featureSets &&
|
||||
uecap->featureSets->featureSetsUplink &&
|
||||
uecap->featureSets->featureSetsUplink->list.count > 0) {
|
||||
NR_FeatureSetUplink_t *ul_feature_setup = uecap->featureSets->featureSetsUplink->list.array[0];
|
||||
switch (ul_feature_setup->supportedSRS_Resources->maxNumberSRS_Ports_PerResource) {
|
||||
case NR_SRS_Resources__maxNumberSRS_Ports_PerResource_n1:
|
||||
nrofSRS_Ports = 1;
|
||||
break;
|
||||
case NR_SRS_Resources__maxNumberSRS_Ports_PerResource_n2:
|
||||
nrofSRS_Ports = 2;
|
||||
break;
|
||||
case NR_SRS_Resources__maxNumberSRS_Ports_PerResource_n4:
|
||||
nrofSRS_Ports = 4;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_RRC, "Max Number of SRS Ports Per Resource %ld is invalid!\n",
|
||||
ul_feature_setup->supportedSRS_Resources->maxNumberSRS_Ports_PerResource);
|
||||
}
|
||||
nrofSRS_Ports = min(nrofSRS_Ports, maxMIMO_Layers);
|
||||
switch (nrofSRS_Ports) {
|
||||
case 1:
|
||||
srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_port1;
|
||||
break;
|
||||
case 2:
|
||||
srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_ports2;
|
||||
break;
|
||||
case 4:
|
||||
srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_ports4;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_RRC, "Number of SRS Ports Per Resource %ld is invalid!\n",
|
||||
ul_feature_setup->supportedSRS_Resources->maxNumberSRS_Ports_PerResource);
|
||||
}
|
||||
}
|
||||
LOG_I(NR_RRC, "SRS configured with %d ports\n", 1<<srs_res0->nrofSRS_Ports);
|
||||
}
|
||||
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));
|
||||
@@ -1136,12 +1156,20 @@ void config_uplinkBWP(NR_BWP_Uplink_t *ubwp,
|
||||
pusch_Config->uci_OnPUSCH=NULL;
|
||||
pusch_Config->tp_pi2BPSK=NULL;
|
||||
|
||||
long maxMIMO_Layers = servingcellconfigdedicated &&
|
||||
servingcellconfigdedicated->uplinkConfig
|
||||
&& servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig
|
||||
&& servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1
|
||||
&& servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers ?
|
||||
*servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers : 1;
|
||||
|
||||
ubwp->bwp_Dedicated->srs_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->srs_Config));
|
||||
config_srs(ubwp->bwp_Dedicated->srs_Config,
|
||||
NULL,
|
||||
curr_bwp,
|
||||
uid,
|
||||
bwp_loop+1,
|
||||
maxMIMO_Layers,
|
||||
configuration->do_SRS);
|
||||
|
||||
ubwp->bwp_Dedicated->configuredGrantConfig = NULL;
|
||||
|
||||
@@ -150,6 +150,7 @@ void config_srs(NR_SetupRelease_SRS_Config_t *setup_release_srs_Config,
|
||||
const int curr_bwp,
|
||||
const int uid,
|
||||
const int res_id,
|
||||
const long maxMIMO_Layers,
|
||||
const int do_srs);
|
||||
void set_dl_mcs_table(int scs,
|
||||
NR_UE_NR_Capability_t *cap,
|
||||
|
||||
@@ -91,6 +91,12 @@
|
||||
#define NR_RRC_RECONFIGURATION_DELAY_MS 10
|
||||
#define NR_RRC_BWP_SWITCHING_DELAY_MS 6
|
||||
|
||||
// 3GPP TS 38.133 - Section 8 - Table 8.2.1.2.7-2: Parameters which cause interruption other than SCS
|
||||
// This table was recently added to 3GPP. It shows that changing the parameters locationAndBandwidth, nrofSRS-Ports or
|
||||
// maxMIMO-Layers-r16 causes an interruption. This parameter is not yet being used in code, but has been placed here
|
||||
// for future reference.
|
||||
#define NR_OF_SRS_PORTS_SWITCHING_DELAY_MS 30
|
||||
|
||||
#define NR_UE_MODULE_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!!
|
||||
#define NR_UE_INDEX_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!! used to be -1
|
||||
|
||||
|
||||
@@ -479,9 +479,15 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
LOG_I(RRC,"TRANSFORM PRECODING ENABLED......\n");
|
||||
}
|
||||
|
||||
long maxMIMO_Layers = servingcellconfigdedicated->uplinkConfig &&
|
||||
servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig &&
|
||||
servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1 &&
|
||||
servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers ?
|
||||
*servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers : 1;
|
||||
|
||||
int curr_bwp = NRRIV2BW(servingcellconfigcommon->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,MAX_BWP_SIZE);
|
||||
initialUplinkBWP->srs_Config = calloc(1,sizeof(*initialUplinkBWP->srs_Config));
|
||||
config_srs(initialUplinkBWP->srs_Config, NULL, curr_bwp, uid, 0, configuration->do_SRS);
|
||||
config_srs(initialUplinkBWP->srs_Config, NULL, curr_bwp, uid, 0, maxMIMO_Layers, configuration->do_SRS);
|
||||
|
||||
// Downlink BWPs
|
||||
int n_dl_bwp = 1;
|
||||
|
||||
Reference in New Issue
Block a user