/*
 * Copyright 1988, 1989, 1990, 1991 Massachusetts Institute of Technology
 */


/* boa16_driver.c: a driver for the BOA_16 */

#include "boa16.h"
#include "structs.h"
/* --------------------------------------------------------------- */

static int boa16_set_state( swtr, output, v, a1, a2 )
     
     SWTR_ptr swtr;
     int	output;		/* the number of the output */
     int	v,a1,a2;	/* the number of the input patched to that channel */
{

  if( !output || output < 1 || output > NUM_OUTPUTS || !swtr)
    return 0;
  output -= 1;	/* adjust for zero-base */
  
  /* if anything is 0, leave it alone */
  
  if( v )
    {
      if( v < 1 )
	v = 1;
      else if( v > NUM_INPUTS )
	v = NUM_INPUTS;
      swtr->state[output].VideoSource = v;
    }
  if( a1 )
    {
      if( a1 < 1 )
	a1 = 1;
      else if( a1 > NUM_INPUTS )
	a1 = NUM_INPUTS;
      swtr->state[output].LeftSource = a1;
    }
  if( a2 )
    {
      if( a2 < 1 )
	a2 = 1;
      else if( a2 > NUM_INPUTS )
	a2 = NUM_INPUTS;
      swtr->state[output].RightSource = a2;
    }
  return 0;
}

/* --------------------------------------------------------------- */

int boa16_reset( swtr )
     
     SWTR_ptr	swtr;
{
  int i, default_in;
  
  if( !swtr )
    return -1;
  
  if( swtr->fd<0 )
    return -1;
  
  for (i = 1; i <= NUM_OUTPUTS; i++) {
    if (swtr->default_input[i] != -1) default_in = swtr->default_input[i];
    else default_in = i;
    if (boa16_set_chan_src(swtr, ALL_CHAN, default_in, i) < 0)
      return -1;
  }
  return 0;
}

/* --------------------------------------------------------------- */

int boa16_set_chan_src( swtr, chan, srcnum, output )
     SWTR_ptr swtr;
     int	output;	/* should always be 1, because only 1 output */
     int	chan;
     int	srcnum;
{
  char cmd[10];
  int vsrc, lsrc, rsrc;

  if( !swtr )
    return -1;
  
  if( swtr->fd < 0 )
    return -1;
  
  if( srcnum < 1 )
    srcnum = 1;
  else if( srcnum > NUM_INPUTS )
    srcnum = NUM_INPUTS;
  
  if (output < 1)
    output = 1;
  else if (output > NUM_OUTPUTS)
    output = NUM_OUTPUTS;

  /* 
   * RMS mod 1/10/91; if we make a change to the state
   * of the video channel, we should wait until we're sure
   * the switch has been made before returning; this could
   * cause video digitizers (for example) to get a bad frame
   * or a frame from the wrong video source.
   *
   * if BOA_ACK is defined, wait for the return character;
   * else, just wait some predefined time
   */

  boa16_inquire( swtr, output, &vsrc, &lsrc, &rsrc );

  switch(chan) {
  case VIDEO_CHAN:
    sprintf(cmd, "V%d%d", srcnum,output );
    ttyutil_write( swtr->fd, cmd, strlen(cmd), 20 );
    boa16_set_state( swtr, output, srcnum, 0, 0 );
#ifndef BOA_ACK
    if(vsrc != srcnum)
      mpause(200);
#endif
    break;
  case LEFT_CHAN:
    sprintf(cmd, "A%d%d", srcnum,output );
    ttyutil_write( swtr->fd, cmd, strlen(cmd), 20 );
    boa16_set_state( swtr, output, 0, srcnum, srcnum );
    break;
  case RIGHT_CHAN:
    sprintf(cmd, "A%d%d", srcnum,output );
    ttyutil_write( swtr->fd, cmd, strlen(cmd), 20 );
    boa16_set_state( swtr, output, 0, srcnum, srcnum );
    break;
  case ALL_CHAN:
    sprintf(cmd, "B%d%d", srcnum,output );
    ttyutil_write( swtr->fd, cmd, strlen(cmd), 20 );
    boa16_set_state( swtr, output, srcnum, srcnum, srcnum );
#ifndef BOA_ACK
    if(vsrc != srcnum)
      mpause(200);
#endif
    break;
  case (RIGHT_CHAN | LEFT_CHAN):
    sprintf(cmd, "A%d%d", srcnum,output );
    ttyutil_write( swtr->fd, cmd, strlen(cmd), 20 );
    boa16_set_state( swtr, output, 0, srcnum, srcnum );
    break;
  case (RIGHT_CHAN | VIDEO_CHAN):
    sprintf(cmd, "B%d%d", srcnum,output );
    ttyutil_write( swtr->fd, cmd, strlen(cmd), 20 );
    boa16_set_state( swtr, output, srcnum, srcnum, srcnum);
#ifndef BOA_ACK
    if(vsrc != srcnum)
      mpause(200);
#endif
    break;
  case (LEFT_CHAN | VIDEO_CHAN):
    sprintf(cmd, "B%d%d", srcnum,output );
    ttyutil_write( swtr->fd, cmd, strlen(cmd), 20 );
    boa16_set_state( swtr, output, srcnum, srcnum, srcnum );
#ifndef BOA_ACK
    if(vsrc != srcnum)
      mpause(200);
#endif
    break;
  default:
    return(0);
  }

#ifdef BOA_ACK
  if (ttyutil_read(swtr->fd, cmd, 1, BOA16_TIMEOUT) < 1) {
    bsdsyslog(LOG_NOTICE,"%s: %s: i/o timeout in setting state",
	      swtr->devname, swtr->port);
    return(-1);
  }
#endif /* BOA_ACK */
#ifdef FULL_DEBUG
  if (DEBUG) 
    printf("Set output %d of BOA_16 switcher to input %d, mask %d\n",
	   output, srcnum, chan);
#endif /* FULL_DEBUG */
  return 0;
}

/* --------------------------------------------------------------- */

int boa16_inquire( swtr, output, vsrc, lsrc, rsrc )
     SWTR_ptr swtr;
     int	output;
     int *	vsrc;
     int *	lsrc;
     int *	rsrc;
{
  
  if( output < 1 || output > NUM_OUTPUTS || !swtr)
    return -1;	/* don't mess with the channel return values */
  output -= 1;		/* adjust for zero-base */
  
  *vsrc = swtr->state[output].VideoSource;
  *lsrc = swtr->state[output].LeftSource;
  *rsrc = swtr->state[output].RightSource;
  if (DEBUG) printf("Inquired about BOA_16 switcher output %d\n",output);
  return 0;
}

/* --------------------------------------------------------------- */

int boa16_setfuncs( swtr )

	SWTR_ptr	swtr;
{
	swtr->reset = boa16_reset;
	swtr->set_chan_src = boa16_set_chan_src;
	swtr->inquire = boa16_inquire;
	swtr->inputs = NUM_INPUTS;
	swtr->outputs = NUM_OUTPUTS;
	return 0;
}
