/*
***********************************************************************
*
* Copyright (C) 1999 Ericsson Radio Systems AB
* 
* The Association of Radio Industries and Businesses (ARIB) has the
* licence to reproduce, distribute and publish the Bit Exact C Code
* programs in this CD-ROM together with the other parts of the RCR
* STD-27 (Personal Digital Cellular Telecommunication System)
* specification.
* 
* Ericsson has declared Option 1 (royalty-free licence) to ARIB for
* its Essential Industrial Property Rights related to the ACELP
* specification and the Bit Exact C Code programs. The royalty-free
* licence is limited to the development and manufacturing of
* products complying with the RCR STD-27H specification (or
* subsequent versions) for sale and use in Japan. Copying of the
* program(s) for any other purpose requires the prior written
* permission from Ericsson.
* 
* The user of the Bit Exact C Code hereby acknowledges the
* following:
* 
* 1.  Ericsson does not provide the user with any warranties,
*     whether express or implied, including but not limited to
*     warranties of merchantability and fitness for a particular
*     purpose relating to the Bit Exact C Code.
* 
* 2.  Ericsson shall have no responsibility whatsoever to indemnify
*     the user against actions or claims for infringement of any
*     intellectual property rights, e.g. patents, copyrights,
*     registered designs or any other rights, by reason of the
*     user's use of the Bit Exact C Code.
* 
***********************************************************************
*/

/*************************************************************************
 *
 *   FUNCTION:  vox_tx_handler()
 *              State machine for vox in PDCEFR
 *
 *    vox_state has the following values :
 *       0 = normal speech
 *       1 = POST0
 *       2 = POST1
 *       3 = PRE
 *       4 = No transmission
 *    
 *    vox_frame_type has the following values :
 *       0 = normal speech frame or POST1 frame
 *       1 = POST0
 *       2 = PRE
 *       3 = No transmission
 *    
 *
 *
 *************************************************************************/

#include "typedef.h"
#include "basic_op.h"
#include "codec.h"
#include <stdio.h>

Word16 vox_frames = 0;
Word16 since_last_sid = 0;
Word16 sid_update_rate = 50;
Word16 vox_elapsed_sp_frames = 20;
Word16 vox_vad_hangover = 0;
Word16 vox_average_ok  = 0;                                       
Word16 prev_vox_avg_ok  = 0;                                    


Word16 vox_tx_handler (
    Word16 *vox_state,      /* i/o: input VOX state     */ 
    Word16 vad,             /* i  : Voice Activity Flag */ 
    Word16 *vox_frame_type  /* o  : Frame type          */
)
{
   Word16 sp_flag = 1;
   if (vad) {
      vox_elapsed_sp_frames = add(vox_elapsed_sp_frames,1);
      vox_vad_hangover = 0;
   } else {
      vox_vad_hangover = add(vox_vad_hangover,1);
      if (vox_elapsed_sp_frames < 20 || vox_vad_hangover > 8) {
         sp_flag = 0;
         vox_elapsed_sp_frames = 0;
      }
   }
      
   /* first VOX-update counter */ 
   if(sp_flag){                        
      vox_frames = 0;                  
   } else {                            
      vox_frames = add(vox_frames,1);  
   }  
   /* VOX averaging state handling  */     
   prev_vox_avg_ok = vox_average_ok;   
   if(vox_vad_hangover > 8){           
      vox_average_ok = 1;              
   } else {                            
      vox_average_ok = 0; 
   }

   switch (*vox_state) {
   case 0: /* Speech */
      if (sp_flag) {
         *vox_state = 0;
         *vox_frame_type = 0;
      } else {
         *vox_state = 1;
         *vox_frame_type = 1;
         reset_cod_states();
      }
      since_last_sid = 0;
      break;
   case 1: /* POST0 */
      *vox_state = 2;
      *vox_frame_type = 0;
      since_last_sid = 0;
      break;
   case 2: /* POST1 */
      since_last_sid = add(since_last_sid,1);
      if (sp_flag) {
         *vox_state = 3;
         *vox_frame_type = 2;
      } else {
         *vox_state = 4;
         *vox_frame_type = 3; /* no transmission */
      }
      break;
   case 3:  /* PRE */
      if (sp_flag) {
         *vox_state = 0;
         *vox_frame_type = 0;
         since_last_sid = add(since_last_sid,1);
         reset_cod_states();
      } else {
         *vox_state = 1;
         *vox_frame_type = 1;
      }
      break;
   case 4:  /* no TX */
      since_last_sid = add(since_last_sid,1);
      if (sp_flag) {
         *vox_state = 3;
         *vox_frame_type = 2;
      } else {
         if (add(since_last_sid,1) == sid_update_rate || vox_frames == 9) {
            *vox_state = 1;
            *vox_frame_type = 1;
         } else {
            *vox_state = 4;
            *vox_frame_type = 3; // no transmission
         }
      }
      break;
   }
   return 0;

}
