view src/g23m-gprs/grr/grr_meass.c @ 220:0ed36de51973

ABB semaphore protection overhaul The ABB semaphone protection logic that came with TCS211 from TI was broken in several ways: * Some semaphore-protected functions were called from Application_Initialize() context. NU_Obtain_Semaphore() called with NU_SUSPEND fails with NU_INVALID_SUSPEND in this context, but the return value wasn't checked, and NU_Release_Semaphore() would be called unconditionally at the end. The latter call would increment the semaphore count past 1, making the semaphore no longer binary and thus no longer effective for resource protection. The fix is to check the return value from NU_Obtain_Semaphore() and skip the NU_Release_Semaphore() call if the semaphore wasn't properly obtained. * Some SPI hardware manipulation was being done before entering the semaphore- protected critical section. The fix is to reorder the code: first obtain the semaphore, then do everything else. * In the corner case of L1/DSP recovery, l1_abb_power_on() would call some non-semaphore-protected ABB & SPI init functions. The fix is to skip those calls in the case of recovery. * A few additional corner cases existed, all of which are fixed by making ABB semaphore protection 100% consistent for all ABB functions and code paths. There is still one remaining problem of priority inversion: suppose a low- priority task calls an ABB function, and some medium-priority task just happens to preempt right in the middle of that semaphore-protected ABB operation. Then the high-priority SPI task is locked out for a non-deterministic time until that medium-priority task finishes its work and goes back to sleep. This priority inversion problem remains outstanding for now.
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 26 Apr 2021 20:55:25 +0000
parents fa8dc04885d8
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  GPRS (8441)
|  Modul   :  GRR
+----------------------------------------------------------------------------- 
|  Copyright 2002 Texas Instruments Berlin, AG 
|                 All rights reserved. 
| 
|                 This file is confidential and a trade secret of Texas 
|                 Instruments Berlin, AG 
|                 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 Berlin, AG. 
+----------------------------------------------------------------------------- 
|  Purpose :  This module implements signal handler functions for service
|             MEAS of entity GRR.
+----------------------------------------------------------------------------- 
*/ 

#ifndef GRR_MEASS_C
#define GRR_MEASS_C
#endif

#define ENTITY_GRR

/*==== INCLUDES =============================================================*/

#include <string.h>
#include "typedefs.h"   /* to get Condat data types */
#include "vsi.h"        /* to get a lot of macros */
#include "macdef.h"
#include "gprs.h"
#include "gsm.h"        /* to get a lot of macros */
#include "ccdapi.h"     /* to get CCD API */
#include "cnf_grr.h"    /* to get cnf-definitions */
#include "mon_grr.h"    /* to get mon-definitions */
#include "prim.h"       /* to get the definitions of used SAP and directions */
#include "message.h"
#include "grr.h"        /* to get the global entity definitions */
#include "grr_f.h"
#include "grr_measf.h"  /* to get the definitions for interference measurements */
#include "grr_meass.h"  /* to get the own definitions */
#include "grr_measp.h"  /* to get the own definitions */
#include "cl_rlcmac.h"
#include "grr_tcs.h"

/*==== CONST ================================================================*/

#define BS_PA_MFRMS_OFFSET       2 /* BS_PA_MRMS is coded within 3 bits and  */
                                   /* ranges from 2 to 9                     */
#define DRX_DENOMINATOR_FOR_CCCH 4

/*==== LOCAL VARS ===========================================================*/

/*==== LOCAL TYPES===========================================================*/

#if !defined (NTRACE)

LOCAL void meas_im_trace_i_level( T_MEAS_IM_FILTER *filter, 
                                  T_ilev           *i_level );
  
#endif /* #if !defined (NTRACE) */

/*==== PUBLIC FUNCTIONS =====================================================*/
/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_permit
+------------------------------------------------------------------------------
| Description : This function returns whether interference measurements in
|               packet transfer mode shall be performed by Layer 1 
|               autonomously.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE meas_im_get_permit ( void )
{ 
  UBYTE permit = MPHP_IM_ENABLED;

  TRACE_FUNCTION( "meas_im_get_permit" );
  
  if( grr_data->meas_im.mode NEQ IM_MODE_IDLE_TRANSFER AND
      grr_data->meas_im.mode NEQ IM_MODE_TRANSFER          )
  {
    permit = MPHP_IM_DISABLED;
  }

  return( permit );
} /* meas_im_get_permit() */

/*
+------------------------------------------------------------------------------
| Function    : meas_init
+------------------------------------------------------------------------------
| Description : This function initializes the measurement module.
|
| Parameters  : im_mode - operation mode for interference measurements
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_init ( T_MEAS_IM_MODE im_mode )
{ 
  TRACE_FUNCTION( "meas_init" );
  
  /* general initialization */
  INIT_STATE( MEAS, MEAS_NULL );

  /* initialization of interference measurements */
  meas_im_init( im_mode );

  /* initialization of extended measurements */
  meas_em_init( );

  /* initialization of C value derivation */
  meas_c_init( );

} /* meas_init() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_rel_i_level
+------------------------------------------------------------------------------
| Description : This function returns the interference level values mapped to
|               values relative to the C value.
|
| Parameters  : *ma      - Ptr to frequency information in MA format
|               *i_level - Ptr to relative interference level values
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_get_rel_i_level ( T_MEAS_IM_CARRIER *ma,
                                      T_ilev            *i_level )
{
  T_MEAS_IM_FILTER *filter; /* filter */

  TRACE_FUNCTION( "meas_im_get_rel_i_level" );

  filter = meas_im_get_filter( ma );

  meas_im_fill_rel_iLevel( &i_level->v_ilev0, &i_level->ilev0, filter, 0 );
  meas_im_fill_rel_iLevel( &i_level->v_ilev1, &i_level->ilev1, filter, 1 );
  meas_im_fill_rel_iLevel( &i_level->v_ilev2, &i_level->ilev2, filter, 2 );
  meas_im_fill_rel_iLevel( &i_level->v_ilev3, &i_level->ilev3, filter, 3 );
  meas_im_fill_rel_iLevel( &i_level->v_ilev4, &i_level->ilev4, filter, 4 );
  meas_im_fill_rel_iLevel( &i_level->v_ilev5, &i_level->ilev5, filter, 5 );
  meas_im_fill_rel_iLevel( &i_level->v_ilev6, &i_level->ilev6, filter, 6 );
  meas_im_fill_rel_iLevel( &i_level->v_ilev7, &i_level->ilev7, filter, 7 );

