/* **********************************************************************
 * *                                                                    * 
 * *       Generic Simulator of a Serial Radar/Antenna Controller       *
 * *                                                                    * 
 * **********************************************************************
 * File: libs/antenna/iantsim_pwrp.c
 * 
 * COPYRIGHT (c) 1987, 1988, 1991, 1996, 1997, 1999, 2000, 2001, 2002,
 *                        2003, 2004, 2005 BY 
 *          SIGMET INCORPORATED, WESTFORD MASSACHUSETTS, U.S.A.  
 * 
 * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
 * ONLY  IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
 * INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE  OR  ANY OTHER
 * COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
 * OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
 * TRANSFERED. 
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sigtypes.h"
#include "setup.h"
#include "dsp.h"
#include "antenna_lib.h"
#include "antenna_int.h"
#include "config_lib.h"
#include "user_lib.h"

#include "antsim_global.h"

static MESSAGE antsim_init_always(void);
static MESSAGE antsim_init_first(void);

MESSAGE iantsim_pwrp( )
{
  return( iantsim_pwrp_opt( 0 ) ) ;
}

/* ------------------------------
 * Simulate one of several styles of serial Radar/Antenna controller.
 *
 * Version of iant_sim_pwrp() that supports obscure options.  Saves the
 * trouble of editing dozens of calls to iant_sim_pwrp() when only special
 * purpose needs are being addressed.
 */
MESSAGE iantsim_pwrp_opt( UINT2 lauto_a )
{
  UINT2 lcreated ; MESSAGE istatus ; SINT4 icount ;
  char spath[PATHNAME_SIZE], *psdirectory ;
      
  /* Create and map the global section
   */
  istatus = antsim_global_init( &lcreated );
  if( istatus != SS_NORMAL ) return istatus;

  /* Reload the antenna simulator configuration file.  This is the
   * same file that is used to configure the antenna driver itself.
   */
  istatus = ant_load_setup(NULL, &pantsim_c->setup ) ;
  if ( istatus != SS_NORMAL ) return istatus ;

  /* Check that the antenna type is valid
   */
  switch (pantsim_c->setup.icontrol_format)
    {
    case ANTFMT_XMTVOID:
    case ANTFMT_XMT01:
    case ANTFMT_XMT02:
    case ANTFMT_XMT04:
    case ANTFMT_XMT05:
      switch (pantsim_c->setup.istatus_format)
	{
	case ANTFMT_RCVVOID:
	case ANTFMT_RCV01:
	case ANTFMT_RCV02:
	case ANTFMT_RCV03:
	case ANTFMT_RCV04:
	case ANTFMT_RCV05:
	  break;

	default:
	  return ANT_BAD_STATUS;
	  break;
	}
      break;

    default:
      return ANT_BAD_CONTROL;
      break;
    }
  istatus = antsim_init_always();
  if ( istatus != SS_NORMAL ) return istatus;

  /* We are finished now if the global section was already there, and all the
   * desired processes also report a valid status.
   */
  if ( !lcreated )
    {
      return SS_NORMAL;
    }

  /* - - - - - - - - - - - - - - - - - - - - -
   * Here we start the parallel processes:
   */
  istatus = antsim_init_first( );
  if ( istatus != SS_NORMAL ) return istatus;

  pantsim_c->info.lauto = lauto_a ;

  psdirectory = getenv( "IRIS_BIN" );
  
  /* Startup the receive process and wait up to 5 seconds for it to
   * start.
   */
  pantsim_c->info.ircv_status = 0 ;
  strcpy( spath, psdirectory ) ; strcat( spath, "antsim_rcv" ) ;
  istatus = sig_fork_daemon( spath, "ANTSIM_RCV" ) ;
  if( istatus != SS_NORMAL ) return istatus;

  icount = 0;
  while( 0 == pantsim_c->info.ircv_status ) 
    {
      if( icount++ > 100 ) return iMessageMod_va( USER_PROCESS_START, 1, "antsim_rcv" );
      sig_microSleep( 50000 ) ;
    }
  if ( pantsim_c->info.ircv_status != SS_NORMAL )
    return pantsim_c->info.ircv_status;

  /* Startup the transmit process and wait up to 5 seconds for it to
   * start.
   */
  pantsim_c->info.ixmt_status = 0;
  strcpy( spath, psdirectory ) ; strcat( spath, "antsim_xmt" ) ;
  istatus = sig_fork_daemon( spath, "ANTSIM_XMT" ) ;
  if( istatus != SS_NORMAL ) return istatus;

  icount = 0;
  while( 0 == pantsim_c->info.ixmt_status ) 
    {
      if( icount++ > 100 ) return iMessageMod_va( USER_PROCESS_START, 1, "antsim_xmt" );
      sig_microSleep( 50000 ) ;
    }
  if (pantsim_c->info.ixmt_status != SS_NORMAL )
    return pantsim_c->info.ixmt_status;

  return SS_NORMAL;
}

