view src/gpf/ccd/freq_list_com.c @ 287:3dee79757ae4

UI fw: load handheld audio mode on boot We have now reached the point where use of audio mode config files should be considered mandatory. In ACI usage we can tell users that they need to perform an AT@AUL of some appropriate audio mode, but in UI-enabled fw we really need to have the firmware load audio modes on its own, so that correct audio config gets established when the handset or development board runs on its own, without a connected host computer. Once have FC Venus with both main and headset audio channels and headset plug insertion detection, our fw will need to automatically load the handheld mode or the headset mode depending on the plug insertion state. For now we load only the handheld mode, which has been tuned for FC-HDS4 on FC Luna.
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 13 Nov 2021 03:20:57 +0000
parents 4e78acac3d88
children
line wrap: on
line source

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