#if !defined (NTRACE)

  meas_im_trace_i_level( filter, i_level );
  
#endif /* #if !defined (NTRACE) */

} /* meas_im_get_rel_i_level() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_drx_period_seconds 
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL ULONG meas_im_get_drx_period_seconds ( void )
{
  ULONG t_drx; /* DRX period for the MS */

  TRACE_FUNCTION( "meas_im_get_drx_period_seconds" );

  if( grr_is_pbcch_present( ) EQ TRUE )
  {
    if( grr_is_non_drx_mode( ) )
    {
      t_drx = DRX_NORM_FACTOR / BLOCK_PER_MF;
    }
    else
    {
      t_drx = ( DRX_NORM_FACTOR * PAGING_CYCLE ) / grr_data->ms.split_pg_cycle;
    }
  
    t_drx *= ( USEC_PER_MF / MEAS_ACRCY );
  }
  else
  {
    if( meas_is_spgc_ccch_supported( ) )
    {
      if( grr_is_non_drx_mode( ) )
      {
        t_drx = DRX_NORM_FACTOR / DRX_DENOMINATOR_FOR_CCCH;
      }
      else
      {
        t_drx = ( DRX_NORM_FACTOR * PAGING_CYCLE ) / grr_data->ms.split_pg_cycle;
      }
    }
    else
    {
      t_drx = DRX_NORM_FACTOR *
                         ( psc_db->net_ctrl.bs_pa_mfrms + BS_PA_MFRMS_OFFSET );
    }

    t_drx *= ( USEC_PER_CS_MF / MEAS_ACRCY );
  }

  return( t_drx );
} /* meas_im_get_drx_period_seconds() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_drx_period_frames
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL USHORT meas_im_get_drx_period_frames ( void )
{
  ULONG frames;

  TRACE_FUNCTION( "meas_im_get_drx_period_frames" );

  frames = meas_im_get_drx_period_seconds( ) * N_MSEC_PER_FRAME;
  frames = M_ROUND_UP( frames, Z_MSEC_PER_FRAME * DRX_NORM_FACTOR ); 
  
  return( ( USHORT )frames );
} /* meas_im_get_drx_period_frames() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_abs_i_level
+------------------------------------------------------------------------------
| Description : This function returns the interference level values mapped to
|               values as defined for RXLEV. It returns the number of bits 
|               occupied within the measurement report.
|
| Parameters  : *ma      - Ptr to frequency information in MA format
|               *i_level - Ptr to absolute interference level values
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE meas_im_get_abs_i_level ( T_MEAS_IM_CARRIER *ma,
                                       T_ilev_abs        *i_level )
{
  UBYTE used_bits;

  T_MEAS_IM_FILTER *filter; /* filter */

  TRACE_FUNCTION( "meas_im_get_abs_i_level" );

  filter = meas_im_get_filter(  ma );

  used_bits  = 
      meas_im_fill_abs_iLevel( &i_level->v_ilevabs0, &i_level->ilevabs0, filter, 0 );
  used_bits += 
      meas_im_fill_abs_iLevel( &i_level->v_ilevabs1, &i_level->ilevabs1, filter, 1 );
  used_bits +=
      meas_im_fill_abs_iLevel( &i_level->v_ilevabs2, &i_level->ilevabs2, filter, 2 );
  used_bits +=
      meas_im_fill_abs_iLevel( &i_level->v_ilevabs3, &i_level->ilevabs3, filter, 3 );
  used_bits +=
      meas_im_fill_abs_iLevel( &i_level->v_ilevabs4, &i_level->ilevabs4, filter, 4 );
  used_bits +=
      meas_im_fill_abs_iLevel( &i_level->v_ilevabs5, &i_level->ilevabs5, filter, 5 );
  used_bits +=
      meas_im_fill_abs_iLevel( &i_level->v_ilevabs6, &i_level->ilevabs6, filter, 6 );
  used_bits +=
      meas_im_fill_abs_iLevel( &i_level->v_ilevabs7, &i_level->ilevabs7, filter, 7 );

#if !defined (NTRACE)

  meas_im_trace_i_level( filter, ( T_ilev* )i_level );
  
