Hamlib/src/rig.c

3820 wiersze
95 KiB
C
Czysty Zwykły widok Historia

/**
* \file src/rig.c
* \brief Ham Radio Control Libraries interface
* \author Stephane Fillod
* \author Frank Singleton
* \date 2000-2001
*
* Hamlib interface is a frontend implementing wrapper functions.
*/
/*
* Hamlib Interface - main file
* Copyright (c) 2000,2001 by Stephane Fillod and Frank Singleton
*
* $Id: rig.c,v 1.40 2001-07-01 11:46:17 f4cfe 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 <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define HAMLIB_DLL
#include <hamlib/rig.h>
#include <serial.h>
#include "event.h"
/**
* \brief Hamlib release number
* \todo Should we include copyright here too?
*/
const char hamlib_version[] = "Hamlib version " VERSION;
#define DEFAULT_SERIAL_PORT "/dev/ttyS0"
/**
* 52 CTCSS sub-audible tones
*/
const tone_t full_ctcss_list[] = {
600, 670, 693, 719, 744, 770, 797, 825, 854, 885, 915,
948, 974, 1000, 1035, 1072, 1109, 1148, 1188, 1200, 1230, 1273,
1318, 1365, 1413, 1462, 1514, 1567, 1598, 1622, 1655, 1679,
1713, 1738, 1773, 1799, 1835, 1862, 1899, 1928, 1966, 1995,
2035, 2065, 2107, 2181, 2257, 2291, 2336, 2418, 2503, 2541,
0,
};
/**
* 50 CTCSS sub-audible tones, from 67.0Hz to 254.1Hz
*
* \note Don't even think about changing a bit of this array, several
* backends depend on it. If you need to, create a copy for your
* own caps. --SF
*/
const tone_t common_ctcss_list[] = {
670, 693, 719, 744, 770, 797, 825, 854, 885, 915,
948, 974, 1000, 1035, 1072, 1109, 1148, 1188, 1230, 1273,
1318, 1365, 1413, 1462, 1514, 1567, 1598, 1622, 1655, 1679,
1713, 1738, 1773, 1799, 1835, 1862, 1899, 1928, 1966, 1995,
2035, 2065, 2107, 2181, 2257, 2291, 2336, 2418, 2503, 2541,
0,
};
/**
* 106 DCS codes
*/
const tone_t full_dcs_list[] = {
017, 023, 025, 026, 031, 032, 036, 043, 047, 050, 051, 053,
054, 065, 071, 072, 073, 074, 114, 115, 116, 122, 125, 131,
132, 134, 143, 145, 152, 155, 156, 162, 165, 172, 174, 205,
212, 223, 225, 226, 243, 244, 245, 246, 251, 252, 255, 261,
263, 265, 266, 271, 274, 306, 311, 315, 325, 331, 332, 343,
346, 351, 356, 364, 365, 371, 411, 412, 413, 423, 431, 432,
445, 446, 452, 454, 455, 462, 464, 465, 466, 503, 506, 516,
523, 526, 532, 546, 565, 606, 612, 624, 627, 631, 632, 654,
662, 664, 703, 712, 723, 731, 732, 734, 743, 754,
0,
};
/*
* Data structure to track the opened rig (by rig_open)
*/
struct opened_rig_l {
RIG *rig;
struct opened_rig_l *next;
};
static struct opened_rig_l *opened_rig_list = { NULL };
/*
* Careful, the order must be the same as their RIG_E* counterpart!
* TODO: localise the messages..
*/
static const char *rigerror_table[] = {
"Command completed sucessfully",
"Invalid parameter",
"Invalid configuration",
"Memory shortage",
"Feature not implemented",
"Communication timed out",
"IO error",
"Internal Hamlib error",
"Protocol error",
"Command rejected by the rig",
"Command performed, but arg truncated, result not guaranteed",
"Feature not available",
"Target VFO unaccessible",
NULL,
};
/**
* \internal
*/
#define ERROR_TBL_SZ (sizeof(rigerror_table)/sizeof(char *))
/**
* \brief get string describing the error code
* \param errnum The error code
* \return the appropriate description string, ortherwise a NULL pointer
* if the error code is unknown.
*
* Returns a string describing the error code passed in the argument \a errnum.
*
* \todo support gettext/localization
*/
const char *rigerror(int errnum)
{
errnum = abs(errnum);
if (errnum > ERROR_TBL_SZ)
return NULL;
return rigerror_table[errnum];
}
/*
* track which rig is opened (with rig_open)
* needed at least for transceive mode
*/
static int add_opened_rig(RIG *rig)
{
struct opened_rig_l *p;
p = (struct opened_rig_l *)malloc(sizeof(struct opened_rig_l));
if (!p)
return -RIG_ENOMEM;
p->rig = rig;
p->next = opened_rig_list;
opened_rig_list = p;
return RIG_OK;
}
static int remove_opened_rig(RIG *rig)
{
struct opened_rig_l *p,*q;
q = NULL;
for (p=opened_rig_list; p; p=p->next) {
if (p->rig == rig) {
if (q == NULL) {
opened_rig_list = opened_rig_list->next;
} else {
q->next = p->next;
}
free(p);
return RIG_OK;
}
q = p;
}
return -RIG_EINVAL; /* Not found in list ! */
}
/**
* \brief execs cfunc() on each opened rig
* \param cfunc The function to be executed on each rig
* \param data Data pointer to be passed to cfunc()
*
* Calls cfunc() function for each opened rig.
* The contents of the opened rig table
* is processed in random order according to a function
* pointed to by \a cfunc, whic is called with two arguments,
* the first pointing to the #RIG handle, the second
* to a data pointer \a data.
* If \a data is not needed, then it can be set to NULL.
* The processing of the opened rig table is stopped
* when cfunc() returns 0.
* \internal
*
* \return always RIG_OK.
*/
int foreach_opened_rig(int (*cfunc)(RIG *, rig_ptr_t), rig_ptr_t data)
{
struct opened_rig_l *p;
for (p=opened_rig_list; p; p=p->next) {
if ((*cfunc)(p->rig,data) == 0)
return RIG_OK;
}
return RIG_OK;
}
/**
* \brief allocate a new #RIG handle
* \param rig_model The rig model for this new handle
*
* Allocates a new #RIG handle and initializes the associated data
* for \a rig_model.
*
* \return a pointer to the #RIG handle otherwise NULL if memory allocation
* failed or \a rig_model is unknown (e.g. backend autoload failed).
*
* \sa rig_cleanup(), rig_open()
*/
RIG *rig_init(rig_model_t rig_model)
{
RIG *rig;
const struct rig_caps *caps;
struct rig_state *rs;
int i;
rig_debug(RIG_DEBUG_VERBOSE,"rig:rig_init called \n");
rig_check_backend(rig_model);
caps = rig_get_caps(rig_model);
if (!caps)
return NULL;
/*
* okay, we've found it. Allocate some memory and set it to zeros,
* and especially the initialize the callbacks
*/
rig = calloc(1, sizeof(RIG));
if (rig == NULL) {
/*
* FIXME: how can the caller know it's a memory shortage,
* and not "rig not found" ?
*/
return NULL;
}
rig->caps = caps;
/*
* populate the rig->state
* TODO: read the Preferences here!
*/
rs = &rig->state;
rs->rigport.type.rig = caps->port_type; /* default from caps */
strncpy(rs->rigport.path, DEFAULT_SERIAL_PORT, FILPATHLEN);
rs->rigport.parm.serial.rate = caps->serial_rate_max; /* fastest ! */
rs->rigport.parm.serial.data_bits = caps->serial_data_bits;
rs->rigport.parm.serial.stop_bits = caps->serial_stop_bits;
rs->rigport.parm.serial.parity = caps->serial_parity;
rs->rigport.parm.serial.handshake = caps->serial_handshake;
rs->rigport.write_delay = caps->write_delay;
rs->rigport.post_write_delay = caps->post_write_delay;
rs->rigport.timeout = caps->timeout;
rs->rigport.retry = caps->retry;
rs->pttport.type.ptt = caps->ptt_type;
rs->dcdport.type.dcd = caps->dcd_type;
rs->vfo_comp = 0.0; /* override it with preferences */
rs->current_vfo = RIG_VFO_CURR; /* we don't know yet! */
rs->transceive = caps->transceive;
/* should it be a parameter to rig_init ? --SF */
rs->itu_region = RIG_ITU_REGION2;
switch(rs->itu_region) {
case RIG_ITU_REGION1:
memcpy(rs->tx_range_list, caps->tx_range_list1,
sizeof(struct freq_range_list)*FRQRANGESIZ);
memcpy(rs->rx_range_list, caps->rx_range_list1,
sizeof(struct freq_range_list)*FRQRANGESIZ);
break;
case RIG_ITU_REGION2:
case RIG_ITU_REGION3:
default:
memcpy(rs->tx_range_list, caps->tx_range_list2,
sizeof(struct freq_range_list)*FRQRANGESIZ);
memcpy(rs->rx_range_list, caps->rx_range_list2,
sizeof(struct freq_range_list)*FRQRANGESIZ);
break;
}
rs->vfo_list = 0;
for (i=0; i<FRQRANGESIZ; i++) {
if (rs->rx_range_list[i].start != 0 &&
rs->rx_range_list[i].end != 0)
rs->vfo_list |= rs->rx_range_list[i].vfo;
if (rs->tx_range_list[i].start != 0 &&
rs->tx_range_list[i].end != 0)
rs->vfo_list |= rs->tx_range_list[i].vfo;
}
memcpy(rs->preamp, caps->preamp, sizeof(int)*MAXDBLSTSIZ);
memcpy(rs->attenuator, caps->attenuator, sizeof(int)*MAXDBLSTSIZ);
memcpy(rs->tuning_steps, caps->tuning_steps,
sizeof(struct tuning_step_list)*TSLSTSIZ);
memcpy(rs->filters, caps->filters,
sizeof(struct filter_list)*FLTLSTSIZ);
memcpy(rs->chan_list, caps->chan_list, sizeof(chan_t)*CHANLSTSIZ);
rs->has_get_func = caps->has_get_func;
rs->has_set_func = caps->has_set_func;
rs->has_get_level = caps->has_get_level;
rs->has_set_level = caps->has_set_level;
rs->has_get_parm = caps->has_get_parm;
rs->has_set_parm = caps->has_set_parm;
rs->max_rit = caps->max_rit;
rs->max_xit = caps->max_xit;
rs->max_ifshift = caps->max_ifshift;
rs->announces = caps->announces;
rs->rigport.fd = rs->pttport.fd = rs->dcdport.fd = -1;
/*
* let the backend a chance to setup his private data
* FIXME: check rig_init() return code
*/
if (caps->rig_init != NULL)
caps->rig_init(rig);
return rig;
}
/**
* \brief open the communication to the rig
* \param rig The #RIG handle of the radio to be opened
*
* Opens communication to a radio which \a RIG handle has been passed
* by argument.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \retval RIG_EINVAL \a rig is NULL or unconsistent.
* \retval RIG_ENIMPL port type communication is not implemented yet.
*
* \sa rig_init(), rig_close()
*/
int rig_open(RIG *rig)
{
const struct rig_caps *caps;
int status;
vfo_t vfo;
rig_debug(RIG_DEBUG_VERBOSE,"rig:rig_open called \n");
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
rig->state.rigport.fd = -1;
switch(rig->state.rigport.type.rig) {
case RIG_PORT_SERIAL:
status = serial_open(&rig->state.rigport);
if (status != 0)
return status;
break;
case RIG_PORT_DEVICE:
status = open(rig->state.rigport.path, O_RDWR, 0);
if (status < 0)
return -RIG_EIO;
rig->state.rigport.fd = status;
break;
case RIG_PORT_NONE:
break; /* ez :) */
case RIG_PORT_NETWORK: /* not implemented yet! */
return -RIG_ENIMPL;
default:
return -RIG_EINVAL;
}
/*
* FIXME: what to do if PTT open fails or PTT unsupported?
* fail rig_open? remember unallocating..
*/
switch(rig->state.pttport.type.ptt) {
case RIG_PTT_NONE:
case RIG_PTT_RIG:
break;
case RIG_PTT_SERIAL_RTS:
case RIG_PTT_SERIAL_DTR:
rig->state.pttport.fd = ser_open(&rig->state.pttport);
if (rig->state.pttport.fd < 0)
rig_debug(RIG_DEBUG_ERR, "Cannot open PTT device \"%s\"\n",
rig->state.pttport.path);
break;
case RIG_PTT_PARALLEL:
rig->state.pttport.fd = par_open(&rig->state.pttport);
if (rig->state.pttport.fd < 0)
rig_debug(RIG_DEBUG_ERR, "Cannot open PTT device \"%s\"\n",
rig->state.pttport.path);
break;
default:
rig_debug(RIG_DEBUG_ERR, "Unsupported PTT type %d\n",
rig->state.pttport.type.ptt);
}
switch(rig->state.dcdport.type.dcd) {
case RIG_DCD_NONE:
case RIG_DCD_RIG:
break;
case RIG_DCD_SERIAL_DSR:
case RIG_DCD_SERIAL_CTS:
rig->state.dcdport.fd = ser_open(&rig->state.dcdport);
if (rig->state.dcdport.fd < 0)
rig_debug(RIG_DEBUG_ERR, "Cannot open DCD device \"%s\"\n",
rig->state.dcdport.path);
break;
case RIG_DCD_PARALLEL:
rig->state.dcdport.fd = par_open(&rig->state.dcdport);
if (rig->state.dcdport.fd < 0)
rig_debug(RIG_DEBUG_ERR, "Cannot open DCD device \"%s\"\n",
rig->state.dcdport.path);
break;
default:
rig_debug(RIG_DEBUG_ERR, "Unsupported DCD type %d\n",
rig->state.dcdport.type.dcd);
}
add_opened_rig(rig);
/*
* Maybe the backend has something to initialize
* FIXME: check rig_open() return code
*/
if (caps->rig_open != NULL)
caps->rig_open(rig);
/*
* trigger state->current_vfo first retrieval
*/
if (!caps->targetable_vfo && caps->get_vfo)
caps->get_vfo(rig, &vfo);
return RIG_OK;
}
/**
* \brief close the communication to the rig
* \param rig The #RIG handle of the radio to be closed
*
* Closes communication to a radio which \a RIG handle has been passed
* by argument that was previously open with rig_open().
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_cleanup(), rig_open()
*/
int rig_close(RIG *rig)
{
const struct rig_caps *caps;
struct rig_state *rs;
rig_debug(RIG_DEBUG_VERBOSE,"rig:rig_close called \n");
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
rs = &rig->state;
if (rs->transceive) {
/*
* TODO: check error codes et al.
*/
remove_trn_rig(rig);
}
/*
* Let the backend say 73s to the rig
*/
if (caps->rig_close)
caps->rig_close(rig);
/*
* FIXME: what happens if PTT and rig ports are the same?
* (eg. ptt_type = RIG_PTT_SERIAL)
*/
switch(rs->pttport.type.ptt) {
case RIG_PTT_NONE:
case RIG_PTT_RIG:
break;
case RIG_PTT_SERIAL_RTS:
case RIG_PTT_SERIAL_DTR:
ser_close(&rs->pttport);
break;
case RIG_PTT_PARALLEL:
par_close(&rs->pttport);
break;
default:
rig_debug(RIG_DEBUG_ERR, "Unsupported PTT type %d\n",
rs->pttport.type.ptt);
}
switch(rs->dcdport.type.dcd) {
case RIG_DCD_NONE:
case RIG_DCD_RIG:
break;
case RIG_DCD_SERIAL_DSR:
case RIG_DCD_SERIAL_CTS:
ser_close(&rs->dcdport);
break;
case RIG_DCD_PARALLEL:
par_close(&rs->dcdport);
break;
default:
rig_debug(RIG_DEBUG_ERR, "Unsupported DCD type %d\n",
rs->dcdport.type.dcd);
}
rs->dcdport.fd = rs->pttport.fd = -1;
if (rs->rigport.fd != -1) {
if (!rs->rigport.stream)
fclose(rs->rigport.stream); /* this closes also fd */
else
close(rs->rigport.fd);
rs->rigport.fd = -1;
rs->rigport.stream = NULL;
}
remove_opened_rig(rig);
return RIG_OK;
}
/**
* \brief release a rig handle and free associated memory
* \param rig The #RIG handle of the radio to be closed
*
* Releases a rig struct which port has eventualy been closed already
* with rig_close().
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_init(), rig_close()
*/
int rig_cleanup(RIG *rig)
{
rig_debug(RIG_DEBUG_VERBOSE,"rig:rig_cleanup called \n");
if (!rig || !rig->caps)
return -RIG_EINVAL;
/*
* basically free up the priv struct
*/
if (rig->caps->rig_cleanup)
rig->caps->rig_cleanup(rig);
free(rig);
return RIG_OK;
}
/**
* \brief set the frequency of the target VFO
* \param rig The rig handle
* \param vfo The target VFO
* \param freq The frequency to set to
*
* Sets the frequency of the target VFO.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_freq()
*/
int rig_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (rig->state.vfo_comp != 0.0)
freq += (freq_t)((double)rig->state.vfo_comp * freq);
if (caps->set_freq == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_freq(rig, vfo, freq);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_freq(rig, vfo, freq);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the frequency of the target VFO
* \param rig The rig handle
* \param vfo The target VFO
* \param freq The location where to store the current frequency
*
* Retrieves the frequency of the target VFO.
* The value stored at \a freq location equals RIG_FREQ_NONE when the current
* frequency of the VFO is not defined (e.g. blank memory).
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_freq()
*/
int rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !freq)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_freq == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo) {
retcode = caps->get_freq(rig, vfo, freq);
} else {
if (!caps->set_vfo)
return -RIG_ENAVAIL;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_freq(rig, vfo, freq);
caps->set_vfo(rig, curr_vfo);
}
/* VFO compensation */
if (rig->state.vfo_comp != 0.0)
*freq += (freq_t)(rig->state.vfo_comp * (*freq));
return retcode;
}
/**
* \brief set the mode of the target VFO
* \param rig The rig handle
* \param vfo The target VFO
* \param mode The mode to set to
* \param width The passband width to set to
*
* Sets the mode and associated passband of the target VFO.
* The passband \a width must be supported by the backend of the rig.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_mode()
*/
int rig_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_mode == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_mode(rig, vfo, mode, width);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_mode(rig, vfo, mode, width);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the mode of the target VFO
* \param rig The rig handle
* \param vfo The target VFO
* \param mode The location where to store the current mode
* \param width The location where to store the current passband width
*
* Retrieves the mode and passband of the target VFO.
* If the backend is unable to determine the width, the \a width
* will be set to RIG_PASSBAND_NORMAL as a default.
* The value stored at \a mode location equals RIG_MODE_NONE when the current
* mode of the VFO is not defined (e.g. blank memory).
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_mode()
*/
int rig_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !mode || !width)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_mode == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_mode(rig, vfo, mode, width);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_mode(rig, vfo, mode, width);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the normal passband of a mode
* \param rig The rig handle
* \param mode The mode to get the passband
*
* Returns the normal (default) passband for the given \a mode.
*
* \return the passband in Hz if the operation has been sucessful,
* or a 0 if an error occured (passband not found, whatever).
*
* \sa rig_passband_narrow(), rig_passband_wide()
*/
pbwidth_t rig_passband_normal(RIG *rig, rmode_t mode)
{
const struct rig_state *rs;
int i;
if (!rig)
return 0; /* huhu! */
rs = &rig->state;
for (i=0; i<FLTLSTSIZ && rs->filters[i].modes; i++) {
if (rs->filters[i].modes & mode) {
return rs->filters[i].width;
}
}
return 0;
}
/**
* \brief get the narrow passband of a mode
* \param rig The rig handle
* \param mode The mode to get the passband
*
* Returns the narrow (closest) passband for the given \a mode.
* EXAMPLE: rig_set_mode(my_rig, RIG_MODE_LSB,
* rig_passband_narrow(my_rig, RIG_MODE_LSB) );
*
* \return the passband in Hz if the operation has been sucessful,
* or a 0 if an error occured (passband not found, whatever).
*
* \sa rig_passband_normal(), rig_passband_wide()
*/
pbwidth_t rig_passband_narrow(RIG *rig, rmode_t mode)
{
const struct rig_state *rs;
pbwidth_t normal;
int i;
if (!rig)
return 0; /* huhu! */
rs = &rig->state;
for (i=0; i<FLTLSTSIZ-1 && rs->filters[i].modes; i++) {
if (rs->filters[i].modes & mode) {
normal = rs->filters[i].width;
for (i++; i<FLTLSTSIZ && rs->filters[i].modes; i++) {
if ((rs->filters[i].modes & mode) &&
(rs->filters[i].width < normal)) {
return rs->filters[i].width;
}
}
return 0;
}
}
return 0;
}
/**
* \brief get the wide passband of a mode
* \param rig The rig handle
* \param mode The mode to get the passband
*
* Returns the wide (default) passband for the given \a mode.
* EXAMPLE: rig_set_mode(my_rig, RIG_MODE_AM,
* rig_passband_wide(my_rig, RIG_MODE_AM) );
*
* \return the passband in Hz if the operation has been sucessful,
* or a 0 if an error occured (passband not found, whatever).
*
* \sa rig_passband_narrow(), rig_passband_normal()
*/
pbwidth_t rig_passband_wide(RIG *rig, rmode_t mode)
{
const struct rig_state *rs;
pbwidth_t normal;
int i;
if (!rig)
return 0; /* huhu! */
rs = &rig->state;
for (i=0; i<FLTLSTSIZ-1 && rs->filters[i].modes; i++) {
if (rs->filters[i].modes & mode) {
normal = rs->filters[i].width;
for (i++; i<FLTLSTSIZ && rs->filters[i].modes; i++) {
if ((rs->filters[i].modes & mode) &&
(rs->filters[i].width > normal)) {
return rs->filters[i].width;
}
}
return 0;
}
}
return 0;
}
/**
* \brief set the current VFO
* \param rig The rig handle
* \param vfo The VFO to set to
*
* Sets the current VFO. The VFO can be RIG_VFO_A, RIG_VFO_B, RIG_VFO_C
* for VFOA, VFOB, VFOC respectively or RIG_VFO_MEM for Memory mode.
* Supported VFOs depends on rig capabilities.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_vfo()
*/
int rig_set_vfo(RIG *rig, vfo_t vfo)
{
const struct rig_caps *caps;
int retcode;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_vfo == NULL)
return -RIG_ENAVAIL;
retcode= caps->set_vfo(rig, vfo);
if (retcode == RIG_OK)
rig->state.current_vfo = vfo;
return retcode;
}
/**
* \brief get the current VFO
* \param rig The rig handle
* \param vfo The location where to store the current VFO
*
* Retrieves the current VFO. The VFO can be RIG_VFO_A, RIG_VFO_B, RIG_VFO_C
* for VFOA, VFOB, VFOC respectively or RIG_VFO_MEM for Memory mode.
* Supported VFOs depends on rig capabilities.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_vfo()
*/
int rig_get_vfo(RIG *rig, vfo_t *vfo)
{
const struct rig_caps *caps;
int retcode;
if (!rig || !rig->caps || !vfo)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_vfo == NULL)
return -RIG_ENAVAIL;
retcode= caps->get_vfo(rig, vfo);
if (retcode == RIG_OK)
rig->state.current_vfo = *vfo;
return retcode;
}
/**
* \brief set PTT on/off
* \param rig The rig handle
* \param vfo The target VFO
* \param ptt The PTT status to set to
*
* Sets "Push-To-Talk" on/off.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_ptt()
*/
int rig_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
switch (rig->state.pttport.type.ptt) {
case RIG_PTT_RIG:
if (caps->set_ptt == NULL)
return -RIG_ENIMPL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_ptt(rig, vfo, ptt);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_ptt(rig, vfo, ptt);
caps->set_vfo(rig, curr_vfo);
return retcode;
break;
case RIG_PTT_SERIAL_DTR:
case RIG_PTT_SERIAL_RTS:
ser_ptt_set(&rig->state.pttport, ptt);
break;
case RIG_PTT_PARALLEL:
par_ptt_set(&rig->state.pttport, ptt);
break;
case RIG_PTT_NONE:
return -RIG_ENAVAIL; /* not available */
default:
return -RIG_EINVAL;
}
return RIG_OK;
}
/**
* \brief get the status of the PTT
* \param rig The rig handle
* \param vfo The target VFO
* \param ptt The location where to store the status of the PTT
*
* Retrieves the status of PTT (are we on the air?).
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_ptt()
*/
int rig_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !ptt)
return -RIG_EINVAL;
caps = rig->caps;
switch (rig->state.pttport.type.ptt) {
case RIG_PTT_RIG:
if (caps->get_ptt == NULL)
return -RIG_ENIMPL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_ptt(rig, vfo, ptt);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_ptt(rig, vfo, ptt);
caps->set_vfo(rig, curr_vfo);
return retcode;
break;
case RIG_PTT_SERIAL_RTS:
case RIG_PTT_SERIAL_DTR:
ser_ptt_get(&rig->state.pttport, ptt);
break;
case RIG_PTT_PARALLEL:
par_ptt_get(&rig->state.pttport, ptt);
break;
case RIG_PTT_NONE:
return -RIG_ENAVAIL; /* not available */
default:
return -RIG_EINVAL;
}
return RIG_OK;
}
/**
* \brief get the status of the DCD
* \param rig The rig handle
* \param vfo The target VFO
* \param dcd The location where to store the status of the DCD
*
* Retrieves the status of DCD (is squelch open?).
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
*/
int rig_get_dcd(RIG *rig, vfo_t vfo, dcd_t *dcd)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !dcd)
return -RIG_EINVAL;
caps = rig->caps;
switch (rig->state.dcdport.type.dcd) {
case RIG_DCD_RIG:
if (caps->get_dcd == NULL)
return -RIG_ENIMPL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_dcd(rig, vfo, dcd);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_dcd(rig, vfo, dcd);
caps->set_vfo(rig, curr_vfo);
return retcode;
break;
case RIG_DCD_SERIAL_CTS:
case RIG_DCD_SERIAL_DSR:
ser_dcd_get(&rig->state.dcdport, dcd);
break;
case RIG_DCD_PARALLEL:
par_dcd_get(&rig->state.dcdport, dcd);
break;
case RIG_DCD_NONE:
return -RIG_ENAVAIL; /* not available */
default:
return -RIG_EINVAL;
}
return RIG_OK;
}
/**
* \brief set the repeater shift
* \param rig The rig handle
* \param vfo The target VFO
* \param rptr_shift The repeater shift to set to
*
* Sets the current repeater shift.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_rptr_shift()
*/
int rig_set_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t rptr_shift)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_rptr_shift == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_rptr_shift(rig, vfo, rptr_shift);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_rptr_shift(rig, vfo, rptr_shift);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current repeater shift
* \param rig The rig handle
* \param vfo The target VFO
* \param rptr_shift The location where to store the current repeater shift
*
* Retrieves the current repeater shift.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_rptr_shift()
*/
int rig_get_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t *rptr_shift)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !rptr_shift)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_rptr_shift == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_rptr_shift(rig, vfo, rptr_shift);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_rptr_shift(rig, vfo, rptr_shift);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set the repeater offset
* \param rig The rig handle
* \param vfo The target VFO
* \param rptr_offs The VFO to set to
*
* Sets the current repeater offset.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_rptr_offs()
*/
int rig_set_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t rptr_offs)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_rptr_offs == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_rptr_offs(rig, vfo, rptr_offs);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_rptr_offs(rig, vfo, rptr_offs);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current repeater offset
* \param rig The rig handle
* \param vfo The target VFO
* \param rptr_offs The location where to store the current repeater offset
*
* Retrieves the current repeater offset.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_rptr_offs()
*/
int rig_get_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t *rptr_offs)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !rptr_offs)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_rptr_offs == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_rptr_offs(rig, vfo, rptr_offs);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_rptr_offs(rig, vfo, rptr_offs);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set the split frequencies
* \param rig The rig handle
* \param vfo The target VFO
* \param tx_freq The transmit split frequency to set to
*
* Sets the split frequencies.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_split_freq()
*/
int rig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_split_freq == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_split_freq(rig, vfo, tx_freq);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_split_freq(rig, vfo, tx_freq);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current split frequencies
* \param rig The rig handle
* \param vfo The target VFO
* \param tx_freq The location where to store the current transmit split frequency
*
* Retrieves the current split frequencies.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_split_freq()
*/
int rig_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !tx_freq)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_split_freq == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_split_freq(rig, vfo, tx_freq);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_split_freq(rig, vfo, tx_freq);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set the split modes
* \param rig The rig handle
* \param vfo The target VFO
* \param tx_mode The transmit split mode to set to
* \param tx_width The transmit split width to set to
*
* Sets the split mode.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_split_mode()
*/
int rig_set_split_mode(RIG *rig, vfo_t vfo, rmode_t tx_mode, pbwidth_t tx_width)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_split_mode == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_split_mode(rig, vfo, tx_mode, tx_width);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_split_mode(rig, vfo, tx_mode, tx_width);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current split modes
* \param rig The rig handle
* \param vfo The target VFO
* \param tx_mode The location where to store the current transmit split mode
* \param tx_width The location where to store the current transmit split width
*
* Retrieves the current split mode.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_split_mode()
*/
int rig_get_split_mode(RIG *rig, vfo_t vfo, rmode_t *tx_mode, pbwidth_t *tx_width)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !tx_mode || !tx_width)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_split_mode == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_split_mode(rig, vfo, tx_mode, tx_width);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_split_mode(rig, vfo, tx_mode, tx_width);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set the split mode
* \param rig The rig handle
* \param vfo The target VFO
* \param split The split mode to set to
*
* Sets the current split mode.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_split()
*/
int rig_set_split(RIG *rig, vfo_t vfo, split_t split)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_split == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_split(rig, vfo, split);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_split(rig, vfo, split);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current split mode
* \param rig The rig handle
* \param vfo The target VFO
* \param split The location where to store the current split mode
*
* Retrieves the current split mode.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_split()
*/
int rig_get_split(RIG *rig, vfo_t vfo, split_t *split)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !split)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_split == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_split(rig, vfo, split);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_split(rig, vfo, split);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set the RIT
* \param rig The rig handle
* \param vfo The target VFO
* \param rit The RIT offset to adjust to
*
* Sets the current RIT offset. A value of 0 for \a rit disables RIT.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_rit()
*/
int rig_set_rit(RIG *rig, vfo_t vfo, shortfreq_t rit)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_rit == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_rit(rig, vfo, rit);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_rit(rig, vfo, rit);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current RIT offset
* \param rig The rig handle
* \param vfo The target VFO
* \param rit The location where to store the current RIT offset
*
* Retrieves the current RIT offset.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_rit()
*/
int rig_get_rit(RIG *rig, vfo_t vfo, shortfreq_t *rit)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !rit)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_rit == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_rit(rig, vfo, rit);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_rit(rig, vfo, rit);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set the XIT
* \param rig The rig handle
* \param vfo The target VFO
* \param xit The XIT offset to adjust to
*
* Sets the current XIT offset. A value of 0 for \a xit disables XIT.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_xit()
*/
int rig_set_xit(RIG *rig, vfo_t vfo, shortfreq_t xit)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_xit == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_xit(rig, vfo, xit);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_xit(rig, vfo, xit);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current XIT offset
* \param rig The rig handle
* \param vfo The target VFO
* \param xit The location where to store the current XIT offset
*
* Retrieves the current XIT offset.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_xit()
*/
int rig_get_xit(RIG *rig, vfo_t vfo, shortfreq_t *xit)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !xit)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_xit == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_xit(rig, vfo, xit);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_xit(rig, vfo, xit);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set the Tuning Step
* \param rig The rig handle
* \param vfo The target VFO
* \param ts The tuning step to set to
*
* Sets the Tuning Step.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_ts()
*/
int rig_set_ts(RIG *rig, vfo_t vfo, shortfreq_t ts)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_ts == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_ts(rig, vfo, ts);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_ts(rig, vfo, ts);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current Tuning Step
* \param rig The rig handle
* \param vfo The target VFO
* \param ts The location where to store the current tuning step
*
* Retrieves the current tuning step.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_ts()
*/
int rig_get_ts(RIG *rig, vfo_t vfo, shortfreq_t *ts)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !ts)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_ts == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_ts(rig, vfo, ts);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_ts(rig, vfo, ts);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set the antenna
* \param rig The rig handle
* \param vfo The target VFO
* \param ant The anntena to select
*
* Sets the current antenna.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_ant()
*/
int rig_set_ant(RIG *rig, vfo_t vfo, ant_t ant)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_ant == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_ant(rig, vfo, ant);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_ant(rig, vfo, ant);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current antenna
* \param rig The rig handle
* \param vfo The target VFO
* \param ant The location where to store the current antenna
*
* Retrieves the current antenna.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_ant()
*/
int rig_get_ant(RIG *rig, vfo_t vfo, ant_t *ant)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !ant)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_ant == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_ant(rig, vfo, ant);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_ant(rig, vfo, ant);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief conversion utility from relative range to absolute in mW
* \param rig The rig handle
* \param mwpower The location where to store the converted power in mW
* \param power The relative power
* \param freq The frequency where the conversion should take place
* \param mode The mode where the conversion should take place
*
* Converts a power value expressed in a range on a [0.0 .. 1.0] relative
* scale to the real transmit power in milli Watts the radio would emit.
* The \a freq and \a mode where the conversion should take place must be
* also provided since the relative power is peculiar to a specific
* freq and mode range of the radio.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_mW2power()
*/
int rig_power2mW(RIG *rig, unsigned int *mwpower, float power, freq_t freq, rmode_t mode)
{
const freq_range_t *txrange;
if (!rig || !rig->caps || !mwpower || power<0.0 || power>1.0)
return -RIG_EINVAL;
if (rig->caps->power2mW != NULL)
return rig->caps->power2mW(rig, mwpower, power, freq, mode);
txrange = rig_get_range(rig->state.tx_range_list, freq, mode);
if (!txrange) {
/*
* freq is not on the tx range!
*/
return -RIG_ECONF; /* could be RIG_EINVAL ? */
}
*mwpower = (unsigned int)(power * txrange->high_power);
return RIG_OK;
}
/**
* \brief conversion utility from absolute in mW to relative range
* \param rig The rig handle
* \param power The location where to store the converted relative power
* \param mwpower The power in mW
* \param freq The frequency where the conversion should take place
* \param mode The mode where the conversion should take place
*
* Converts a power value expressed in the real transmit power in milli Watts
* the radio would emit to a range on a [0.0 .. 1.0] relative scale.
* The \a freq and \a mode where the conversion should take place must be
* also provided since the relative power is peculiar to a specific
* freq and mode range of the radio.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_power2mW()
*/
int rig_mW2power(RIG *rig, float *power, unsigned int mwpower, freq_t freq, rmode_t mode)
{
const freq_range_t *txrange;
if (!rig || !rig->caps || !power || mwpower==0)
return -RIG_EINVAL;
if (rig->caps->mW2power != NULL)
return rig->caps->mW2power(rig, power, mwpower, freq, mode);
txrange = rig_get_range(rig->state.tx_range_list, freq, mode);
if (!txrange) {
/*
* freq is not on the tx range!
*/
return -RIG_ECONF; /* could be RIG_EINVAL ? */
}
if (mwpower == 0) {
*power = 0.0;
return RIG_OK;
}
*power = (float)txrange->high_power/mwpower;
if (*power > 1.0)
*power = 1.0;
return (mwpower>txrange->high_power? RIG_OK : RIG_ETRUNC);
}
/**
* \brief get the best frequency resolution of the rig
* \param rig The rig handle
* \param mode The mode where the conversion should take place
*
* Returns the best frequency resolution of the rig, for a given \a mode.
*
* \return the frequency resolution in Hertz if the operation h
* has been sucessful, otherwise a negative value if an error occured.
*
*/
shortfreq_t rig_get_resolution(RIG *rig, rmode_t mode)
{
const struct rig_state *rs;
int i;
if (!rig || !rig->caps || !mode)
return -RIG_EINVAL;
rs = &rig->state;
for (i=0; i<TSLSTSIZ && rs->tuning_steps[i].ts; i++) {
if (rs->tuning_steps[i].modes & mode)
return rs->tuning_steps[i].ts;
}
return -RIG_EINVAL;
}
/**
* \brief set CTCSS sub-tone frequency
* \param rig The rig handle
* \param vfo The target VFO
* \param tone The tone to set to
*
* Sets the current Continuous Tone Controlled Squelch System (CTCSS)
* sub-audible tone frequency.
* \note the \a tone integer is NOT in Hz, but in tenth of Hz! This way,
* if you want to set a subaudible tone of 88.5 Hz for example,
* then pass 885 to this function.
* Also, to disable Tone encoding, set \a tone to 0 (FIXME: not clear in API).
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_ctcss_tone(), rig_set_ctcss_sql()
*/
int rig_set_ctcss_tone(RIG *rig, vfo_t vfo, tone_t tone)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_ctcss_tone == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_ctcss_tone(rig, vfo, tone);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_ctcss_tone(rig, vfo, tone);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current CTCSS sub-tone frequency
* \param rig The rig handle
* \param vfo The target VFO
* \param tone The location where to store the current tone
*
* Retrieves the current Continuous Tone Controlled Squelch System (CTCSS)
* sub-audible tone frequency.
* \note the \a *tone integer is NOT in Hz, but in tenth of Hz! This way,
* if the function rig_get_ctcss_tone() returns a subaudible tone of 885
* for example, then the real tone is 88.5 Hz.
* Also, a value of 0 for \a *tone means the Tone encoding is disabled.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_ctcss_tone(), rig_get_ctcss_sql()
*/
int rig_get_ctcss_tone(RIG *rig, vfo_t vfo, tone_t *tone)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !tone)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_ctcss_tone == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_ctcss_tone(rig, vfo, tone);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_ctcss_tone(rig, vfo, tone);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set the current encoding DCS code
* \param rig The rig handle
* \param vfo The target VFO
* \param code The tone to set to
*
* Sets the current encoding Digitally-Coded Squelch code.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_dcs_code(), rig_set_dcs_sql()
*/
int rig_set_dcs_code(RIG *rig, vfo_t vfo, tone_t code)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_dcs_code == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_dcs_code(rig, vfo, code);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_dcs_code(rig, vfo, code);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current encoding DCS code
* \param rig The rig handle
* \param vfo The target VFO
* \param code The location where to store the current tone
*
* Retrieves the current encoding Digitally-Coded Squelch code.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_dcs_code(), rig_get_dcs_sql()
*/
int rig_get_dcs_code(RIG *rig, vfo_t vfo, tone_t *code)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !code)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_dcs_code == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_dcs_code(rig, vfo, code);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_dcs_code(rig, vfo, code);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set CTCSS squelch
* \param rig The rig handle
* \param vfo The target VFO
* \param tone The PL tone to set the squelch to
*
* Sets the current Continuous Tone Controlled Squelch System (CTCSS)
* sub-audible *squelch* tone.
* \note \a tone is NOT in Hz, but in tenth of Hz! This way,
* if you want to set subaudible squelch tone of 88.5 Hz for example,
* then pass 885 to this function.
* Also, to disable Tone squelch, set \a tone to 0 (FIXME: not clear in API).
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_ctcss_sql(), rig_set_ctcss_tone()
*/
int rig_set_ctcss_sql(RIG *rig, vfo_t vfo, tone_t tone)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_ctcss_sql == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_ctcss_sql(rig, vfo, tone);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_ctcss_sql(rig, vfo, tone);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current CTCSS squelch
* \param rig The rig handle
* \param vfo The target VFO
* \param tone The location where to store the current tone
*
* Retrieves the current Continuous Tone Controlled Squelch System (CTCSS)
* sub-audible *squelch* tone.
* \note \a *tone is NOT in Hz, but in tenth of Hz! This way,
* if the function rig_get_ctcss_sql() returns a subaudible tone of 885
* for example, then the real tone is 88.5 Hz.
* Also, a value of 0 for @tone means the Tone squelch is disabled.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_ctcss_sql(), rig_get_ctcss_tone()
*/
int rig_get_ctcss_sql(RIG *rig, vfo_t vfo, tone_t *tone)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !tone)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_ctcss_sql == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_ctcss_sql(rig, vfo, tone);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_ctcss_sql(rig, vfo, tone);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set the current DCS code
* \param rig The rig handle
* \param vfo The target VFO
* \param code The tone to set to
*
* Sets the current Digitally-Coded *Squelch* code.
*
* \return returns RIG_OK if the operation has been sucessful, ortherwise
* a negative value if an error occured (in which case, cause is set
* appropriately).
*
* \sa rig_get_dcs_sql(), rig_set_dcs_code()
*/
int rig_set_dcs_sql(RIG *rig, vfo_t vfo, tone_t code)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_dcs_sql == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_dcs_sql(rig, vfo, code);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_dcs_sql(rig, vfo, code);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current DCS code
* \param rig The rig handle
* \param vfo The target VFO
* \param code The location where to store the current tone
*
* Retrieves the current Digitally-Coded *Squelch* code.
*
* \return RIG_OK if the operation has been sucessful, ortherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_dcs_sql(), rig_get_dcs_code()
*/
int rig_get_dcs_sql(RIG *rig, vfo_t vfo, tone_t *code)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !code)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_dcs_sql == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_dcs_sql(rig, vfo, code);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_dcs_sql(rig, vfo, code);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief turn on/off the radio
* \param rig The rig handle
* \param status The status to set to
*
* turns on/off the radio.
* See #RIG_POWER_ON, #RIG_POWER_OFF and #RIG_POWER_STANDBY defines
* for the \a status.
*
* \return RIG_OK if the operation has been sucessful, ortherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_powerstat()
*/
int rig_set_powerstat(RIG *rig, powerstat_t status)
{
if (!rig || !rig->caps)
return -RIG_EINVAL;
if (rig->caps->set_powerstat == NULL)
return -RIG_ENAVAIL;
return rig->caps->set_powerstat(rig, status);
}
/**
* \brief get the on/off status of the radio
* \param rig The rig handle
* \param status The locatation where to store the current status
*
* Retrieve the status of the radio. See RIG_POWER_ON, RIG_POWER_OFF and
* RIG_POWER_STANDBY defines for the \a status.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_powerstat()
*/
int rig_get_powerstat(RIG *rig, powerstat_t *status)
{
if (!rig || !rig->caps || !status)
return -RIG_EINVAL;
if (rig->caps->get_powerstat == NULL)
return -RIG_ENAVAIL;
return rig->caps->get_powerstat(rig, status);
}
/**
* \brief reset the radio
* \param rig The rig handle
* \param reset The reset operation to perform
*
* Resets the radio.
* See RIG_RESET_NONE, RIG_RESET_SOFT and RIG_RESET_MCALL defines
* for the \a reset.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
*/
int rig_reset(RIG *rig, reset_t reset)
{
if (!rig || !rig->caps)
return -RIG_EINVAL;
if (rig->caps->reset == NULL)
return -RIG_ENAVAIL;
return rig->caps->reset(rig, reset);
}
/**
* \brief try to guess a rig
* \param port A pointer describing a port linking the host to the rig
*
* Try to guess what is the model of rig pointed to by port.
* It can be very buggy, and mess up the radio at the other end.
* (but fun if it works!)
*
* \warning this is really Experimental, It has been tested only
* with IC-706MkIIG. any feedback welcome! --SF
*
* \return the rig model id according to the rig_model_t type if found,
* otherwise RIG_MODEL_NONE if unable to determine rig model.
*/
rig_model_t rig_probe(port_t *port)
{
if (!port)
return RIG_MODEL_NONE;
return rig_probe_all(port);
}
/**
* \brief set a radio level setting
* \param rig The rig handle
* \param vfo The target VFO
* \param level The level setting
* \param val The value to set the level setting to
*
* Sets the level of a setting.
* The level value \a val can be a float or an integer. See #value_t
* for more information.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_has_set_level(), rig_get_level()
*/
int rig_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_level == NULL || !rig_has_set_level(rig,level))
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_level(rig, vfo, level, val);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_level(rig, vfo, level, val);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the value of a level
* \param rig The rig handle
* \param vfo The target VFO
* \param level The level setting
* \param val The location where to store the value of \a level
*
* Retrieves the value of a \a level.
* The level value @val can be a float or an integer. See #value_t
* for more information.
*
* RIG_LEVEL_STRENGTH: \a val is an integer, representing the S Meter
* level in dB, according to the ideal S Meter scale. The ideal
* S Meter scale is as follow: S0=-54, S1=-48, S2=-42, S3=-36,
* S4=-30, S5=-24, S6=-18, S7=-12, S8=-6, S9=0, +10=10, +20=20,
* +30=30, +40=40, +50=50 and +60=60. This is the responsability
* of the backend to return values calibrated for this scale.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_has_get_level(), rig_set_level()
*/
int rig_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !val)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_level == NULL || !rig_has_get_level(rig,level))
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_level(rig, vfo, level, val);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_level(rig, vfo, level, val);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set a radio parameter
* \param rig The rig handle
* \param parm The parameter
* \param val The value to set the parameter sto
*
* Sets a parameter.
* The parameter value \a val can be a float or an integer. See #value_t
* for more information.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_has_set_parm(), rig_get_parm()
*/
int rig_set_parm(RIG *rig, setting_t parm, value_t val)
{
if (!rig || !rig->caps)
return -RIG_EINVAL;
if (rig->caps->set_parm == NULL || !rig_has_set_parm(rig,parm))
return -RIG_ENAVAIL;
return rig->caps->set_parm(rig, parm, val);
}
/**
* \brief get the value of a parameter
* \param rig The rig handle
* \param parm The parameter
* \param val The location where to store the value of @parm
*
* Retrieves the value of a \a parm.
* The parameter value \a val can be a float or an integer. See #value_t
* for more information.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_has_get_parm(), rig_set_parm()
*/
int rig_get_parm(RIG *rig, setting_t parm, value_t *val)
{
if (!rig || !rig->caps || !val)
return -RIG_EINVAL;
if (rig->caps->get_parm == NULL || !rig_has_get_parm(rig,parm))
return -RIG_ENAVAIL;
return rig->caps->get_parm(rig, parm, val);
}
/**
* \brief check retrieval ability of level settings
* \param rig The rig handle
* \param level The level settings
*
* Checks if a rig is capable of *getting* a level setting.
* Since the \a level is an OR'ed bitwise argument, more than
* one level can be checked at the same time.
*
* EXAMPLE: if (rig_has_get_level(my_rig, RIG_LVL_STRENGTH)) disp_Smeter();
*
* \return a bit map of supported level settings that can be retrieved,
* otherwise 0 if none supported.
*
* \sa rig_has_set_level(), rig_get_level()
*/
setting_t rig_has_get_level(RIG *rig, setting_t level)
{
if (!rig || !rig->caps)
return 0;
return (rig->state.has_get_level & level);
}
/**
* \brief check settable ability of level settings
* \param rig The rig handle
* \param level The level settings
*
* Checks if a rig can *set* a level setting.
* Since the \a level is an OR'ed bitwise argument, more than
* one level can be check at the same time.
*
* EXAMPLE: if (rig_has_set_level(my_rig, RIG_LVL_RFPOWER)) crank_tx();
*
* \return a bit map of supported level settings that can be set,
* otherwise 0 if none supported.
*
* \sa rig_has_get_level(), rig_set_level()
*/
setting_t rig_has_set_level(RIG *rig, setting_t level)
{
if (!rig || !rig->caps)
return 0;
return (rig->state.has_set_level & level);
}
/**
* \brief check retrieval ability of parameter settings
* \param rig The rig handle
* \param parm The parameter settings
*
* Checks if a rig is capable of *getting* a parm setting.
* Since the \a parm is an OR'ed bitwise argument, more than
* one parameter can be checked at the same time.
*
* EXAMPLE: if (rig_has_get_parm(my_rig, RIG_PARM_ANN)) good4you();
*
* \return a bit map of supported parameter settings that can be retrieved,
* otherwise 0 if none supported.
*
* \sa rig_has_set_parm(), rig_get_parm()
*/
setting_t rig_has_get_parm(RIG *rig, setting_t parm)
{
if (!rig || !rig->caps)
return 0;
return (rig->state.has_get_parm & parm);
}
/**
* \brief check settable ability of parameter settings
* \param rig The rig handle
* \param parm The parameter settings
*
* Checks if a rig can *set* a parameter setting.
* Since the \a parm is an OR'ed bitwise argument, more than
* one parameter can be check at the same time.
*
* EXAMPLE: if (rig_has_set_parm(my_rig, RIG_PARM_ANN)) announce_all();
*
* \return a bit map of supported parameter settings that can be set,
* otherwise 0 if none supported.
*
* \sa rig_has_get_parm(), rig_set_parm()
*/
setting_t rig_has_set_parm(RIG *rig, setting_t parm)
{
if (!rig || !rig->caps)
return 0;
return (rig->state.has_set_parm & parm);
}
/**
* \brief check ability of radio functions
* \param rig The rig handle
* \param func The functions
*
* Checks if a rig supports a set of functions.
* Since the \a func is an OR'ed bitwise argument, more than
* one function can be checked at the same time.
*
* EXAMPLE: if (rig_has_get_func(my_rig,RIG_FUNC_FAGC)) disp_fagc_button();
*
* \return a bit map of supported functions,
* otherwise 0 if none supported.
*
* \sa rig_has_set_func(), rig_get_func()
*/
setting_t rig_has_get_func(RIG *rig, setting_t func)
{
if (!rig || !rig->caps)
return 0;
return (rig->state.has_get_func & func);
}
/**
* \brief check ability of radio functions
* \param rig The rig handle
* \param func The functions
*
* Checks if a rig supports a set of functions.
* Since the \a func is an OR'ed bitwise argument, more than
* one function can be checked at the same time.
*
* EXAMPLE: if (rig_has_set_func(my_rig,RIG_FUNC_FAGC)) disp_fagc_button();
*
* \return a bit map of supported functions,
* otherwise 0 if none supported.
*
* \sa rig_set_func(), rig_has_get_func()
*/
setting_t rig_has_set_func(RIG *rig, setting_t func)
{
if (!rig || !rig->caps)
return 0;
return (rig->state.has_set_func & func);
}
/**
* \brief activate/desactivate functions of radio
* \param rig The rig handle
* \param vfo The target VFO
* \param func The functions to activate
* \param status The status (on or off) to set to
*
* Activate/desactivate functions of the radio.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_func()
*/
int rig_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_func == NULL || !rig_has_set_func(rig,func))
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_func(rig, vfo, func, status);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_func(rig, vfo, func, status);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the status of functions of the radio
* \param rig The rig handle
* \param vfo The target VFO
* \param func The functions to get the status
* \param status The location where to store the function status
*
* Retrieves the status of functions of the radio. Only the function bits
* set to 1 will be queried.
* On return, \a func will hold the status of functions (bit set to 1 =
* activated, bit set to 0 = desactivated).
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_func()
*/
int rig_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !func)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_func == NULL || !rig_has_get_func(rig,func))
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_func(rig, vfo, func, status);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_func(rig, vfo, func, status);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set the current memory channel number
* \param rig The rig handle
* \param vfo The target VFO
* \param ch The memory channel number
*
* Sets the current memory channel number.
* It is not mandatory for the radio to be in memory mode. Actually
* it depends on rigs. YMMV.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_mem()
*/
int rig_set_mem(RIG *rig, vfo_t vfo, int ch)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_mem == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_mem(rig, vfo, ch);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_mem(rig, vfo, ch);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief get the current memory channel number
* \param rig The rig handle
* \param vfo The target VFO
* \param ch The location where to store the current memory channel number
*
* Retrieves the current memory channel number.
* It is not mandatory for the radio to be in memory mode. Actually
* it depends on rigs. YMMV.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_mem()
*/
int rig_get_mem(RIG *rig, vfo_t vfo, int *ch)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !ch)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->get_mem == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->get_mem(rig, vfo, ch);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->get_mem(rig, vfo, ch);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
#ifdef WANT_OLD_VFO_TO_BE_REMOVED
/**
* rig_mv_ctl - perform Memory/VFO operations
* \param rig The rig handle
* \param vfo The target VFO
* \param op The Memory/VFO operation to perform
*
* Performs Memory/VFO operation.
* See #mv_op_t for more information.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
*/
int rig_mv_ctl(RIG *rig, vfo_t vfo, mv_op_t op)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->mv_ctl == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->mv_ctl(rig, vfo, op);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->mv_ctl(rig, vfo, op);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
#else
/**
* \brief check retrieval ability of VFO operations
* \param rig The rig handle
* \param op The VFO op
*
* Checks if a rig is capable of executing a VFO operation.
* Since the \a op is an OR'ed bitmap argument, more than
* one op can be checked at the same time.
*
* EXAMPLE: if (rig_has_vfo_op(my_rig, RIG_OP_CPY)) disp_VFOcpy_btn();
*
* \return a bit map mask of supported op settings that can be retrieved,
* otherwise 0 if none supported.
*
* \sa rig_vfo_op()
*/
vfo_op_t rig_has_vfo_op(RIG *rig, vfo_op_t op)
{
if (!rig || !rig->caps)
return 0;
return (rig->caps->vfo_ops & op);
}
/**
* \brief perform Memory/VFO operations
* \param rig The rig handle
* \param vfo The target VFO
* \param op The Memory/VFO operation to perform
*
* Performs Memory/VFO operation.
* See #vfo_op_t for more information.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_has_vfo_op()
*/
int rig_vfo_op(RIG *rig, vfo_t vfo, vfo_op_t op)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->vfo_op == NULL || !rig_has_vfo_op(rig,op))
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->vfo_op(rig, vfo, op);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->vfo_op(rig, vfo, op);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
#endif /* WANT_OLD_VFO_TO_BE_REMOVED */
/**
* \brief check availability of scaning functions
* \param rig The rig handle
* \param scan The scan op
*
* Checks if a rig is capable of performing a scan operation.
* Since the \a scan parameter is an OR'ed bitmap argument, more than
* one op can be checked at the same time.
*
* EXAMPLE: if (rig_has_scan(my_rig, RIG_SCAN_PRIO)) disp_SCANprio_btn();
*
* \return a bit map of supported scan settings that can be retrieved,
* otherwise 0 if none supported.
*
* \sa rig_scan()
*/
scan_t rig_has_scan(RIG *rig, scan_t scan)
{
if (!rig || !rig->caps)
return 0;
return (rig->caps->scan_ops & scan);
}
/**
* \brief perform Memory/VFO operations
* \param rig The rig handle
* \param vfo The target VFO
* \param scan The scanning operation to perform
* \param ch Optional channel argument used for the scan.
*
* Performs scanning operation.
* See #scan_t for more information.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_has_scan()
*/
int rig_scan(RIG *rig, vfo_t vfo, scan_t scan, int ch)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->scan == NULL ||
(scan!=RIG_SCAN_STOP && !rig_has_scan(rig, scan)))
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->scan(rig, vfo, scan, ch);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->scan(rig, vfo, scan, ch);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief send DTMF digits
* \param rig The rig handle
* \param vfo The target VFO
* \param digits Digits to be send
*
* Sends DTMF digits.
* See DTMF change speed, etc. (TODO).
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
*/
int rig_send_dtmf(RIG *rig, vfo_t vfo, const char *digits)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !digits)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->send_dtmf == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->send_dtmf(rig, vfo, digits);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->send_dtmf(rig, vfo, digits);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief receive DTMF digits
* \param rig The rig handle
* \param vfo The target VFO
* \param digits Location where the digits are to be stored
* \param length in: max length of buffer, out: number really read.
*
* Receives DTMF digits (not blocking).
* See DTMF change speed, etc. (TODO).
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
*/
int rig_recv_dtmf(RIG *rig, vfo_t vfo, char *digits, int *length)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !digits || !length)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->recv_dtmf == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->recv_dtmf(rig, vfo, digits, length);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->recv_dtmf(rig, vfo, digits, length);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief send morse code
* \param rig The rig handle
* \param vfo The target VFO
* \param msg Message to be sent
*
* Sends morse message.
* See keyer change speed, etc. (TODO).
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
*/
int rig_send_morse(RIG *rig, vfo_t vfo, const char *msg)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps || !msg)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->send_morse == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->send_morse(rig, vfo, msg);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->send_morse(rig, vfo, msg);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief set the current memory bank
* \param rig The rig handle
* \param vfo The target VFO
* \param bank The memory bank
*
* Sets the current memory bank number.
* It is not mandatory for the radio to be in memory mode. Actually
* it depends on rigs. YMMV.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_mem()
*/
int rig_set_bank(RIG *rig, vfo_t vfo, int bank)
{
const struct rig_caps *caps;
int retcode;
vfo_t curr_vfo;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (caps->set_bank == NULL)
return -RIG_ENAVAIL;
if (caps->targetable_vfo || vfo == RIG_VFO_CURR ||
vfo == rig->state.current_vfo)
return caps->set_bank(rig, vfo, bank);
if (!caps->set_vfo)
return -RIG_ENTARGET;
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
return retcode;
retcode = caps->set_bank(rig, vfo, bank);
caps->set_vfo(rig, curr_vfo);
return retcode;
}
/**
* \brief save all the data associated with current VFO
* \param rig The rig handle
* \param chan The location where to store the channel data
*
* Gets all the data associated with current VFO.
* See #channel_t for more information.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \todo return code checking
* \sa rig_get_channel()
*/
int rig_save_channel(RIG *rig, channel_t *chan)
{
int i;
int chan_num;
if (!rig || !chan)
return -RIG_EINVAL;
chan_num = chan->channel_num;
memset(chan, 0, sizeof(channel_t));
chan->channel_num = chan_num;
rig_get_vfo(rig, &chan->vfo);
rig_get_freq(rig, RIG_VFO_CURR, &chan->freq);
rig_get_mode(rig, RIG_VFO_CURR, &chan->mode, &chan->width);
rig_get_split(rig, RIG_VFO_CURR, &chan->split);
if (chan->split != RIG_SPLIT_OFF) {
rig_get_split_freq(rig, RIG_VFO_CURR, &chan->tx_freq);
rig_get_split_mode(rig, RIG_VFO_CURR, &chan->tx_mode, &chan->tx_width);
}
rig_get_rptr_shift(rig, RIG_VFO_CURR, &chan->rptr_shift);
rig_get_rptr_offs(rig, RIG_VFO_CURR, &chan->rptr_offs);
for (i=0; i<RIG_SETTING_MAX; i++)
rig_get_level(rig, RIG_VFO_CURR, rig_idx2setting(i), &chan->levels[i]);
rig_get_ant(rig, RIG_VFO_CURR, &chan->ant);
rig_get_ts(rig, RIG_VFO_CURR, &chan->tuning_step);
rig_get_rit(rig, RIG_VFO_CURR, &chan->rit);
rig_get_xit(rig, RIG_VFO_CURR, &chan->xit);
chan->funcs = 0;
for (i=0; i<RIG_SETTING_MAX; i++) {
int fstatus;
rig_get_func(rig, RIG_VFO_CURR, rig_idx2setting(i), &fstatus);
chan->funcs |= fstatus? rig_idx2setting(i) : 0;
}
rig_get_ctcss_tone(rig, RIG_VFO_CURR, &chan->ctcss_tone);
rig_get_ctcss_sql(rig, RIG_VFO_CURR, &chan->ctcss_sql);
rig_get_dcs_code(rig, RIG_VFO_CURR, &chan->dcs_code);
rig_get_dcs_sql(rig, RIG_VFO_CURR, &chan->dcs_sql);
/* rig_get_mem_name(rig, RIG_VFO_CURR, chan->channel_desc); */
return RIG_OK;
}
/**
* \brief restore all the data associated with current VFO
* \param rig The rig handle
* \param chan The location where to store the channel data
*
* Sets all the data associated with current VFO.
* See #channel_t for more information.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \todo return code checking
* \sa rig_get_channel()
*/
int rig_restore_channel(RIG *rig, const channel_t *chan)
{
int i;
if (!rig || !chan)
return -RIG_EINVAL;
rig_set_vfo(rig, chan->vfo); /* huh!? */
rig_set_freq(rig, RIG_VFO_CURR, chan->freq);
rig_set_mode(rig, RIG_VFO_CURR, chan->mode, chan->width);
rig_set_split(rig, RIG_VFO_CURR, chan->split);
if (chan->split != RIG_SPLIT_OFF) {
rig_set_split_freq(rig, RIG_VFO_CURR, chan->tx_freq);
rig_set_split_mode(rig, RIG_VFO_CURR, chan->tx_mode, chan->tx_width);
}
rig_set_rptr_shift(rig, RIG_VFO_CURR, chan->rptr_shift);
rig_set_rptr_offs(rig, RIG_VFO_CURR, chan->rptr_offs);
for (i=0; i<RIG_SETTING_MAX; i++)
rig_set_level(rig, RIG_VFO_CURR, rig_idx2setting(i), chan->levels[i]);
rig_set_ant(rig, RIG_VFO_CURR, chan->ant);
rig_set_ts(rig, RIG_VFO_CURR, chan->tuning_step);
rig_set_rit(rig, RIG_VFO_CURR, chan->rit);
rig_set_xit(rig, RIG_VFO_CURR, chan->xit);
for (i=0; i<RIG_SETTING_MAX; i++)
rig_set_func(rig, RIG_VFO_CURR, rig_idx2setting(i),
chan->funcs & rig_idx2setting(i));
rig_set_ctcss_tone(rig, RIG_VFO_CURR, chan->ctcss_tone);
rig_set_ctcss_sql(rig, RIG_VFO_CURR, chan->ctcss_sql);
rig_set_dcs_code(rig, RIG_VFO_CURR, chan->dcs_code);
rig_set_dcs_sql(rig, RIG_VFO_CURR, chan->dcs_sql);
/* rig_set_mem_name(rig, RIG_VFO_CURR, chan->channel_desc); */
return RIG_OK;
}
/**
* \brief set channel data
* \param rig The rig handle
* \param chan The location of data to set for this channel
*
* Sets the data associated with a channel.
* See #channel_t for more information.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_channel()
*/
int rig_set_channel(RIG *rig, const channel_t *chan)
{
channel_t curr_chan;
int curr_chan_num;
vfo_t curr_vfo;
if (!rig || !rig->caps || !chan)
return -RIG_EINVAL;
/*
* if not available, emulate it
*/
if (rig->caps->set_channel == NULL) {
rig_save_channel(rig, &curr_chan);
#ifdef WANT_OLD_VFO_TO_BE_REMOVED
rig_mv_ctl(rig, RIG_VFO_CURR, RIG_MVOP_MEM_MODE);
#else
curr_vfo = rig->state.current_vfo;
rig_set_vfo(rig, RIG_VFO_MEM);
#endif
rig_get_mem(rig, RIG_VFO_CURR, &curr_chan_num);
rig_set_mem(rig, RIG_VFO_CURR, chan->channel_num);
rig_set_mem(rig, RIG_VFO_CURR, curr_chan_num);
rig_restore_channel(rig, chan);
#ifdef WANT_OLD_VFO_TO_BE_REMOVED
rig_mv_ctl(rig, RIG_VFO_CURR, RIG_MVOP_VFO_MODE);
#else
rig_set_vfo(rig, curr_vfo);
#endif
rig_restore_channel(rig, &curr_chan);
return RIG_OK;
}
return rig->caps->set_channel(rig, chan);
}
/**
* \brief get channel data
* \param rig The rig handle
* \param chan The location where to store the channel data
*
* Retrieves the data associated with the channel \a chan->channel_num.
* See #channel_t for more information.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_channel()
*/
int rig_get_channel(RIG *rig, channel_t *chan)
{
#if 0
channel_t curr_chan;
int curr_chan_num;
#endif
if (!rig || !rig->caps || !chan)
return -RIG_EINVAL;
/*
* if not available, emulate it
*/
if (rig->caps->get_channel == NULL) {
#if 0
rig_save_channel(rig, &curr_chan);
#endif
#ifdef WANT_OLD_VFO_TO_BE_REMOVED
rig_mv_ctl(rig, RIG_VFO_CURR, RIG_MVOP_MEM_MODE);
#else
rig_set_vfo(rig, RIG_VFO_MEM);
#endif
#if 0
rig_get_mem(rig, RIG_VFO_CURR, &curr_chan_num);
#endif
rig_set_mem(rig, RIG_VFO_CURR, chan->channel_num);
rig_save_channel(rig, chan);
#if 0
rig_set_mem(rig, RIG_VFO_CURR, curr_chan_num);
rig_restore_channel(rig, &curr_chan);
#endif
return RIG_OK;
}
return rig->caps->get_channel(rig, chan);
}
/**
* \brief find the freq_range of freq/mode
* \param range_list The range list to search from
* \param freq The frequency that will be part of this range
* \param mode The mode that will be part of this range
*
* Returns a pointer to the #freq_range_t including \a freq and \a mode.
* Works for rx and tx range list as well.
*
* \return the location of the #freq_range_t if found,
* otherwise NULL if not found or if \a range_list is invalid.
*
*/
const freq_range_t *
rig_get_range(const freq_range_t range_list[], freq_t freq, rmode_t mode)
{
int i;
for (i=0; i<FRQRANGESIZ; i++) {
if (range_list[i].start == 0 && range_list[i].end == 0) {
return NULL;
}
if (freq >= range_list[i].start && freq <= range_list[i].end &&
(range_list[i].modes & mode)) {
return &range_list[i];
}
}
return NULL;
}
/**
* \brief control the transceive mode
* \param rig The rig handle
* \param vfo The target VFO
* \param trn The transceive status to set to
*
* Enable/disable the transceive handling of a rig and kick off async mode.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_get_trn()
*/
int rig_set_trn(RIG *rig, vfo_t vfo, int trn)
{
const struct rig_caps *caps;
int status;
if (!rig || !rig->caps)
return -RIG_EINVAL;
caps = rig->caps;
if (rig->state.transceive == RIG_TRN_OFF)
return -RIG_ENAVAIL;
if (trn == RIG_TRN_RIG) {
if (rig->state.transceive) {
/*
* TODO: check error codes et al.
*/
status = add_trn_rig(rig);
if (caps->set_trn)
return caps->set_trn(rig, vfo, RIG_TRN_RIG);
else
return status;
} else {
return -RIG_ECONF;
}
} else {
status = remove_trn_rig(rig);
if (caps->set_trn)
return caps->set_trn(rig, vfo, RIG_TRN_OFF);
else
return status;
}
return RIG_OK;
}
/**
* \brief get the current transceive mode
* \param rig The rig handle
* \param vfo The target VFO
* \param trn The location where to store the current transceive mode
*
* Retrieves the current status of the transceive mode, i.e. if radio
* sends new status automatically when some changes happened on the radio.
*
* \return RIG_OK if the operation has been sucessful, otherwise
* a negative value if an error occured (in which case, cause is
* set appropriately).
*
* \sa rig_set_trn()
*/
int rig_get_trn(RIG *rig, vfo_t vfo, int *trn)
{
if (!rig || !rig->caps || !trn)
return -RIG_EINVAL;
if (rig->caps->get_trn == NULL)
return -RIG_ENAVAIL;
return rig->caps->get_trn(rig, vfo, trn);
}
/**
* \brief get general information from the radio
* \param rig The rig handle
*
* Retrieves some general information from the radio.
* This can include firmware revision, exact model name, or just nothing.
*
* \return a pointer to freshly allocated memory containing the ASCIIZ string
* if the operation has been sucessful, otherwise NULL if an error occured
* or get_info not part of capabilities.
*/
const char* rig_get_info(RIG *rig)
{
if (!rig || !rig->caps)
return NULL;
if (rig->caps->get_info == NULL)
return NULL;
return rig->caps->get_info(rig);
}
/**
* \brief basically convert setting_t expressed 2^n to n
* \param s The setting to convert to
*
* Converts a setting_t value expressed by 2^n to the value of n.
*
* \return the index such that 2^n is the setting, otherwise 0
* if the setting was not found.
*/
int rig_setting2idx(setting_t s)
{
int i;
for (i = 0; i<RIG_SETTING_MAX; i++)
if (s & rig_idx2setting(i))
return i;
return 0;
}