/* ------------------------------
 * Initialize antenna parameters in preparation for running the internal
 * simulator.
 * History:
 *     jmh   14 Nov 1991   Added initialization of the masks
 *     jmh   18 Oct 1991   Removed antenna structure argument
 */
static MESSAGE antsim_init_always( )
{
  UINT4 itemp_mask;
  MESSAGE istatus;

  /* Convert the manual setup structure into a more easily used format
   */
  itemp_mask = 0;
  if (pantsim_c->setup.cont_servo_power.lenabled) itemp_mask |= ACF_SERVO;
  if (pantsim_c->setup.cont_radiate.lenabled)     itemp_mask |= ACF_RADIATE;
  if (pantsim_c->setup.cont_tr_power.lenabled)    itemp_mask |= ACF_TRPOWER;
                                                  itemp_mask |= ACF_IRIS;
  if (pantsim_c->setup.cont_reset.lenabled)       itemp_mask |= ACF_RESET;
                                                  itemp_mask |= ACF_AUTO_RAD;
  if (pantsim_c->setup.cont_noise.lenabled)       itemp_mask |= ACF_NOISE;
  if (pantsim_c->setup.cont_siggen.lenabled)      itemp_mask |= ACF_SIGGEN;
  if (pantsim_c->setup.cont_sigcw.lenabled)       itemp_mask |= ACF_SIGCW;
  if (pantsim_c->setup.cont_pwbw.lenabled)        itemp_mask |= ACF_PWBW;
  if (pantsim_c->setup.cont_pw_unset.lenabled)    itemp_mask |= ACF_PW_UNSET;
  if (pantsim_c->setup.cont_nst.lenabled)         itemp_mask |= ACF_NST;
  if (pantsim_c->setup.cont_polar.lenabled)       itemp_mask |= ACF_POLAR;

  pantsim_c->info.ic_mask = itemp_mask;

  itemp_mask = 0;
  if (pantsim_c->setup.status_low_airflow.lenabled)    itemp_mask |= ASF_LOWAIRFLOW;
  if (pantsim_c->setup.status_low_wgp.lenabled)        itemp_mask |= ASF_LOW_WGP;
  if (pantsim_c->setup.status_interlock_open.lenabled) itemp_mask |= ASF_INTERLOCK;
  if (pantsim_c->setup.status_standby.lenabled)        itemp_mask |= ASF_STANDBY;
  if (pantsim_c->setup.status_radiate.lenabled)        itemp_mask |= ASF_RADIATE;
  if (pantsim_c->setup.status_mag_current.lenabled)    itemp_mask |= ASF_MAGTFLT;
  if (pantsim_c->setup.status_local.lenabled)          itemp_mask |= ASF_LOCAL;
  if (pantsim_c->setup.status_trlocal.lenabled)        itemp_mask |= ASF_TRLOCAL;
  if (pantsim_c->setup.status_servo_power.lenabled)    itemp_mask |= ASF_SERVO;
  if (pantsim_c->setup.status_tr_power.lenabled)       itemp_mask |= ASF_TRPOWER;
  if (pantsim_c->setup.status_shutdown.lenabled)       itemp_mask |= ASF_SHUTDOWN;
  if (pantsim_c->setup.status_sigfault.lenabled)       itemp_mask |= ASF_SIGFAULT;
  if (pantsim_c->setup.status_siggen.lenabled)         itemp_mask |= ASF_SIGGEN;
  if (pantsim_c->setup.status_sigcw.lenabled)          itemp_mask |= ASF_SIGCW;
  if (pantsim_c->setup.status_pwbw.lenabled)           itemp_mask |= ASF_PWBW;
  if (pantsim_c->setup.status_polar.lenabled)          itemp_mask |= ASF_POLAR;

  pantsim_c->info.is_mask = itemp_mask;
  pantsim_c->info.lwe_should_reset = FALSE;

  pantsim_c->bitex.iunit_cnt = 2;
  pantsim_c->bitex.ifield_cnt = 4;
  pantsim_c->bitex.units[0].iunit_id = 0x10;
  pantsim_c->bitex.units[1].iunit_id = 0x11;
  pantsim_c->bitex.units[2].iunit_id = 0x12;
  pantsim_c->bitex.units[3].iunit_id = 0x13;
  pantsim_c->bitex.units[0].iunit_length = 13;
  pantsim_c->bitex.units[1].iunit_length = 18;
  pantsim_c->bitex.units[2].iunit_length = 13;
  pantsim_c->bitex.units[3].iunit_length = 13;
  pantsim_c->bitex.units[0].lcontrol_unit = FALSE ;
  pantsim_c->bitex.units[1].lcontrol_unit = FALSE ;
  pantsim_c->bitex.units[2].lcontrol_unit = FALSE ;
  pantsim_c->bitex.units[3].lcontrol_unit = FALSE ;
  pantsim_c->bitex.units[0].lQBite = FALSE ;
  pantsim_c->bitex.units[1].lQBite = TRUE ;
  pantsim_c->bitex.units[2].lQBite = FALSE ;
  pantsim_c->bitex.units[3].lQBite = FALSE ;

  /* Fills in example Q-BITE case only */
  pantsim_c->bitex.fields[0].ldisabled = FALSE;
  pantsim_c->bitex.fields[0].iunit = 1;
  pantsim_c->bitex.fields[0].ibyte = 2;
  pantsim_c->bitex.fields[0].ibit  = 1;

  pantsim_c->bitex.fields[1].ldisabled = FALSE;
  pantsim_c->bitex.fields[1].iunit = 1;
  pantsim_c->bitex.fields[1].ibyte = 3;
  pantsim_c->bitex.fields[1].ibit  = 2;

  pantsim_c->bitex.fields[2].ldisabled = FALSE;
  pantsim_c->bitex.fields[2].iunit = 1;
  pantsim_c->bitex.fields[2].ibyte = 5;
  pantsim_c->bitex.fields[2].ibit  = 3;

  pantsim_c->bitex.fields[3].ldisabled = FALSE;
  pantsim_c->bitex.fields[3].iunit = 1;
  pantsim_c->bitex.fields[3].ibyte = 8;
  pantsim_c->bitex.fields[3].ibit  = 4;

  pantsim_c->bitex.fields[4].ldisabled = FALSE;
  pantsim_c->bitex.fields[4].iunit = 1;
  pantsim_c->bitex.fields[4].ibyte = 12;
  pantsim_c->bitex.fields[4].ibit  = 5;

  /* Enlarge the acceleration limits and elevation limit angles
   * slightly from the definitions used by the antenna driver
   * itself.
   */
  pantsim_c->setup.fazvelmax *= 1.2 ;
  pantsim_c->setup.felvelmax *= 1.2 ;
  pantsim_c->setup.ielmin    -= iBin2FromFDeg( 5.0 ) ;
  pantsim_c->setup.ielmax    += iBin2FromFDeg( 5.0 ) ;

  /* Set flag indicating whether a dual system RCP is configured
   */
  switch( pantsim_c->setup.istatus_format ) {
  case ANTFMT_RCV05:
    pantsim_c->info.drcp.lSetupDual = TRUE  ; break ;
  default:
    pantsim_c->info.drcp.lSetupDual = FALSE ; break ;
  }

  istatus = SS_NORMAL;

  return istatus;
}