#endif /* #if !defined (NTRACE) */

  return( used_bits );
} /* meas_im_get_abs_i_level() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_set_carrier
+------------------------------------------------------------------------------
| Description : 
|
|            Frequency Band    config.       ETSI GSM spec.  coding used in L1
|            GSM 900           STD_900       1-124           1-124
|            E-GSM             STD_EGSM      1-124,          1-124,
|                                            975-1023, 0     125-174
|            PCS 1900          STD_1900      512-810         512-810
|            DCS 1800          STD_1800      512-885         512-885
|            GSM 900/DCS 1800  STD_DUAL      1-124,          1-124,
|                                            512-885         125-498
|            E-GSM/DCS 1800    STD_DUAL_EGSM 1-124,          1-124,
|                                            975-1023,0      125-174,
|                                            512-885         175-548
|            GSM 850           STD_850       128-251         128-251
|            GSM 850/PCS 1900  STD_DUAL_US   128-251,        1-124,
|                                            512-810         125-424
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_set_carrier ( T_MEAS_IM_CARRIER *carrier,
                                  T_p_frequency_par *freq_par )
{
  TRACE_FUNCTION( "meas_im_set_carrier" );

  if( freq_par->p_chan_sel.hopping )
  {
    UBYTE  i;
    UBYTE  bit_shift;
    USHORT array_idx;
    USHORT arfcn;
  
    carrier->hopping              = TRUE;
    carrier->alloc.hop_param.hsn  = ( freq_par->p_chan_sel.p_rf_ch.arfcn >> 8 );
    carrier->alloc.hop_param.maio = ( freq_par->p_chan_sel.p_rf_ch.arfcn & 0x00FF );

    memset( carrier->alloc.hop_param.arfcn_bit_field,
            0, MAX_IM_HOP_ARFCN_BIT_FIELD_SIZE );

    for( i = 0; i < freq_par->p_freq_list.p_rf_chan_cnt; i++ )
    {
      arfcn = freq_par->p_freq_list.p_rf_chan_no.p_radio_freq[i];
      
      switch( std )
      {
        case STD_1900: arfcn -= LOW_CHANNEL_1900; break;
        case STD_1800: arfcn -= LOW_CHANNEL_1800; break;
        default      :                            break;
      }

      array_idx =            arfcn / 8;
      bit_shift = ( UBYTE )( arfcn % 8 );

      if( array_idx < MAX_IM_HOP_ARFCN_BIT_FIELD_SIZE )
      {
        carrier->alloc.hop_param.arfcn_bit_field[array_idx] |= 
                                                         ( 0x01 << bit_shift );
      }
      else
      {
        TRACE_ERROR( "meas_im_set_carrier: array_idx >= MAX_IM_HOP_ARFCN_BIT_FIELD_SIZE" );
      }
    }
  }
  else
  {
    carrier->hopping     = FALSE;
    carrier->alloc.arfcn = freq_par->p_chan_sel.p_rf_ch.arfcn;
  }

#if !defined (NTRACE)
  
  if( grr_data->meas_im.n_im_trace & M_IM_TRACE_FREQUENCY )
  {
    if( carrier->hopping )
    {
      ULONG arfcn[4];
      ULONG freq[4];

      arfcn[0]  = ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[0]  <<  0;
      arfcn[0] |= ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[1]  <<  8;
      arfcn[0] |= ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[2]  << 16;
      arfcn[0] |= ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[3]  << 24;
      arfcn[1]  = ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[4]  <<  0;
      arfcn[1] |= ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[5]  <<  8;
      arfcn[1] |= ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[6]  << 16;
      arfcn[1] |= ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[7]  << 24;
      arfcn[2]  = ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[8]  <<  0;
      arfcn[2] |= ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[9]  <<  8;
      arfcn[2] |= ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[10] << 16;
      arfcn[2] |= ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[11] << 24;
      arfcn[3]  = ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[12] <<  0;
      arfcn[3] |= ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[13] <<  8;
      arfcn[3] |= ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[14] << 16;
      arfcn[3] |= ( ULONG )carrier->alloc.hop_param.arfcn_bit_field[15] << 24;
    
      freq[0]   = ( ULONG )freq_par->p_freq_list.p_rf_chan_no.p_radio_freq[0] << 16;
      freq[0]  |= ( ULONG )freq_par->p_freq_list.p_rf_chan_no.p_radio_freq[1] <<  0;
      freq[1]   = ( ULONG )freq_par->p_freq_list.p_rf_chan_no.p_radio_freq[2] << 16;
      freq[1]  |= ( ULONG )freq_par->p_freq_list.p_rf_chan_no.p_radio_freq[3] <<  0;
      freq[2]   = ( ULONG )freq_par->p_freq_list.p_rf_chan_no.p_radio_freq[4] << 16;
      freq[2]  |= ( ULONG )freq_par->p_freq_list.p_rf_chan_no.p_radio_freq[5] <<  0;
      freq[3]   = ( ULONG )freq_par->p_freq_list.p_rf_chan_no.p_radio_freq[6] << 16;
      freq[3]  |= ( ULONG )freq_par->p_freq_list.p_rf_chan_no.p_radio_freq[7] <<  0;


      TRACE_EVENT_P9( "meas_im_get_trns_freq: %08X%08X%08X%08X Num: %d Freq: %08X %08X %08X %08X",
                      arfcn[3], arfcn[2], arfcn[1], arfcn[0],
                      freq_par->p_freq_list.p_rf_chan_cnt,
                      freq[0],  freq[1],  freq[2],  freq[3] );
    }
    else
    {
      TRACE_EVENT_P1( "meas_im_get_trns_freq: %d", carrier->alloc.arfcn );
    }
  }

#endif /* #if !defined (NTRACE) */

} /* meas_im_set_carrier() */

