Logo Search packages:      
Sourcecode: hamlib version File versions  Download package

optoscan.c

/*
 *  Hamlib CI-V backend - OptoScan extensions
 *  Copyright (c) 2000-2005 by Stephane Fillod
 *
 *    $Id: optoscan.c,v 1.13 2005/04/03 12:27:15 fillods Exp $
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as
 *   published by the Free Software Foundation; either version 2 of
 *   the License, or (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this library; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <math.h>
#include <sys/time.h>

#include "hamlib/rig.h"
#include "serial.h"
#include "misc.h"
#include "cal.h"
#include "token.h"

#include "icom.h"
#include "icom_defs.h"
#include "frame.h"
#include "optoscan.h"


const struct confparams opto_ext_parms[] = {
  { TOK_TAPECNTL, "tapecntl", "Toggle Tape Switch", "Toggles built in tape switch", 0, RIG_CONF_CHECKBUTTON, {} },
  { TOK_5KHZWIN,  "5khzwin", "Toggle 5kHz Search Window", "Toggles 5kHz search window", 0, RIG_CONF_CHECKBUTTON, {} },
  { TOK_SPEAKER,  "speaker", "Toggle speaker audio", "Toggles speaker audio", 0, RIG_CONF_CHECKBUTTON, {} },
  { TOK_AUDIO, "audio", "Audio present", "Audio present", NULL, RIG_CONF_CHECKBUTTON, {} },
  { TOK_DTMFPEND, "dtmfpend", "DTMF Digit Pending", "DTMF Digit Pending", NULL, RIG_CONF_CHECKBUTTON, {} },
  { TOK_DTMFOVRR, "dtmfovrr", "DTMF Buffer Overflow", "DTMF Buffer Overflow", NULL, RIG_CONF_CHECKBUTTON, {} },
  { TOK_CTCSSACT, "ctcssact", "CTCSS Tone Active", "CTCSS Tone Active", NULL, RIG_CONF_CHECKBUTTON, {} },
  { TOK_DCSACT,   "dcsact", "DCS Code Active", "DCS Code Active", NULL, RIG_CONF_CHECKBUTTON, {} }, 
  { RIG_CONF_END, NULL, }
};

static int optoscan_get_status_block(RIG *rig, struct optostat *status_block);
static int optoscan_send_freq(RIG *rig,pltstate_t *state);
static int optoscan_RTS_toggle(RIG *rig);
static int optoscan_start_timer(RIG *rig, pltstate_t *state);
static int optoscan_wait_timer(RIG *rig, pltstate_t *state);

/*
 * optoscan_open
 * Assumes rig!=NULL, rig->state.priv!=NULL
 */
int optoscan_open(RIG *rig)
{
            struct icom_priv_data *priv;
            struct rig_state *rs;
            pltstate_t *pltstate;
            unsigned char ackbuf[16];
            int ack_len, retval;

            rs = &rig->state;
            priv = (struct icom_priv_data*)rs->priv;

            pltstate = malloc(sizeof(pltstate_t));
            if (!pltstate) {
                  return -RIG_ENOMEM;
            }
            memset(pltstate, 0, sizeof(pltstate_t));
            priv->pltstate = pltstate;

            /* select REMOTE control */
            retval = icom_transaction (rig, C_CTL_MISC, S_OPTO_REMOTE, 
                                    NULL, 0, ackbuf, &ack_len);
            if (retval != RIG_OK) {
                  free(pltstate);
                  return retval;
            }

            if (ack_len != 1 || ackbuf[0] != ACK) {
                        rig_debug(RIG_DEBUG_ERR,"optoscan_open: ack NG (%#.2x), "
                                                "len=%d\n", ackbuf[0], ack_len);
                        free(pltstate);
                        return -RIG_ERJCTED;
            }

            return RIG_OK;
}

/*
 * optoscan_close
 * Assumes rig!=NULL, rig->state.priv!=NULL
 */
