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

cat.c

/*  cat.c
 *
 *  Yaesu FT847 CAT control functions for the xdemorse application
 */

/*
 *  xdemorse: An application to decode and display
 *  Morse code signals using the computer's sound card.
 *
 *  Copyright (C) 2003  Neoklis Kyriazis
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU 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 General Public License for more details:
 *
 *  http://www.gnu.org/copyleft/gpl.txt
 */

#include "xdemorse.h"
#include <termios.h>


/* Average bin values */
extern int gbl_bin_ave[];

/* Command codes for FT847 CAT */
unsigned char
  CAT_ON[]        = { 0x00, 0, 0, 0, 0x00 },
  CAT_OFF[]       = { 0x00, 0, 0, 0, 0x80 },
  PTT_ON[]        = { 0x00, 0, 0, 0, 0x08 },
  PTT_OFF[]       = { 0x00, 0, 0, 0, 0x88 },
  MODE_LSB[]      = { 0x00, 0, 0, 0, 0x07 },
  MODE_USB[]      = { 0x01, 0, 0, 0, 0x07 },
  MODE_CW[]       = { 0x02, 0, 0, 0, 0x07 },
  MODE_CWR[]      = { 0x03, 0, 0, 0, 0x07 },
  MODE_CWN[]      = { 0x82, 0, 0, 0, 0x07 },
  MODE_CWNR[]     = { 0x83, 0, 0, 0, 0x07 },
  MODE_DIG[]      = { 0x0a, 0, 0, 0, 0x07 },
  MODE_PKT[]      = { 0x0c, 0, 0, 0, 0x07 },
  RX_STATUS[]     = { 0x00, 0, 0, 0, 0xE7 },
  MAIN_VFO[]      = { 0x00, 0, 0, 0, 0x03 };

#define     WRITE_RX_VFO      0x01

/* Runtime config data */
extern rc_data_t rc_data;

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

/* Serial port File descriptor */
static int tcvr_serial_fd = 0;

/* Original serial port options */
static struct termios tcvr_serial_old_options;


/*  Open_Tcvr_Serial()
 *
 *  Opens Tcvr's Serial Port device, returns the file
 *  descriptor tcvr_serial_fd on success or exits on error
 */

  void
Open_Tcvr_Serial( void )
{
  struct termios new_options; /* New serial port options */
  struct flock lockinfo;      /* File lock information   */

  /* For testing serial port */
  unsigned char test;

  /* Serial port name */
  char serial_port[15];


  /* Abort if serial already open */
  if( isFlagSet(CAT_SETUP) )
      return;

  /* Open Serial device, exit on error */
  if( isFlagSet(ENABLE_CAT_847) )
      strcpy( serial_port, rc_data.ft847_serial );
  else
      if( isFlagSet(ENABLE_CAT_857) )
        strcpy( serial_port, rc_data.ft857_serial );
  tcvr_serial_fd = open( serial_port, O_RDWR | O_NOCTTY );
  if( tcvr_serial_fd < 0 )
  {
      char message[32];

      perror( serial_port );
      snprintf( message, 32, "Failed to open %s", serial_port );
      Error_Dialog( message );
      Set_Flag( SERIAL_IO_ERROR );
      return;
  }

  /* Attempt to lock entire Serial port device file */
  lockinfo.l_type   = F_WRLCK;
  lockinfo.l_whence = SEEK_SET;
  lockinfo.l_start  = 0;
  lockinfo.l_len    = 0;

  /* If Serial device is already locked, abort */
  if( fcntl( tcvr_serial_fd, F_SETLK, &lockinfo ) < 0 )
  {
      char message[60];
      fcntl( tcvr_serial_fd, F_GETLK, &lockinfo );
      snprintf( message, 60,
            "Failed to lock %s\n"
            "Device locked by pid %d",
            serial_port, lockinfo.l_pid );
      Error_Dialog( message );
      Set_Flag( SERIAL_IO_ERROR );
      return;
  }

  /* Save the current serial port options */
  tcgetattr( tcvr_serial_fd, &tcvr_serial_old_options );

  /* Read the current serial port options */
  tcgetattr( tcvr_serial_fd, &new_options );

  /* Set the i/o baud rates */
  if( isFlagSet(ENABLE_CAT_847) )
  {
      cfsetispeed( &new_options, B57600 );
      cfsetospeed( &new_options, B57600 );
  }
  else
      if( isFlagSet(ENABLE_CAT_857) )
      {
        cfsetispeed( &new_options, B38400 );
        cfsetospeed( &new_options, B38400 );
      }

  /* Set options for 'raw' I/O mode */
  new_options.c_iflag &=
      ~( IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON );
  new_options.c_oflag &= ~( OPOST | OLCUC  | ONLCR  | OCRNL | ONOCR | ONLRET );
  new_options.c_lflag &= ~( ECHO  | ECHONL | ICANON | ISIG  | IEXTEN );
  new_options.c_cflag &= ~( CSIZE | PARENB );
  new_options.c_cflag |= ( CS8 | CLOCAL | CREAD | CSTOPB );

  /* Setup read() timeout to .2 sec */
  new_options.c_cc[ VMIN ]  = 0;
  new_options.c_cc[ VTIME ] = 2;

  /* Setup the new options for the port */
  tcsetattr( tcvr_serial_fd, TCSAFLUSH, &new_options );

  /* Enable CAT */
  if( isFlagSet(ENABLE_CAT) )
      Write_Tcvr_Command(CAT_ON);

  /* Test the serial port */
  Write_Tcvr_Command( RX_STATUS );
  Read_Tcvr_Serial( &test, 1 );
  if( isFlagClear(SERIAL_IO_ERROR) )
      Set_Flag( CAT_SETUP );
  else
  {
      tcsetattr( tcvr_serial_fd, TCSANOW, &tcvr_serial_old_options );
      close( tcvr_serial_fd );
      tcvr_serial_fd = 0;
  }

} /* End of Open_Tcvr_Serial() */

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