/*
+------------------------------------------------------------------------------
| Function    : meas_prepare_and_start_idle
+------------------------------------------------------------------------------
| Description : ...
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_prepare_and_start_idle ( void ) 
{ 
  TRACE_FUNCTION( "meas_prepare_and_start_idle" );

  meas_im_cgrlc_int_level_req( TRUE );

  switch( GET_STATE( MEAS ) )
  {
    case MEAS_IDLE:
      if ( grr_data->meas_im.mode EQ IM_MODE_IDLE_TRANSFER OR
           grr_data->meas_im.mode EQ IM_MODE_IDLE             )
      {
        meas_im_prepare_idle( );

        switch( GET_STATE( MEAS_IM ) )
        {
          case MEAS_IM_NULL:
            {
              if( meas_im_start_idle( ) )
              {
                SET_STATE( MEAS_IM, MEAS_IM_START );
              }
            }
            break;

           default:
            /* do nothing */
            break;
        }
      }
      break;

    default:
      /* do nothing */
      break;
  }
} /* meas_prepare_and_start_idle() */

/*
+------------------------------------------------------------------------------
| Function    : meas_prepare_and_stop_idle
+------------------------------------------------------------------------------
| Description : ...
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_prepare_and_stop_idle ( void ) 
{ 
  TRACE_FUNCTION( "meas_prepare_and_stop_idle" );

  switch( GET_STATE( MEAS ) )
  {
    case MEAS_IDLE:
      {
        meas_im_prepare_idle( );
      }
      break;

    default:
      /* do nothing */
      break;
  }
} /* meas_prepare_and_stop_idle() */

/*==== SIGNAL FUNCTIONS =====================================================*/

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_start
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_START
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_start ( void ) 
{ 
  TRACE_ISIG( "sig_ctrl_meas_start" );
  
  /* process the extended measurement service */
  if( psc_db->is_ext_psi5_valid EQ TRUE )
  {
    sig_ctrl_meas_ext_valid_psi5( );
  }

  /* process the interference measurement service */
  sig_ctrl_meas_int_list_valid( );

} /* sig_ctrl_meas_start() */