int optoscan_close(RIG *rig)
{
            struct icom_priv_data *priv;
            struct rig_state *rs;
            unsigned char ackbuf[16];
            int ack_len, retval;

            rs = &rig->state;
            priv = (struct icom_priv_data*)rs->priv;

            /* select LOCAL control */
            retval = icom_transaction (rig, C_CTL_MISC, S_OPTO_LOCAL, 
                                    NULL, 0, ackbuf, &ack_len);
            if (retval != RIG_OK)
                        return retval;

            if (ack_len != 1 || ackbuf[0] != ACK) {
                        rig_debug(RIG_DEBUG_ERR,"optoscan_close: ack NG (%#.2x), "
                                                "len=%d\n", ackbuf[0], ack_len);
                        return -RIG_ERJCTED;
            }

            free(priv->pltstate);

            return RIG_OK;
}

/*
 * optoscan_get_info
 * Assumes rig!=NULL, rig->state.priv!=NULL
 */
const char* optoscan_get_info(RIG *rig)
{
            struct icom_priv_data *priv;
            struct rig_state *rs;
            unsigned char ackbuf[16];
            int ack_len, retval;
            static char info[64];

            rs = &rig->state;
            priv = (struct icom_priv_data*)rs->priv;

            /* select LOCAL control */
            retval = icom_transaction (rig, C_CTL_MISC, S_OPTO_RDID, 
                                    NULL, 0, ackbuf, &ack_len);
            if (retval != RIG_OK)
                        return NULL;

            if (ack_len != 7) {
                        rig_debug(RIG_DEBUG_ERR,"optoscan_get_info: ack NG (%#.2x), "
                                                "len=%d\n", ackbuf[0], ack_len);
                        return NULL;
            }

            sprintf(info, "OptoScan%c%c%c, software version %d.%d, "
                                    "interface version %d.%d\n",
                                    ackbuf[2], ackbuf[3], ackbuf[4],
                                    ackbuf[5] >> 4, ackbuf[5] & 0xf, 
                                    ackbuf[6] >> 4, ackbuf[6] & 0xf);

            return info;
}

/*
 * optoscan_get_ctcss_tone
 * Assumes rig!=NULL, rig->state.priv!=NULL
 */
int optoscan_get_ctcss_tone(RIG *rig, vfo_t vfo, tone_t *tone)
{
            const struct rig_caps *caps;
            unsigned char tonebuf[MAXFRAMELEN];
            int tone_len, retval;

            caps = rig->caps;

            retval = icom_transaction(rig, C_CTL_MISC, S_OPTO_RDCTCSS, NULL, 0,
                                                                        tonebuf, &tone_len);
            if (retval != RIG_OK)
                        return retval;

            if (tone_len != 4) {
                        rig_debug(RIG_DEBUG_ERR,"optoscan_get_ctcss_tone: ack NG (%#.2x), "
                                                "len=%d\n", tonebuf[0], tone_len);
                        return -RIG_ERJCTED;
            }

            tone_len -= 2;

            *tone = from_bcd_be(tonebuf+2, tone_len*2);
            rig_debug(RIG_DEBUG_ERR,"optoscan_get_ctcss_tone: *tone=%d\n",*tone);

            return RIG_OK;
}


/*
 * optoscan_get_dcs_code
 * Assumes rig!=NULL, rig->state.priv!=NULL
 */
int optoscan_get_dcs_code(RIG * rig, vfo_t vfo, tone_t *code)
{
            const struct rig_caps *caps;
            unsigned char tonebuf[MAXFRAMELEN];
            int tone_len, retval;

            caps = rig->caps;

            retval = icom_transaction(rig, C_CTL_MISC, S_OPTO_RDDCS, NULL, 0,
                                                                        tonebuf, &tone_len);
            if (retval != RIG_OK)
                        return retval;

            if (tone_len != 4) {
                        rig_debug(RIG_DEBUG_ERR,"optoscan_get_dcs_code: ack NG (%#.2x), "
                                                "len=%d\n", tonebuf[0], tone_len);
                        return -RIG_ERJCTED;
            }

            tone_len -= 2;

            *code = from_bcd_be(tonebuf+2, tone_len*2);
            rig_debug(RIG_DEBUG_ERR,"optoscan_get_dcs_code: *code=%d\n",*code);

        return RIG_OK;
}