/*  Read_Tcvr_Serial()
 *
 *  Reading Data from the Tcvr's Serial Port
 */

  void
Read_Tcvr_Serial( unsigned char *cmnd, int block_size )
{
  /* Error condition */
  if( read(tcvr_serial_fd, cmnd, block_size) < block_size )
  {
      tcflush( tcvr_serial_fd, TCIOFLUSH );
      Set_Flag( SERIAL_IO_ERROR );
      Error_Dialog( "Serial port Rx I/O error" );
  }

} /* End of Read_Tcvr_Serial() */

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

/*  Write_Tcvr_Command()
 *
 *  Writes a command (status change)
 *  to the Yaesu Tranceiver
 */

  void
Write_Tcvr_Command( unsigned char *cmnd )
{
  tcflush( tcvr_serial_fd, TCIOFLUSH );
  if( write( tcvr_serial_fd, cmnd, 5 ) < 5 ) /* Error condition */
  {
      tcflush( tcvr_serial_fd, TCIOFLUSH );
      Set_Flag( SERIAL_IO_ERROR );
      Error_Dialog( "Serial port Tx I/O error" );
      return;
  }

  /* Give time to CAT to do its thing */
  usleep(1000);

} /* End of Write_Tcvr_Command() */

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

/*  Close_Tcvr_Serial()
 *
 *  Restore old options and close the Serial port
 */

  void
Close_Tcvr_Serial( void )
{
  if( isFlagSet(CAT_SETUP) )
  {
      if( isFlagSet(ENABLE_CAT_847) )
        Write_Tcvr_Command( CAT_OFF );
      tcsetattr( tcvr_serial_fd, TCSANOW, &tcvr_serial_old_options );
      close( tcvr_serial_fd );
      tcvr_serial_fd = 0;
  }

  Clear_Flag( CAT_SETUP );

} /* End of Close_Tcvr_Serial() */

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

/* Tune_Tcvr()
 *
 * Tunes the transceiver to the frequency of the strongest
 * signal near a mouse click in the waterfall window
 */

  void