/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_stop
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_STOP
|               
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_stop ( void ) 
{ 
  UBYTE state = GET_STATE( MEAS );

  TRACE_ISIG( "sig_ctrl_meas_stop" );
  
  /* process the interference measurement service */
  switch( state )
  {
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      {
        meas_im_stop_trns( );
        SET_STATE( MEAS_IM, MEAS_IM_NULL );
      }
      break;

    case MEAS_IDLE:
      {
        switch( GET_STATE( MEAS_IM ) )
        {
          case MEAS_IM_START:
            {
              meas_im_stop_idle( );

              SET_STATE( MEAS_IM, MEAS_IM_STOP_REQ ); 
            }
            break;

          case MEAS_IM_NULL:
            SET_STATE( MEAS_IM, MEAS_IM_NULL );
            break;

          default:
            TRACE_ERROR( "SIG_CTRL_MEAS_STOP unexpected INT MEAS 1" );
            break;
        }
      }
      break;

    default:
      /* do nothing */;
      break;
  }

  /* process the extended measurement service */
  switch( state )
  {
    case MEAS_NULL:
    case MEAS_IDLE:
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      switch( GET_STATE( MEAS_EM ) )
      {
        case MEAS_EM_REP_REQ:
          meas_em_stop_req( );
          break;

        case MEAS_EM_PMR_SENDING:
        case MEAS_EM_PENDING:
          SET_STATE( MEAS_EM, MEAS_EM_NULL );
          break;

        default:
          TRACE_ERROR( "SIG_CTRL_MEAS_STOP unexpected EXT MEAS 1" );
          break;
      }
      
      if( grr_t_status( T3178) NEQ 0 )
      {
         vsi_t_stop( GRR_handle, T3178);
         TRACE_EVENT( "Timer T3178 stopped" );
      }
      break;

    default:
     TRACE_ERROR( "SIG_CTRL_MEAS_STOP unexpected EXT MEAS 2" );
      break;
  }

  /* process the signal quality service */
  if( state EQ MEAS_TRANSFER )
  {
    RX_SetRxQual( RX_QUAL_UNAVAILABLE );
  }  

  SET_STATE( MEAS, MEAS_NULL );

} /* sig_ctrl_meas_stop() */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_suspend
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_SUSPEND
|               This signal suspends the measurement service
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_suspend ( void ) 
{ 
  TRACE_ISIG( "sig_ctrl_meas_suspend" );
  
  /* process the interference measurement service */
  switch( GET_STATE( MEAS ) )
  {
    case MEAS_IDLE:
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      {
        switch( GET_STATE( MEAS_IM ) )
        {
          case MEAS_IM_START:
            {
              meas_im_stop_idle( );

              grr_data->meas_im.trig_signal = IM_TRIG_SIGNAL_PAUSE;

              SET_STATE( MEAS_IM, MEAS_IM_STOP_REQ ); 
            }
            break;

          default:
            /* do nothing */
            break;
        }
      }
      break;

    default:
      /* do nothing */
      break;
  }

  /* process the extended measurement service */
  switch( GET_STATE( MEAS ) )
  {
    case MEAS_IDLE:
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      SET_STATE( MEAS_EM, MEAS_EM_SUSPEND );
    
      meas_em_process_t3178( );
      break;

    default:
      /* do nothing */
      break;
  }
} /* sig_ctrl_meas_suspend() */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_resume
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_RESUME
|               This signal resumes the measurement service
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_resume ( void ) 
{ 
  TRACE_ISIG( "sig_ctrl_meas_resume" );
  
  /* process the interference measurement service */
  switch( GET_STATE( MEAS ) )
  {
    case MEAS_IDLE:
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      if ( grr_data->meas_im.mode EQ IM_MODE_IDLE_TRANSFER OR
           grr_data->meas_im.mode EQ IM_MODE_IDLE             )
      {
        if( meas_im_start_idle( ) )
        {
          SET_STATE( MEAS_IM, MEAS_IM_START );
        }
        else
        {
          SET_STATE( MEAS_IM, MEAS_IM_NULL );
        }
        break;
      }
      break;

    default:
      /* do nothing */
      break;
  }

  /* process the extended measurement service */
  switch( GET_STATE( MEAS ) )
  {
    case MEAS_IDLE:
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      SET_STATE( MEAS_EM, MEAS_EM_NULL );
    
      meas_em_process_t3178( );
      break;

    default:
      /* do nothing */
      break;
  }

} /* sig_ctrl_meas_resume() */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_pim
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_PIM
|
| Parameters  : dummy - description of parameter dummy
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_pim ( void ) 
{ 
  UBYTE state = GET_STATE( MEAS );

  TRACE_ISIG( "sig_ctrl_meas_pim" );
  
  /* process the interference measurement service */
  switch( state )
  {
    case MEAS_TRANSFER:
      meas_im_state_changed( MEAS_IDLE );

      /*lint -fallthrough*/

    case MEAS_ACCESS:
      meas_im_stop_trns( );
      SET_STATE( MEAS_IM, MEAS_IM_NULL );
      if ( grr_data->meas_im.mode EQ IM_MODE_IDLE_TRANSFER OR
           grr_data->meas_im.mode EQ IM_MODE_IDLE             )
      {
        meas_im_prepare_idle( );
        
        if( meas_im_start_idle( ) )
        {
          SET_STATE( MEAS_IM, MEAS_IM_START );
        }
      }
      break;

    default:
      /* do nothing */
      break;
  }

  /* process the extended measurement service */
  switch( state )
  {
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      {
        if( GET_STATE( MEAS_EM ) EQ MEAS_EM_PENDING )
        {
          meas_em_start( );
          SET_STATE( MEAS_EM, MEAS_EM_REP_REQ );
        }
      }
      break;

    default:
      /* do nothing */
      break;
  }

  /* process the signal quality service */
  if( state EQ MEAS_TRANSFER )
  {
    RX_SetRxQual( RX_QUAL_UNAVAILABLE );
  }  

  SET_STATE( MEAS, MEAS_IDLE );

} /* sig_ctrl_meas_pim() */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_pam
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_PAM
|
| Parameters  : dummy - description of parameter dummy
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_pam ( void ) 
{ 
  UBYTE state = GET_STATE( MEAS );

  TRACE_ISIG( "sig_ctrl_meas_pam" );
  
  /* process the interference measurement service */
  switch( state )
  {
    case MEAS_IDLE:
      {
        switch( GET_STATE( MEAS_IM ) )
        {
          case MEAS_IM_START:
            {
              meas_im_stop_idle( );

              grr_data->meas_im.trig_signal = IM_TRIG_SIGNAL_PAM;

              SET_STATE( MEAS_IM, MEAS_IM_STOP_REQ ); 
            }
            break;

          case MEAS_IM_NULL:
            {
              if ( grr_data->meas_im.mode EQ IM_MODE_IDLE_TRANSFER OR
                   grr_data->meas_im.mode EQ IM_MODE_TRANSFER         )
              {
                meas_im_prepare_trns( );
                meas_im_start_trns( );

                SET_STATE( MEAS_IM, MEAS_IM_START );
              }
            }
            break;

          default:
            TRACE_ERROR( "SIG_CTRL_MEAS_PAM unexpected" );
            break;
        }
      }
      break;

    case MEAS_TRANSFER:
      meas_im_state_changed( MEAS_ACCESS );
      break;

    default:
      /* do nothing */
      break;
  }


  /* process the extended measurement service */
  switch( state )
  {
    case MEAS_IDLE:
      {
        switch( GET_STATE( MEAS_EM ) )
        {
          case MEAS_EM_REP_REQ:
            meas_em_stop_req( );
            SET_STATE( MEAS_EM, MEAS_EM_PENDING );
            break;

          default:
            /* do nothing */
            break;
        }
      }
      break;

    default:
      TRACE_ERROR( "SIG_CTRL_MEAS_PAM unexpected, EXT MEAS 2" );
      break;
  }

  /* process the signal quality service */
  if( state EQ MEAS_TRANSFER )
  {
    RX_SetRxQual( RX_QUAL_UNAVAILABLE );
  }  

  SET_STATE( MEAS, MEAS_ACCESS );

} /* sig_ctrl_meas_pam() */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_ptm
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_PTM
|               
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_ptm ( void )
{ 
  TRACE_ISIG( "sig_ctrl_meas_ptm" );

  switch( GET_STATE( MEAS ) )
  {
    case MEAS_IDLE:
    case MEAS_ACCESS:
      meas_im_state_changed( MEAS_TRANSFER );
      break;

    default:
      /* do nothing */
      break;
  }
  
  SET_STATE( MEAS, MEAS_TRANSFER );

} /* sig_ctrl_meas_ptm() */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_int_list_invalid
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_INT_LIST_INVALID
|               If this signal is received then the list for interfrence
|               measurements are invalid
|               and interference measurements shall be stopped, if running
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_int_list_invalid ( void ) 
{ 
  TRACE_ISIG( "sig_ctrl_meas_int_list_invalid" );
  
  meas_prepare_and_stop_idle( );
} /* sig_ctrl_meas_int_list_invalid() */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_int_list_valid
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_INT_LIST_VALID
|               If this signal is received then the list for interfrence
|               measurements are valid
|               and interference measurements could be started, refreshed etc.
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_int_list_valid ( void ) 
{ 
  TRACE_ISIG( "sig_ctrl_meas_int_list_valid" );
  
  meas_prepare_and_start_idle( );

} /* sig_ctrl_meas_int_list_valid() */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_ext_invalid_psi5
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_EXT_INVALID_PSI5
|               If this signal is received then the list for extended
|               measurements are invalid
|               and interference measurements could be stopped, if already running
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_ext_invalid_psi5 ( void ) 
{ 
  TRACE_ISIG( "sig_ctrl_meas_ext_invalid_psi5" );
  
  switch( GET_STATE( MEAS ) )
  {
    case MEAS_NULL:
    case MEAS_IDLE:
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      if( !meas_em_is_valid_pmo_present( ) )
      {
        meas_em_valid_psi5( );

        switch( GET_STATE( MEAS_EM ) )
        {
          case MEAS_EM_REP_REQ:
            meas_em_stop_req( );
            break;

          default:
            SET_STATE( MEAS_EM, MEAS_NULL );
            break;
        }
      }
      break;

    default:
      TRACE_ERROR( "SIG_CTRL_MEAS_EXT_INVALID_PSI5 unexpected" );
      break;
  }
} /* sig_ctrl_meas_ext_invalid_psi5() */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_ext_valid_psi5
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_EXT_VALID_PSI5
|               If this signal is received then the list for extended
|               measurements are valid
|               and interference measurements could performed
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_ext_valid_psi5 ( void ) 
{ 
  TRACE_ISIG( "sig_ctrl_meas_ext_valid_psi5" );
  

  switch( GET_STATE( MEAS ) )
  {
    case MEAS_IDLE:
      if( !meas_em_is_valid_pmo_present( ) )
      {
        switch( GET_STATE( MEAS_EM ) )
        {
          case MEAS_EM_REP_REQ:
            meas_em_stop_req( );
            
            /*lint -fallthrough*/
          
          case MEAS_EM_NULL:
            meas_em_valid_psi5( );
            meas_em_process_t3178( );
            break;    
          default:
            TRACE_ERROR( "SIG_CTRL_MEAS_EXT_VALID_PSI5 unexpected 1" );
            break;
        }
      }
      break;

    case MEAS_NULL:
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      if( !meas_em_is_valid_pmo_present( ) )
      {
        /* measurement report parameters of PSI5 shall only be taken into */
        /* account in case there is no individually parameter set send to */
        /* the MS using a Packet Measurement Order message                */
        meas_em_valid_psi5( );
        meas_em_process_t3178( );
      }
      break;
    
    default:
      TRACE_ERROR( "SIG_CTRL_MEAS_EXT_VALID_PSI5 unexpected 2" );
      break;
  }

} /* sig_ctrl_meas_ext_valid_psi5() */

