/*
 * 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
 */

#include "PHY/types.h"

/**
   \brief Gold Sequence Generation defined in 3x.211
   \param x1 x1 shift register
   \param x2 x2 shift register / cinit if reset is set
   \param reset Reset flag / reinitialize the generator
   \return c 32 bits of gold output
*/
extern inline  uint32_t lte_gold_generic(uint32_t *x1, uint32_t *x2, uint8_t reset)
{
  int32_t n;

  // 3GPP 3x.211
  // Nc = 1600
  // c(n)     = [x1(n+Nc) + x2(n+Nc)]mod2
  // x1(n+31) = [x1(n+3)                     + x1(n)]mod2
  // x2(n+31) = [x2(n+3) + x2(n+2) + x2(n+1) + x2(n)]mod2
  if (reset)
  {
      // Init value for x1: x1(0) = 1, x1(n) = 0, n=1,2,...,30
      // x1(31) = [x1(3) + x1(0)]mod2 = 1
      *x1 = 1 + (1U<<31);
      // Init value for x2: cinit = sum_{i=0}^30 x2*2^i
      // x2(31) = [x2(3)    + x2(2)    + x2(1)    + x2(0)]mod2
      //        =  (*x2>>3) ^ (*x2>>2) + (*x2>>1) + *x2
      *x2 = *x2 ^ ((*x2 ^ (*x2>>1) ^ (*x2>>2) ^ (*x2>>3))<<31);

      // x1 and x2 contain bits n = 0,1,...,31

      // Nc = 1600 bits are skipped at the beginning
      // i.e., 1600 / 32 = 50 32bit words

      for (n = 1; n < 50; n++)
      {
          // Compute x1(0),...,x1(27)
          *x1 = (*x1>>1) ^ (*x1>>4);
          // Compute x1(28),..,x1(31) and xor
          *x1 = *x1 ^ (*x1<<31) ^ (*x1<<28);
          // Compute x2(0),...,x2(27)
          *x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4);
          // Compute x2(28),..,x2(31) and xor
          *x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28);
      }
  }

  *x1 = (*x1>>1) ^ (*x1>>4);
  *x1 = *x1 ^ (*x1<<31) ^ (*x1<<28);
  *x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4);
  *x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28);

  // c(n) = [x1(n+Nc) + x2(n+Nc)]mod2
  return(*x1^*x2);
}