Tune_Tcvr( double x )
{
  int
      from, to,   /* Range to scan for a max bin value  */
      bin_max,    /* Max bin value found in this range  */
      max_idx,    /* fft idx at which the max is found */
      fft_idx,    /* Idx used to search fft bin values */
      tcvr_freq,  /* Transceiver's Rx frequency */
      audio_freq; /* Audio frequency in waterfal window */

  /* Calculate fft index corresponding to pointer x in waterfall window */
  fft_idx = (((int)(x-0.5))*FFT_SIZE) / (2*WFALL_WIDTH);

  /* Look above and below click point for max bin val */
  from = fft_idx - 10;
  if( from < 0 )
      from = 0;
  to = fft_idx + 10;
  if( to >= FFT_SIZE/2 )
      to = FFT_SIZE/2;

  /* Find max bin value around click point */
  bin_max = 0;
  max_idx = fft_idx;
  for( fft_idx = from; fft_idx < to; fft_idx++ )
      if( bin_max < gbl_bin_ave[fft_idx] )
      {
        bin_max = gbl_bin_ave[fft_idx];
        max_idx = fft_idx;
      }

  /* Audio freq. corresponding to fft index */
  audio_freq = (2 * max_idx * rc_data.tone_freq) / WFALL_WIDTH;

  /* Read current Rx frequency */
  tcvr_freq = Read_Rx_Freq();

  /* Calculate and write Rx freq. to center audio on AUDIO_FREQUENCY */
  Write_Rx_Freq(tcvr_freq + audio_freq - rc_data.tone_freq);

} /* Tune_Tcvr() */

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

/*  Read_Rx_Freq()
 *
 *  Reads the Rx freq of the Yaesu transceiver.
 */

  int
Read_Rx_Freq( void )
{
  /* A 5-char string for sending and receiving  */
  /* 5-byte strings to and from the transceiver */
  unsigned char cmnd_parm[5];

  int freq;

  bzero( cmnd_parm, 5 );

  /* Abort if CAT disabled */
  if( isFlagClear(CAT_SETUP) )
      return(-1);

  /* Read Rx frequency */
  Write_Tcvr_Command( MAIN_VFO );
  if( isFlagSet(SERIAL_IO_ERROR) )
      return(-2);

  Read_Tcvr_Serial( cmnd_parm, 5 );
  if( isFlagSet(SERIAL_IO_ERROR) )
      return(-3);

  /* Decode frequency data to 10Hz */
  freq = 0;
  freq += (cmnd_parm[0] & 0xF0) >> 4;
  freq *= 10;
  freq += cmnd_parm[0] & 0x0F;
  freq *= 10;
  freq += (cmnd_parm[1] & 0xF0) >> 4;
  freq *= 10;
  freq += cmnd_parm[1] & 0x0F;
  freq *= 10;
  freq += (cmnd_parm[2] & 0xF0) >> 4;
  freq *= 10;
  freq += cmnd_parm[2] & 0x0F;
  freq *= 10;
  freq += (cmnd_parm[3] & 0xF0) >> 4;
  freq *= 10;
  freq += cmnd_parm[3] & 0x0F;
  freq *= 10;
  freq += (cmnd_parm[4] & 0xF0) >> 4;

  return( freq );

} /* End of Read_Rx_Freq() */

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

/*  Write_Rx_Freq()
 *
 *  Writes the Rx freq to the Yaesu FT-847 transceiver.
 */

  void
Write_Rx_Freq( int freq )
{
  /* A 5-char string for sending and receiving */
  /* 5-byte strings to and from the transceiver */
  unsigned char cmnd_parm[5];

  /* Buffer used for converting freq. to string */
  char freq_buff[9];

  int idx; /* Index for loops etc */


  bzero( cmnd_parm, 5 );

  /* Set Rx frequency */
  snprintf( freq_buff, 9, "%08d", freq/10 );
  for( idx = 0; idx < 4; idx++ )
  {
      cmnd_parm[idx]  = (freq_buff[2*idx]   - '0') << 4;
      cmnd_parm[idx] |= (freq_buff[2*idx+1] - '0');
  }
  cmnd_parm[4] = WRITE_RX_VFO;

  Write_Tcvr_Command( cmnd_parm );

} /* End of Write_Rx_Freq() */

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


Generated by  Doxygen 1.6.0   Back to index