diff gsm-fw/ccd/freq_list_com.c @ 648:970d6199f2c5

gsm-fw/ccd/*.[ch]: initial import from the LoCosto source
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Thu, 04 Sep 2014 05:48:57 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gsm-fw/ccd/freq_list_com.c	Thu Sep 04 05:48:57 2014 +0000
@@ -0,0 +1,421 @@
+/*
++-----------------------------------------------------------------------------
+|  Project : CCD
+|  Modul   : freq_list_com.c
++-----------------------------------------------------------------------------
+|  Copyright 2004 Texas Instruments Deutschland GmbH
+|                 All rights reserved. 
+| 
+|                 This file is confidential and a trade secret of Texas 
+|                 Instruments Deutschland GmbH 
+|                 The receipt of or possession of this file does not convey 
+|                 any rights to reproduce or disclose its contents or to 
+|                 manufacture, use, or sell anything it may describe, in 
+|                 whole, or in part, without the specific written consent of 
+|                 Texas Instruments Deutschland GmbH. 
++-----------------------------------------------------------------------------
+|  Purpose :  Definitions of common functions for decoding of types FDD_CI,
+|             TDD_CI and FREQ_LIST.
++-----------------------------------------------------------------------------
+*/
+
+#define CDC_FREQ_LIST_COM_C
+
+/*
+ * standard definitions like GLOBAL, UCHAR, ERROR etc.
+ */
+#include "typedefs.h"
+#include "header.h"
+
+/*
+ * Types and functions for bit access and manipulation
+ */
+#include "ccd_globs.h"
+#include "bitfun.h"
+
+/*
+ * Error codes and prototypes of exported functions by CCD
+ */
+#include "ccdapi.h"
+
+/*
+ * Prototypes of ccd internal functions
+ */
+#include "ccd.h"
+
+#ifndef RUN_INT_RAM
+U8 ByteBitMask[]= {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x1};
+#endif /* !RUN_INT_RAM */
+
+#ifndef RUN_INT_RAM
+/*
+ * The following table indicates the number of W-parameters and their
+ * length in bits. A length of zero indicates the end of the table.
+ * For frequency lists the W-parameter in the 1024 range starts from 
+ * bit 6 of the information element.
+ */
+const T_W_PARAM param_1024[9] =
+{
+ /*
+  * length       count
+  */
+      10,          1,
+       9,          2,
+       8,          4,
+       7,          8,
+       6,          16,
+       5,          32,
+       4,          64,
+       3,          128,
+       0,          0
+};
+#endif /* !RUN_INT_RAM */
+
+#ifndef RUN_INT_RAM
+/*
+ * The following table indicates the number of W-parameters and their
+ * length in bits. A length of zero indicates the end of the table.
+ * For frequency lists the W-parameter in the 512 range starts from 
+ * bit 7 of the information element.
+ */
+const T_W_PARAM param_512[10] =
+{
+ /*
+  *  length     count
+  */
+       10,        1,
+        9,        1,
+        8,        2,
+        7,        4,
+        6,        8,
+        5,       16,
+        4,       32,
+        3,       64,
+        2,      128,
+        0,        0
+};
+#endif /* !RUN_INT_RAM */
+
+#ifndef RUN_INT_RAM
+/* Attention for RUN_...: static function */
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD            FUNCTION : for_modulo                     |
++--------------------------------------------------------------------+
+
+  PURPOSE : A modulo calculation function. The standard C-Operator
+            fails for negative values! (e.g. -4 mod 6 is 2 and not 4).
+
+*/
+
+/* static */ long for_modulo (long a, long b)
+{
+  long result;
+
+  /* Use standard C-Operator for calculation. */
+  result = a % b;
+
+  /* Correct the result for negative values. */
+  if (result < 0)
+  {
+    result += b;
+  }
+
+  return result;
+}
+#endif /* !RUN_INT_RAM */
+
+#ifndef RUN_INT_RAM
+/* Attention for RUN_...: static function */
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD            FUNCTION : for_smodulo                    |
++--------------------------------------------------------------------+
+
+  PURPOSE : Similar to the modulo operator, but 0 smod n is n and
+            not 0. Same problem for negative values with the standard
+            C-Operator.
+
+*/
+static long for_smodulo (long a, long b)
+{
+  long result;
+
+  /* Use standard C-Operator for calculation. */
+  result = a % b;
+
+  /* Correct the result for negative values. */
+  if (result < 0)
+  {
+    result += b;
+  }
+
+  /* Special handling for result equal 0 */
+  if (result EQ 0)
+  {
+    result = b;
+  }
+
+  return result;
+}
+#endif /* !RUN_INT_RAM */
+
+#ifndef RUN_INT_RAM
+/* Attention for RUN_...: static function */
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD            FUNCTION : for_get_generation             |
++--------------------------------------------------------------------+
+
+  PURPOSE : The function calculates the greatest power of 2 of the given
+            value. The algorithm simply looks to the position of the
+            highest bit.
+
+*/
+
+static U16 for_get_generation (U16 value)
+{
+  int result = 0;
+  int i;
+
+
+  /* Check all 16 bit positions. */
+  for (i = 0; i < 16; i++)
+  {
+    /* If bit is set, store the position. */
+    if (value & 1)
+    {
+      result = i + 1;
+    }
+
+    /* Shift value to have the next bit for comparision. */
+    value = value >> 1;
+  }
+
+  /* Return the highest position. */
+  return result;
+}
+#endif /* !RUN_INT_RAM */
+
+#ifndef RUN_INT_RAM
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD            FUNCTION : cdc_decode_frequencies         |
++--------------------------------------------------------------------+
+
+  PURPOSE : The algorithm is according GSM 4.08 Annex J. It calculates
+            a frequency hopping list from the W-parameter.
+
+*/
+void cdc_decode_frequencies (short        original_range,
+                             short       *w,
+                             short        offset,
+                             U8           callerID,
+                             T_CCD_Globs *globs)
+{
+  short g;
+  short k;
+  short j;
+  short index;
+  short n;
+  short range;
+  U16   channel;
+  U16   bitposition;
+  U8   *BitmapInStruct = globs->pstruct + globs->pstructOffs;
+  U16 first = 0;
+  U16 last  = BITOFFSET_LIST;
+  U16 num   = 0;
+  BOOL ReadW = TRUE;
+
+#ifdef DEBUG_CCD
+  TRACE_CCD (globs, "cdc_decode_frequencies()");
+#endif
+
+  if (callerID != TDD_CI_LIST && w[0] == 0)
+    ReadW = FALSE;
+  for (k = 1; ReadW; k++)
+  {
+    ReadW = (w[k-1] != 0) ? 1 : 0;
+    /*
+     * The next loop follows the tree from child to parent,
+     * from the node of index K to the root (index 1). For each iteration the
+     * node of index INDEX is tackled. The corresponding range is RANGE, and N
+     * is the value of the element in the range defined by the node.
+     *
+     * The data are set to their initial values
+     */
+    index = k;
+    n = w[index-1];
+    g = for_get_generation (index);
+    j = (1 << (g-1));
+    range = original_range / j;
+
+    while (index > 1)
+    {
+      /*
+       * Due to the assumption that the original range is a power of two minus one,
+       * the range for the parent node can be easily computed, and does not depend
+       * upon whether the current node is a left or right child
+       */
+      g     = for_get_generation (index);
+      j     = (1 << (g-1));
+      range = 2 * range + 1;
+
+      /*
+       * Let us note J := 2 g-1 , g being the generation of node INDEX. We have J =
+       * GREATEST_POWER_OF_2_LESSER_OR_EQUAL_TO(INDEX). The numbering used in the tree
+       * is such that the nodes of index J to J + J/2 - 1 are left children, and the nodes
+       * of index J/2 to J+J-1 are right children. Hence an easy test to
+       * distinguish left and right children:
+       */
+      if (2 * index < 3 * j)
+      {
+        /*
+         * The next computation gives the index of the parent node of the node of index
+         * INDEX, for a left child :
+         */
+        index = index - j / 2;
+
+        /*
+         * The next formula is the inverse of the renumbering appearing in the encoding
+         * for a left child. It gives the value of the parent node in the range defined
+         * by the grand-parent node:
+         */
+        n = (short)for_smodulo (n + w[index-1] + (range-1) / 2, range);
+      }
+      else
+      {
+        /*
+         * The next computation gives the index of the parent node of the node of index
+         * INDEX, for a right child :
+         */
+        index = index - j;
+
+        /*
+         * The next formula is the inverse of the renumbering appearing in the encoding
+         * for a right child:
+         */
+        n = (short)for_smodulo (n + w[index-1], range);
+      }
+    }
+
+    /*
+     * Write the calculated number for non-frequency types.
+     * For TDD_CI and TDD_CI: offset = 0 and original_range = 1023.
+     */
+    channel = (U16)for_modulo (n+offset, 1024);
+    if (callerID == FDD_CI_LIST || callerID == TDD_CI_LIST)
+    {
+      *(U16*)(globs->pstruct + globs->pstructOffs) = (U16)channel;
+      globs->pstructOffs += 2;
+    }
+    /* Set the calculated channel number for frequency channel list.*/
+    else
+    {
+      if (channel == 0)
+      {
+        bitposition = 0;
+      }
+      else
+      {
+        bitposition = (U16)(BITOFFSET_LIST - channel);
+      }
+      if (first > bitposition)
+        first = bitposition;
+      if (last < bitposition)
+        last = bitposition;
+      num++;
+      BitmapInStruct[bitposition >> 3] |= ByteBitMask[bitposition & 7];
+    }
+  }
+
+  /* For the bitmap type print the helpful information into the structure. */
+  if (callerID == FREQUENCY_LIST)
+  {
+    *(U16*) (BitmapInStruct - 6) = first;
+    *(U16*) (BitmapInStruct - 6) = last;
+    *(U16*) (BitmapInStruct - 2) = num;
+  }
+}
+#endif /* !RUN_INT_RAM */
+
+#ifndef RUN_INT_RAM
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD            FUNCTION : cdc_decode_param               |
++--------------------------------------------------------------------+
+
+  PURPOSE : The information element contains a list of W-parameter.
+            The table param indicates how many W-parameter from each
+            length shall be inside. The function converts the bitstream
+            of the W-parameter to an array of W-parameter 16 bit values.
+
+*/
+
+void cdc_decode_param (const T_W_PARAM *param,
+                       short           *w,
+                       U16              ListLength,
+                       T_CCD_Globs     *globs)
+{
+  U8  end_detected = FALSE;
+  U16 w_index      = 0;
+  U16 length       = ListLength;
+  U16 act_length   = param->length;
+  U16 act_counter  = param->count;
+  U32 lvalue;
+
+#ifdef DEBUG_CCD
+  TRACE_CCD (globs, "cdc_decode_param()");
+#endif
+
+  /*
+   * Decode values in the list until the end of the IE is detected.
+   */
+  while (!end_detected)
+  {
+    /*
+     * If the length of the next W-parameter is greater than eight bits,
+     * use ccd_decodeLong function. For smaller length use the 
+     * ccd_decodeByte function to extract the W-parameter from the bitstream.
+     */
+    lvalue = bf_getBits (act_length, globs);
+    w[w_index++] = (short)lvalue;
+
+    /*
+     * w = 0 is equal to end of list if it is not the w(0) !!!
+     * (The case w(0)=0 possible for frequency list, but maybe not for other
+     * cases this algorithm is invoked.
+     */
+    if (w_index != 1 && w[w_index-1] == 0)
+    {
+      end_detected = TRUE;
+    }
+
+    /* End of buffer is equal to end of list. */
+    if (length > act_length)
+    {
+      length -= act_length;
+    }
+    else
+    {
+      end_detected = TRUE;
+    }
+
+    /* Check if all w parameters of one size are read. */
+    if (--act_counter == 0)
+    {
+      param++;
+      act_length   = param->length;
+      act_counter  = param->count;
+    }
+    /* End of parameter table */
+    if ((act_length == 0) || (length < act_length))
+    {
+      end_detected = TRUE;
+    }
+  }
+
+  /* Add an end identifier. */
+  w[w_index++] = 0;
+}
+#endif /* !RUN_INT_RAM */