/*
+------------------------------------------------------------------------------
| Function    : sig_cs_meas_start
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CS_MEAS_START
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_cs_meas_start ( void ) 
{ 
  TRACE_ISIG( "sig_cs_meas_start" );
  
  grr_data->meas_im.v_cs_meas_active = TRUE;
  
  meas_prepare_and_start_idle( );

} /* sig_cs_meas_start() */

/*
+------------------------------------------------------------------------------
| Function    : sig_cs_meas_stop
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CS_MEAS_STOP
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_cs_meas_stop ( void ) 
{ 
  TRACE_ISIG( "sig_cs_meas_stop" );
  
  grr_data->meas_im.v_cs_meas_active = FALSE;

  meas_prepare_and_stop_idle( );

} /* sig_cs_meas_stop() */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_pmr_accept
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_PMR_ACCEPT
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_pmr_accept ( void ) 
{ 
  TRACE_ISIG( "sig_ctrl_meas_pmr_accept" );

  switch( GET_STATE( MEAS_EM ) )
  {
    case( MEAS_EM_PMR_SENDING ):
      if( meas_em_send_meas_rpt( FALSE ) EQ FALSE )
      {
        SET_STATE( MEAS_EM, MEAS_EM_NULL );
  
        meas_em_process_t3178( );
      }
      break;

    default:
      TRACE_ERROR( "SIG_CTRL_MEAS_PMR_ACCEPT unexpected" );
      break;
  }

} /* sig_ctrl_meas_pmr_accept() */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_pmr_reject
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CTRL_MEAS_PMR_REJECT
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_pmr_reject ( void ) 
{ 
  TRACE_ISIG( "sig_ctrl_meas_pmr_reject" );

  switch( GET_STATE( MEAS_EM ) )
  {
    case( MEAS_EM_PMR_SENDING ):
      SET_STATE( MEAS_EM, MEAS_EM_NULL );

      meas_em_process_t3178( );
      break;

    default:
      TRACE_ERROR( "SIG_CTRL_MEAS_PMR_REJECT unexpected" );
      break;
  }

} /* sig_ctrl_meas_pmr_reject() */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_ext_meas_cnf
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_ext_meas_cnf 
                                   ( T_RRGRR_EXT_MEAS_CNF *rrgrr_ext_meas_cnf )
{ 
  TRACE_ISIG( "sig_ctrl_meas_ext_meas_cnf" );

  switch( GET_STATE( MEAS ) )
  {
    case MEAS_IDLE:
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      switch( GET_STATE( MEAS_EM ) )
      {
        case( MEAS_EM_REP_REQ ):
          if( meas_em_store_rslt( rrgrr_ext_meas_cnf ) EQ TRUE )
          {
            SET_STATE( MEAS_EM, MEAS_EM_PMR_SENDING );

            if( meas_em_send_meas_rpt( TRUE ) EQ FALSE )
            {
              /*
               * The additional state check is necessary because signals
               * might be send during the processing of the function 
               * meas_em_send_meas_rpt.
               */
              if( GET_STATE( MEAS_EM ) EQ MEAS_EM_PMR_SENDING )
              {
                SET_STATE( MEAS_EM, MEAS_NULL );
  
                meas_em_process_t3178( );
              }
            }
          }
          else
          {
            SET_STATE( MEAS_EM, MEAS_NULL );
  
            meas_em_process_t3178( );
          }
          break;

        default:
          TRACE_EVENT( "SIG_CTRL_MEAS_EXT_MEAS_CNF unexpected 1" );
          break;
      }
      break;

    default:
      TRACE_EVENT( "SIG_CTRL_MEAS_EXT_MEAS_CNF unexpected 2" );
      break;
  }
} /* sig_ctrl_meas_ext_meas_cnf() */