int optoscan_recv_dtmf(RIG *rig, vfo_t vfo, char *digits, int *length)
{
            const struct rig_caps *caps;
            unsigned char dtmfbuf[MAXFRAMELEN],digit;
            int len, retval, digitpos;
            unsigned char xlate[] = {'0','1','2','3','4','5','6',
                               '7','8','9','A','B','C','D',
                               '*','#'};
            caps = rig->caps;
            digitpos=0;
             
            do {
              retval = icom_transaction(rig, C_CTL_MISC, S_OPTO_RDDTMF, 
                                  NULL,0,dtmfbuf, &len);
              if (retval != RIG_OK)
                return retval;
              
              if (len != 3) {
                rig_debug(RIG_DEBUG_ERR,"optoscan_recv_dtmf: ack NG (%#.2x), len=%d\n", dtmfbuf[0], len);
                return -RIG_ERJCTED;
              }
              
              digit = dtmfbuf[2];
              
              if( digit < 0x16 )
                {
                  digits[digitpos] = xlate[digit];
                  digitpos++;
                }
            } while( (digit != 0x99) && (digitpos < *length) );
              
            *length = digitpos;
            digits[digitpos]=0;

            if(*length > 0)
              {
                rig_debug(RIG_DEBUG_ERR,"optoscan_recv_dtmf: %d digits - %s\n",*length,digits);
              }
            else
              {
                rig_debug(RIG_DEBUG_ERR,"optoscan_recv_dtmf: no digits to read.\n");
              }

        return RIG_OK;
}

/*
 * Assumes rig!=NULL, rig->state.priv!=NULL
 */
int optoscan_set_ext_parm(RIG *rig, token_t token, value_t val)
{
      unsigned char epbuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN];
      int ack_len, val_len;
      int retval,subcode;

      memset(epbuf,0,MAXFRAMELEN);
      memset(ackbuf,0,MAXFRAMELEN);

      val_len = 1;

      switch(token) {
      case TOK_TAPECNTL:
        if( val.i == 0 ) {
          subcode = S_OPTO_TAPE_OFF;
        }
        else {
          subcode = S_OPTO_TAPE_ON;
        }
        break;
      case TOK_5KHZWIN:
        if( val.i == 0 ) {
          subcode = S_OPTO_5KSCOFF;
        }
        else {
          subcode = S_OPTO_5KSCON;
        }
        break;
      case TOK_SPEAKER:
        if( val.i == 0 ) {
          subcode = S_OPTO_SPKROFF;
        }
        else {
          subcode = S_OPTO_SPKRON;
        }
        break;
      default:
        return -RIG_EINVAL;
      }

      retval = icom_transaction (rig, C_CTL_MISC, subcode, epbuf, 0,
                                    ackbuf, &ack_len);
      if (retval != RIG_OK)
            return retval;

      if (ack_len != 1 || ackbuf[0] != ACK) {
            rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), "
                  "len=%d\n", __FUNCTION__, ackbuf[0], ack_len);
            return -RIG_ERJCTED;
      }
      
      return RIG_OK;
}

/*
 * Assumes rig!=NULL, rig->state.priv!=NULL
 *  and val points to a buffer big enough to hold the conf value.
 */
int optoscan_get_ext_parm(RIG *rig, token_t token, value_t *val)
{
  struct optostat status_block;
  int retval;

  retval = optoscan_get_status_block(rig,&status_block);

  if (retval != RIG_OK)
    return retval;
  
  switch(token) {
  case TOK_TAPECNTL:
    val->i = status_block.tape_enabled;
    break;
  case TOK_5KHZWIN:
    val->i = status_block.fivekhz_enabled;
    break;
  case TOK_SPEAKER:
    val->i = status_block.speaker_enabled;
    break;
  case TOK_AUDIO:
    val->i = status_block.audio_present;
    break;
  case TOK_DTMFPEND:
    val->i = status_block.DTMF_pending;
    break;
  case TOK_DTMFOVRR:
    val->i = status_block.DTMF_overrun;
    break;
  case TOK_CTCSSACT:
    val->i = status_block.CTCSS_active;
    break;
  case TOK_DCSACT:
    val->i = status_block.DCS_active;
    break;
  default:
    return -RIG_ENIMPL;
  }

  return RIG_OK;
}

/*
 * optoscan_set_level
 * Assumes rig!=NULL, rig->state.priv!=NULL
 */