/* ------------------------------
 * Initialize antenna parameters in preparation for running the internal
 * simulator.
 * History:
 *     jmh   9 Sep 1991   Removed antenna structure argument
 */
static MESSAGE antsim_init_first( )
{
  pantsim_c->info.ixmt_status = 0;
  pantsim_c->info.ircv_status = 0;
  pantsim_c->info.iazmode   = ANTMODE_STOP;
  pantsim_c->info.ielmode   = ANTMODE_STOP;

  pantsim_c->info.iaz       = 0;
  pantsim_c->info.idaz      = 0;
  pantsim_c->info.iel       = 0;
  pantsim_c->info.idel      = 0;
      
  pantsim_c->info.fazv      = 0.;
  pantsim_c->info.fdazv     = 0.;
  pantsim_c->info.felv      = 0.;
  pantsim_c->info.fdelv     = 0.;

  pantsim_c->info.itr_order  = 0;
  pantsim_c->info.iel_order  = 0;
  pantsim_c->info.ipitch     = 0;
  pantsim_c->info.fpitchv    = 0.0;
  pantsim_c->info.iroll      = 0;
  pantsim_c->info.frollv     = 0.0;
  pantsim_c->info.iheading   = 0;
  pantsim_c->info.fheadingv  = 0.0;
  pantsim_c->info.ilatitude  = pantsim_c->setup.ilat;
  pantsim_c->info.ilongitude = pantsim_c->setup.ilon;
  pantsim_c->info.faltitude  = (FLT4)(pantsim_c->setup.ignd_hgt+pantsim_c->setup.irad_hgt);
  pantsim_c->info.fvel_east  = 0.0;
  pantsim_c->info.fvel_north = 0.0;
  pantsim_c->info.fvel_up    = 0.0;
  pantsim_c->info.fsim_rock_pitch   = 0.0;
  pantsim_c->info.fsim_rock_roll    = 0.0;
  pantsim_c->info.fsim_rock_heading = 0.0;
  pantsim_c->info.fsim_rock_phase   = 0.0;
  pantsim_c->info.fsim_tilt_pitch   = 0.0;
  pantsim_c->info.fsim_tilt_pitch   = 0.0;
  pantsim_c->info.fsim_tilt_pitch   = 0.0;

  pantsim_c->info.icbits    = 0;
  pantsim_c->info.isbits    = 0;
  pantsim_c->info.iActualPolar   = POL_VERT_FIX; /*This simulated RCP powers up in V*/
  pantsim_c->info.iDesiredPolar  = POL_UNCHANGED;
  pantsim_c->info.iActualPwbw    = 0;
  pantsim_c->info.iDesiredPwbw   = ANT_PWBW_UNCHANGED;
  pantsim_c->info.idsiggen_value = 0;

  getbtime( &pantsim_c->info.ibtime );

  pantsim_c->info.iin_cnt   = 0;
  pantsim_c->info.iout_cnt  = 0;
  pantsim_c->info.iin_ercnt = 0;
  pantsim_c->info.iout_ercnt= 0;

  /* ic_mask and is_mask are set elsewhere
   */
  getbtime( &pantsim_c->info.isim_time );
  pantsim_c->info.iQBiteSimTime = pantsim_c->info.isim_time;

  pantsim_c->info.itr_on_time      = 0;
  pantsim_c->info.lwe_should_reset = FALSE;
  pantsim_c->info.lsend_time       = FALSE;
  pantsim_c->info.itime_sent_time  = 0;

  bitesim_fault( -1, 0, 0 );

  return SS_NORMAL;
}

/* ------------------------------
 * Un map the shared memory.  Use this when you no longer need antenna driver.
 */
MESSAGE antsim_close(void)
{
  MESSAGE istatus;

  istatus = sig_shmem_unmap( pantsim_c, antsim_size_c, antsim_id_c );

  return istatus;
}