/*
+------------------------------------------------------------------------------
| Function    : sig_gfp_meas_order
+------------------------------------------------------------------------------
| Description : Handles the signal SIG_GFP_MEAS_ORDER
|
| Parameters  : -
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_gfp_meas_order ( void )
{ 
  MCAST( d_meas_order, D_MEAS_ORDER );
  TRACE_ISIG( "sig_gfp_meas_order" );
  
  if (grr_data->nc2_on)
  {
    meas_p_meas_order_ind(d_meas_order);
  }
  else
  {
    TRACE_EVENT( "PACKET MEASUREMENT ORDER RECEIVED,but NC2 is deactivated" );
  }


} /* sig_gfp_meas_order() */

 

/*
+------------------------------------------------------------------------------
| Function    : sig_gfp_meas_int_meas_stop_con
+------------------------------------------------------------------------------
| Description : Handles the signal SIG_GFP_MEAS_INT_MEAS_STOP_CON
|
| Parameters  : *dummy - Ptr to primitive payload
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_gfp_meas_int_meas_stop_con ( T_MPHP_INT_MEAS_STOP_CON * dummy )
{ 
  TRACE_ISIG( "sig_gfp_meas_int_meas_stop_con" );
  
  switch( GET_STATE( MEAS ) )
  {
    case MEAS_NULL:
    case MEAS_IDLE:
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      {
        switch( GET_STATE( MEAS_IM ) )
        {
          case MEAS_IM_STOP_REQ:
            {
              if( grr_data->meas_im.trig_signal EQ IM_TRIG_SIGNAL_PAM )
              {
                meas_im_prepare_trns( );
              }

              SET_STATE( MEAS_IM, MEAS_IM_NULL );

              grr_data->meas_im.trig_signal = IM_TRIG_SIGNAL_NULL;
            }
            break;

          default:
            TRACE_ERROR( "SIG_GFP_MEAS_INT_MEAS_STOP_CON unexpected 1" );
            break;
        }
      }
      break;
      
    default:
      TRACE_ERROR( "SIG_GFP_MEAS_INT_MEAS_STOP_CON unexpected 2" );
      break;
  }

} /* sig_gfp_meas_int_meas_stop_con() */

/*
+------------------------------------------------------------------------------
| Function    : sig_gfp_meas_int_meas_ind
+------------------------------------------------------------------------------
| Description : Handles the signal sig_gfp_meas_int_meas_ind
|
| Parameters  : *mphp_int_meas_ind - Ptr to primitive payload
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_gfp_meas_int_meas_ind ( T_MPHP_INT_MEAS_IND *mphp_int_meas_ind )
{ 
  UBYTE state = GET_STATE( MEAS );

  TRACE_ISIG( "sig_gfp_meas_int_meas_ind" );

  switch( state )
  {
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      meas_im_new_value( mphp_int_meas_ind, state );
      break;

    case MEAS_IDLE:
      {
        switch( GET_STATE( MEAS_IM ) )
        {
          case MEAS_IM_START:
            meas_im_new_value( mphp_int_meas_ind, state );
            break;

          case MEAS_IM_STOP_REQ:
            /* do nothing */
            break;

          default:
            TRACE_ERROR( "SIG_GFP_MEAS_INT_MEAS_IND unexpected 1" );
            break;
        }
      }
      break;

    default:
      TRACE_ERROR( "SIG_GFP_MEAS_INT_MEAS_IND unexpected 2" );
      break;
  }
} /* sig_gfp_meas_int_meas_ind() */

#if !defined (NTRACE)

/*
+------------------------------------------------------------------------------
| Function    : meas_im_trace_i_level
+------------------------------------------------------------------------------
| Description :
|
| Parameters  :
|
+------------------------------------------------------------------------------
*/
LOCAL void meas_im_trace_i_level( T_MEAS_IM_FILTER *filter, 
                                  T_ilev           *i_level )
{ 
  TRACE_ISIG( "meas_im_trace_i_level" );

  if( grr_data->meas_im.n_im_trace & M_IM_TRACE_OUTPUT_VALUE )
  {
    if( filter NEQ NULL )
    {
      TRACE_EVENT_P8( "meas_im_trace_i_level: %02X %02X %02X %02X %02X %02X %02X %02X",
                      i_level->ilev0, i_level->ilev1, i_level->ilev2,
                      i_level->ilev3, i_level->ilev4, i_level->ilev5,
                      i_level->ilev6, i_level->ilev7 );
    }
    else
    {
      TRACE_EVENT( "meas_im_trace_i_level: filter EQ NULL" );
    }
  }
} /* meas_im_trace_i_level() */
  