int optoscan_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
{
            struct icom_priv_data *priv;
            struct rig_state *rs;
            unsigned char lvlbuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN];
            int ack_len;
            int lvl_cn, lvl_sc;           /* Command Number, Subcommand */
            int icom_val;
            int retval;

            rs = &rig->state;
            priv = (struct icom_priv_data*)rs->priv;

            memset(lvlbuf,0,MAXFRAMELEN);

            /*
             * So far, levels of float type are in [0.0..1.0] range
             */
            if (RIG_LEVEL_IS_FLOAT(level))
                        icom_val = val.f * 255;
            else
                        icom_val = val.i;

            switch (level) {
            case RIG_LEVEL_AF:
                  lvl_cn = C_CTL_MISC;
                  if( icom_val == 0 ) {
                    lvl_sc = S_OPTO_SPKROFF;
                  }
                  else {
                    lvl_sc = S_OPTO_SPKRON;
                  }
                  break;
            default:
                  rig_debug(RIG_DEBUG_ERR,"Unsupported set_level %d", level);
                  return -RIG_EINVAL;
            }

            retval = icom_transaction (rig, lvl_cn, lvl_sc, lvlbuf, 0,
                                    ackbuf, &ack_len);
            if (retval != RIG_OK)
                        return retval;

            if (ack_len != 1 || ackbuf[0] != ACK) {
                        rig_debug(RIG_DEBUG_ERR,"optoscan_set_level: ack NG (%#.2x), "
                                                "len=%d\n", ackbuf[0], ack_len);
                        return -RIG_ERJCTED;
            }

            return RIG_OK;
}

/*
 * optoscan_get_level
 * Assumes rig!=NULL, rig->state.priv!=NULL, val!=NULL
 */
int optoscan_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
{
  struct optostat status_block;
  struct icom_priv_data *priv;
  struct rig_state *rs;
  unsigned char lvlbuf[MAXFRAMELEN];
  int lvl_len;
  int lvl_cn, lvl_sc;         /* Command Number, Subcommand */
  int icom_val;
  int cmdhead;
  int retval;
  
  rs = &rig->state;
  priv = (struct icom_priv_data*)rs->priv;
  
  if( level != RIG_LEVEL_AF )
    {
      switch (level) {
      case RIG_LEVEL_RAWSTR:
      lvl_cn = C_RD_SQSM;
      lvl_sc = S_SML;
      break;
      default:
      rig_debug(RIG_DEBUG_ERR,"Unsupported get_level %d", level);
      return -RIG_EINVAL;
      }
      
      retval = icom_transaction (rig, lvl_cn, lvl_sc, NULL, 0,
                         lvlbuf, &lvl_len);
      if (retval != RIG_OK)
      return retval;
      
      /*
       * strbuf should contain Cn,Sc,Data area
       */
      cmdhead = (lvl_sc == -1) ? 1:2;
      lvl_len -= cmdhead;
      
      if (lvlbuf[0] != ACK && lvlbuf[0] != lvl_cn) {
      rig_debug(RIG_DEBUG_ERR,"optoscan_get_level: ack NG (%#.2x), "
              "len=%d\n", lvlbuf[0],lvl_len);
      return -RIG_ERJCTED;
      }
      
      /*
       * The result is a 3 digit BCD, but in *big endian* order: 0000..0255
       * (from_bcd is little endian)
       */
      icom_val = from_bcd_be(lvlbuf+cmdhead, lvl_len*2);
    }
  else /* level == RIG_LEVEL_AF */
    {
      retval = optoscan_get_status_block(rig,&status_block);
      
      if (retval != RIG_OK)
      return retval;
      
      icom_val = 0;
      if( status_block.speaker_enabled == 1 )
      icom_val = 255;
    }
  
  switch (level) {
  case RIG_LEVEL_RAWSTR:
    val->i = icom_val;
    break;
  default:
    if (RIG_LEVEL_IS_FLOAT(level))
      val->f = (float)icom_val/255;
    else
      val->i = icom_val;
  }
  
  rig_debug(RIG_DEBUG_TRACE,"optoscan_get_level: %d %d %d %f\n", lvl_len,
          icom_val, val->i, val->f);
  
  return RIG_OK;
}

