/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /*! \file nr_uci_tools_common.c * \brief * \author * \date 2020 * \version 0.1 * \company Eurecom * \email: * \note * \warning */ #include "nr_dci.h" void nr_group_sequence_hopping(pucch_GroupHopping_t PUCCH_GroupHopping, uint32_t n_id, int n_hop, int nr_slot_tx, uint8_t *u, uint8_t *v) { /* * Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping * The following variables are set by higher layers: * - PUCCH_GroupHopping: * - n_id: higher-layer parameter hoppingId * - n_hop: frequency hopping index * if intra-slot frequency hopping is disabled by the higher-layer parameter PUCCH-frequency-hopping * n_hop=0 * if frequency hopping is enabled by the higher-layer parameter PUCCH-frequency-hopping * n_hop=0 for the first hop * n_hop=1 for the second hop */ // depending on the value of the PUCCH_GroupHopping, we will obtain different values for u,v //pucch_GroupHopping_t PUCCH_GroupHopping = ue->pucch_config_common_nr->pucch_GroupHopping; // from higher layers FIXME!!! // n_id defined as per TS 38.211 subclause 6.3.2.2.1 (is given by the higher-layer parameter hoppingId) // it is hoppingId from PUCCH-ConfigCommon: // Cell-Specific scrambling ID for group hoppping and sequence hopping if enabled // Corresponds to L1 parameter 'HoppingID' (see 38.211, section 6.3.2.2) BIT STRING (SIZE (10)) //uint16_t n_id = ue->pucch_config_common_nr->hoppingId; // from higher layers FIXME!!! #ifdef DEBUG_NR_PUCCH_TX printf("\t\t [nr_group_sequence_hopping] PUCCH_GroupHopping=%u, n_id=%u \n",PUCCH_GroupHopping,n_id); #endif uint8_t f_ss=0,f_gh=0; *u=0; *v = 0; #ifdef DEBUG_NR_PUCCH_TX printf("\t\t [nr_group_sequence_hopping] calculating u,v -> "); #endif if (PUCCH_GroupHopping == neither) { // PUCCH_GroupHopping 'neither' f_ss = n_id%30; } if (PUCCH_GroupHopping == enable) { // PUCCH_GroupHopping 'enabled' uint32_t c_init = floor(n_id / 30); // we initialize c_init to calculate u,v according to 6.3.2.2.1 of 38.211 int l = 32, minShift = (2 * nr_slot_tx + n_hop) << 3; uint32_t *seq = gold_cache(c_init, (minShift + 31) / 32 + 8); // TS 38.211 Subclause 5.2.1 int goldIdx = 0; for (int m=0; m<8; m++) { while(minShift >= l) { goldIdx++; l = l+32; } AssertFatal(goldIdx < 8 + (minShift + 31) / 32, ""); int tmpShift = (minShift & ((1 << 5) - 1)); // minShift%32; f_gh = f_gh + ((1 << m) * ((uint8_t)((seq[goldIdx] >> tmpShift) & 1))); minShift ++; } f_gh = f_gh%30; f_ss = n_id % 30; } if (PUCCH_GroupHopping == disable) { // PUCCH_GroupHopping 'disabled' uint32_t c_init = (1 << 5) * floor(n_id / 30) + (n_id % 30); // we initialize c_init to calculate u,v int goldIdx = 0; f_ss = n_id%30; int l = 32, minShift = (2 * nr_slot_tx + n_hop); while(minShift >= l) { goldIdx++; l = l+32; } // TS 38.211 Subclause 5.2.1 uint32_t *seq = gold_cache(c_init, goldIdx + 1); int tmpShift = (minShift & ((1 << 5) - 1)); // minShift%32; *v = (uint8_t)((seq[goldIdx] >> tmpShift) & 1); // *v = (uint8_t)((s>>(2*nr_slot_tx+n_hop))&1); // Not sure we have to use nr_slot_tx FIXME!!! } *u = (f_gh+f_ss)%30; #ifdef DEBUG_NR_PUCCH_TX printf("%d,%d\n",*u,*v); #endif } double nr_cyclic_shift_hopping(uint32_t n_id, uint8_t m0, uint8_t mcs, uint8_t lnormal, uint8_t lprime, int nr_slot_tx) { /* * Implements TS 38.211 subclause 6.3.2.2.2 Cyclic shift hopping * - n_id: higher-layer parameter hoppingId * - m0: provided by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift of PUCCH-F0-resource-config * - mcs: mcs=0 except for PUCCH format 0 when it depends on information to be transmitted according to TS 38.213 subclause 9.2 * - lnormal: lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission * - lprime: lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213] */ // alpha_init initialized to 2*PI/12=0.5235987756 double alpha = 0.5235987756; uint32_t c_init = n_id; // we initialize c_init again to calculate n_cs uint8_t n_cs=0; int l = 32, minShift = (14 * 8 * nr_slot_tx) + 8 * (lnormal + lprime); #ifdef DEBUG_NR_PUCCH_TX printf("\t\t [nr_cyclic_shift_hopping] calculating alpha (cyclic shift) using c_init=%u -> \n",c_init); #endif uint32_t *seq = gold_cache(c_init, 8 + (minShift + 31) / 32); // TS 38.211 Subclause 5.2.1 int goldIdx = 0; for (int m=0; m<8; m++) { while(minShift >= l) { goldIdx++; l = l+32; } AssertFatal(goldIdx < 8 + (minShift + 31) / 32, ""); int tmpShift = (minShift & ((1 << 5) - 1)); // minShift%32; minShift ++; n_cs += (1 << m) * (uint8_t)((seq[goldIdx] >> tmpShift) & 1); // calculating n_cs (Not sure we have to use nr_slot_tx FIXME!!!) // n_cs = n_cs+((1<>((14*8*nr_slot_tx) + 8*(lnormal+lprime) + m))&1))); } alpha = alpha * (double)((m0 + mcs + n_cs) % 12); #ifdef DEBUG_NR_PUCCH_TX printf("n_cs=%d -> %lf\n",n_cs,alpha); #endif return(alpha); }