#endif /* #if !defined (NTRACE) */

/*
+------------------------------------------------------------------------------
| Function    : sig_ctrl_meas_ba_changed
+------------------------------------------------------------------------------
| Description : Handles the signal SIG_CTRL_MEAS_BA_CHANGED
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_ctrl_meas_ba_changed ( void )
{ 
  TRACE_ISIG( "sig_ctrl_meas_ba_changed" );

  switch( GET_STATE( MEAS ) )
  {
    case MEAS_IDLE:
    case MEAS_ACCESS:
    case MEAS_TRANSFER:
      psc_db->nc_ms.ncmeas.list.number = 0;
      psc_db->nc_ms.rfreq.number       = 0;

      psc_db->nc_ms.ncmeas.list.chng_mrk.curr++;
      break;

    default:
      TRACE_ERROR( "SIG_CTRL_MEAS_BA_CHANGED unexpected" );
      break;
  }
} /* sig_ctrl_meas_ba_changed() */

/*
+------------------------------------------------------------------------------
| Function    : sig_gfp_meas_rxlev_pccch_ind
+------------------------------------------------------------------------------
| Description : Handles the signal SIG_GFP_MEAS_RXLEV_PCCCH_IND
|
| Parameters  : pccch_lev - signal level received on pccch
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_gfp_meas_rxlev_pccch_ind( UBYTE pccch_lev )
{ 
  TRACE_ISIG( "sig_gfp_meas_rxlev_pccch_ind" );
  
  switch( GET_STATE( MEAS ) )
  {
    case MEAS_IDLE:
    case MEAS_ACCESS:
      meas_c_val_update_pim( pccch_lev );
      grr_cgrlc_pwr_ctrl_req( TRUE );
      break;

    default:
      TRACE_ERROR( "SIG_GFP_MEAS_RXLEV_PCCCH_IND unexpected" );
      break;
  }
} /* sig_gfp_meas_rxlev_pccch_ind() */

/*
+------------------------------------------------------------------------------
| Function    : sig_gfp_meas_ctrl_pwr_ta_ptm
+------------------------------------------------------------------------------
| Description : Handles the signal SIG_GFP_MEAS_CTRL_PWR_TA_PTM
|
| Parameters  : -
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_gfp_meas_ctrl_pwr_ta_ptm ( void )
{ 
  MCAST( d_ctrl_pwr_ta, D_CTRL_PWR_TA );

  TRACE_ISIG( "sig_gfp_meas_ctrl_pwr_ta_ptm" );
  
  switch( GET_STATE( MEAS ) )
  {
    case MEAS_TRANSFER:
      if( d_ctrl_pwr_ta->v_gpta )
      {
        sig_meas_tc_update_ta_req( );
      }

      {
        UBYTE pb;
        
        pb = psc_db->g_pwr_par.pb;
        
        meas_handle_pwr_par( );
        
        if( pb NEQ psc_db->g_pwr_par.pb )
        {
          grr_update_pacch();
        }
      }
      break;

    default:
      TRACE_ERROR( "SIG_GFP_MEAS_CTRL_PWR_TA_PTM unexpected" );
      break;
  }
} /* sig_gfp_meas_ctrl_pwr_ta_ptm() */

/*
+------------------------------------------------------------------------------
| Function    : sig_tc_meas_update_pch
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_tc_meas_update_pch ( void )
{ 
  TRACE_ISIG( "sig_tc_meas_update_pch" );

  grr_cgrlc_pwr_ctrl_req( FALSE );

} /* sig_tc_meas_update_pch() */

/*
+------------------------------------------------------------------------------
| Function    : meas_c_get_value
+------------------------------------------------------------------------------
| Description : This function returns the current C value.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE meas_c_get_value ( void )
{
  UBYTE c_value;

  TRACE_FUNCTION( "meas_c_get_value" );

  if( grr_data->meas.c_filter.index > 0 )
  {
    c_value = ( M_ROUND_UP( grr_data->meas.c_filter.value, MEAS_ACRCY ) );
  }
  else
  {

#ifdef _SIMULATION_

    TRACE_ERROR( "meas_c_get_value: grr_data->meas.c_filter.index EQ 0" );

#endif /* #ifdef _SIMULATION_ */

    c_value = C_VALUE_DEFAULT;
  }

  return( c_value );

} /* meas_c_get_value() */

/*
+------------------------------------------------------------------------------
| Function    : meas_c_get_c_value
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_c_get_c_value ( T_CGRLC_c_value *c_value )
{
  TRACE_FUNCTION( "meas_c_get_c_value" );

  c_value->c_acrcy = MEAS_ACRCY;
  c_value->c_lev   = grr_data->meas.c_filter.value;
  c_value->c_idx   = grr_data->meas.c_filter.index;

} /* meas_c_get_c_value() */

/*
+------------------------------------------------------------------------------
| Function    : meas_c_set_c_value
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_c_set_c_value ( T_CGRLC_c_value *c_value )
{
  TRACE_FUNCTION( "meas_c_set_c_value" );

  grr_data->meas.c_filter.value = ( c_value->c_lev * MEAS_ACRCY ) / 
                                    c_value->c_acrcy;

  grr_data->meas.c_filter.index = c_value->c_idx;

} /* meas_c_set_c_value() */