/* OS456 Pipeline tuning algorithm:                                          
 *    Step 2:  Send the next frequency and mode to the receiver using the
 *           TRANSFER NEXT FREQUENCY/MODE command.
 *
 *      Step 3:  Change the state of the RTS interface signal to cause the
 *               next frequency and mode to become the current frequency and
 *               mode, and the receiver to begin settling.
 *
 *    Step 4:  While the receiver is still settling on the current
 *           frequency and mode, send the next frequency and mode to the
 *           receiver using the TRANSFER NEXT FREQUENCY/MODE command.
 *
 *    Step 5:  Wait for the receiver to finish settling.  The total
 *           settling time, including sending the next frequency and
 *           mode, is 20 milliseconds (0.02 seconds).
 *
 *    Step 6:  Check the squelch status by reading the DCD interface
 *           signal.  If the squelch is open, scanning is stopped.
 *           Otherwise, scanning continues.  Optionally, the status of
 *           the CTCSS/DCS/DTMF decoder can be checked, and the
 *           appropriate action taken.
 *
 *    Step 7:  Continuously repeat steps 3 through 6 above.
 */
int optoscan_scan(RIG *rig, vfo_t vfo, scan_t scan, int ch)
{
  pltstate_t *state;
  pltune_cb_t cb;
  int rc, pin_state;
  struct rig_state *rs;

  if(scan != RIG_SCAN_PLT)
    return -RIG_ENAVAIL;

  rs=&rig->state;
  cb = rig->callbacks.pltune;
  state = ((struct icom_priv_data*)rs->priv)->pltstate;

  if(state==NULL)
    return -RIG_EINTERNAL;

  if(state->freq==0) /* pltstate_t is not initialized - perform setup */
    {
      /* time for CIV command to be sent. this is subtracted from */
      /* rcvr settle time */
      state->usleep_time = (1000000 / (rig->state.rigport.parm.serial.rate)) 
      * 13 * 9;

      rc=cb(rig,vfo,&(state->next_freq),&(state->next_mode),
          &(state->next_width),rig->callbacks.pltune_arg);
      if(rc==RIG_SCAN_STOP)
      return RIG_OK; /* callback halted loop */

      /* Step 1 is implicit, since hamlib does this when it opens the device */
      optoscan_send_freq(rig,state); /*Step 2*/
    }

  rc=!RIG_SCAN_STOP;
  while(rc!=RIG_SCAN_STOP)
    {
      optoscan_RTS_toggle(rig); /*Step 3*/

      state->freq = state->next_freq;
      state->mode = state->next_mode;

      optoscan_start_timer(rig,state);

      rc=cb(rig,vfo,&(state->next_freq),&(state->next_mode),
          &(state->next_width),rig->callbacks.pltune_arg);
      if(rc!=RIG_SCAN_STOP)
      {
        optoscan_send_freq(rig,state); /*Step 4*/
      }

      optoscan_wait_timer(rig,state); /*Step 5*/
      
      ser_get_car(&rs->rigport,&pin_state);
      if( pin_state ) /*Step 6*/
      {
        return RIG_OK; /* we've broken squelch - return(). caller can */
                       /* get current freq & mode out of state str    */
      }
    }

  /* exiting pipeline loop - force state init on next call */
  state->freq=0;

  return RIG_OK;
}

/*
 * Assumes rig!=NULL, status_block !=NULL
 */
static int optoscan_get_status_block(RIG *rig, struct optostat *status_block)
{
  int retval, ack_len, expected_len;
  unsigned char ackbuf[MAXFRAMELEN];

  memset(status_block,0,sizeof(struct optostat));

  retval = icom_transaction (rig, C_CTL_MISC, S_OPTO_RDSTAT, NULL, 0,
                       ackbuf, &ack_len);
  
  if (retval != RIG_OK)
    return retval;
  
  switch( rig->caps->rig_model )
    {
    case RIG_MODEL_OS456:
      expected_len=4;
      break;
    case RIG_MODEL_OS535:
      expected_len=5;
      break;
    default:
      rig_debug(RIG_DEBUG_ERR,"optoscan_get_status_block: unknown rig model");
      return -RIG_ERJCTED;
      break;
    }

  if (ack_len != expected_len ) {
    rig_debug(RIG_DEBUG_ERR,"optoscan_get_status_block: ack NG (%#.2x), "
            "len=%d\n", ackbuf[0], ack_len);
    return -RIG_ERJCTED;
  }
  
  if( ackbuf[2] & 1 )  status_block->remote_control = 1;  
  if( ackbuf[2] & 2 )  status_block->DTMF_pending = 1;
  if( ackbuf[2] & 4 )  status_block->DTMF_overrun = 1;
  if( ackbuf[2] & 16 ) status_block->squelch_open = 1;
  if( ackbuf[2] & 32 ) status_block->CTCSS_active = 1;
  if( ackbuf[2] & 64 ) status_block->DCS_active = 1;

  if( ackbuf[3] & 1 )  status_block->tape_enabled = 1;
  if( ackbuf[3] & 2 )  status_block->speaker_enabled = 1;
  if( ackbuf[3] & 4 )  status_block->fivekhz_enabled = 1;
  if( ackbuf[3] & 16 ) status_block->audio_present = 1;

  rig_debug(RIG_DEBUG_VERBOSE,"remote_control     = %d\n",status_block->remote_control);
  rig_debug(RIG_DEBUG_VERBOSE,"DTMF_pending       = %d\n",status_block->DTMF_pending);
  rig_debug(RIG_DEBUG_VERBOSE,"DTMF_overrun       = %d\n",status_block->DTMF_overrun);
  rig_debug(RIG_DEBUG_VERBOSE,"squelch_open       = %d\n",status_block->squelch_open);
  rig_debug(RIG_DEBUG_VERBOSE,"CTCSS_active       = %d\n",status_block->CTCSS_active);
  rig_debug(RIG_DEBUG_VERBOSE,"DCS_active         = %d\n",status_block->DCS_active);
  rig_debug(RIG_DEBUG_VERBOSE,"tape_enabled       = %d\n",status_block->tape_enabled );
  rig_debug(RIG_DEBUG_VERBOSE,"speaker_enabled    = %d\n",status_block->speaker_enabled);
  rig_debug(RIG_DEBUG_VERBOSE,"fivekhz_enabled    = %d\n",status_block->fivekhz_enabled);
  rig_debug(RIG_DEBUG_VERBOSE,"audio_present      = %d\n",status_block->audio_present);

  return RIG_OK;
}


static int optoscan_send_freq(RIG *rig,pltstate_t *state)
{
  unsigned char buff[OPTO_BUFF_SIZE];
  struct icom_priv_data *priv;
  struct rig_state *rs;
  const hamlib_port_t *port;
  int fd;
  char md,pd;
  freq_t freq;
  rmode_t mode;

  port = &(rig->state.rigport);
  fd = port->fd;
  rs = &rig->state;
  priv = (struct icom_priv_data*)rs->priv;
  freq=state->next_freq;
  mode=state->next_mode;

  memset(buff,0,OPTO_BUFF_SIZE);  

  to_bcd(buff,freq,5*2); /* to_bcd requires nibble len */

  rig2icom_mode(rig,mode,0,&md,&pd);
  buff[5]=md;

  /* read echo'd chars only...there will be no ACK from this command
   *
   * Note:
   *  It may have waited fro pltstate->usleep_time before reading the echo'd
   *  chars, but the read will be blocking anyway. --SF
   * */
  return icom_transaction (rig, C_CTL_MISC, S_OPTO_NXT, buff, 6, NULL, NULL);

  return RIG_OK;
}

static int optoscan_RTS_toggle(RIG *rig)
{
  struct rig_state *rs;
  int state=0;

  rs=&rig->state;
  ser_get_rts(&rs->rigport,&state);
  ser_set_rts(&rs->rigport,!state); 

  return RIG_OK;
}

static int optoscan_start_timer(RIG *rig, pltstate_t *state)
{
  gettimeofday(&(state->timer_start),NULL);

  return RIG_OK;
}

static int optoscan_wait_timer(RIG *rig, pltstate_t *state)
{
  struct icom_priv_caps *priv_caps;
  int usec_diff;
  int settle_usec;

  priv_caps = (struct icom_priv_caps *)rig->caps->priv;
  settle_usec = priv_caps->settle_time * 1000; /*convert settle time (ms) to */
                                               /* settle time (usec)         */

  gettimeofday(&(state->timer_current),NULL);

  usec_diff = abs( (state->timer_current.tv_usec) - 
               (state->timer_start.tv_usec) );

  if( usec_diff < settle_usec )
    {
      usleep( settle_usec - usec_diff ); /* sleep balance of settle_time */
    }

  return RIG_OK;
}


Generated by  Doxygen 1.6.0   Back to index