kopia lustrzana https://github.com/Hamlib/Hamlib
806 wiersze
20 KiB
C
806 wiersze
20 KiB
C
/*
|
|
* Hamlib Kenwood backend - Elecraft K2 description
|
|
* Copyright (c) 2002-2009 by Stephane Fillod
|
|
* Copyright (c) 2010 by Nate Bargmann, n0nb@arrl.net
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* See the file 'COPYING.LIB' in the main Hamlib distribution directory for
|
|
* the complete text of the GNU Lesser Public License version 2.1.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <hamlib/rig.h>
|
|
#include "kenwood.h"
|
|
#include "elecraft.h"
|
|
|
|
|
|
#define K2_MODES (RIG_MODE_CW|RIG_MODE_CWR|RIG_MODE_SSB|RIG_MODE_PKTLSB|RIG_MODE_PKTUSB)
|
|
|
|
#define K2_FUNC_ALL (RIG_FUNC_NB|RIG_FUNC_LOCK)
|
|
|
|
#define K2_LEVEL_ALL (RIG_LEVEL_ATT|RIG_LEVEL_PREAMP|RIG_LEVEL_AGC|RIG_LEVEL_SQL|\
|
|
RIG_LEVEL_STRENGTH|RIG_LEVEL_RFPOWER|RIG_LEVEL_KEYSPD)
|
|
|
|
#define K2_VFO (RIG_VFO_A|RIG_VFO_B)
|
|
#define K2_VFO_OP (RIG_OP_UP|RIG_OP_DOWN)
|
|
|
|
#define K2_ANTS (RIG_ANT_1|RIG_ANT_2)
|
|
|
|
static rmode_t k2_mode_table[KENWOOD_MODE_TABLE_MAX] =
|
|
{
|
|
[0] = RIG_MODE_NONE,
|
|
[1] = RIG_MODE_LSB,
|
|
[2] = RIG_MODE_USB,
|
|
[3] = RIG_MODE_CW,
|
|
[4] = RIG_MODE_NONE,
|
|
[5] = RIG_MODE_NONE,
|
|
[6] = RIG_MODE_PKTLSB, /* AFSK */
|
|
[7] = RIG_MODE_CWR,
|
|
[8] = RIG_MODE_NONE, /* TUNE mode */
|
|
[9] = RIG_MODE_PKTUSB /* AFSK */
|
|
};
|
|
|
|
/* kenwood_transaction() will add this to command strings
|
|
* sent to the rig and remove it from strings returned from
|
|
* the rig, so no need to append ';' manually to command strings.
|
|
*/
|
|
static struct kenwood_priv_caps k2_priv_caps =
|
|
{
|
|
.cmdtrm = EOM_KEN,
|
|
.mode_table = k2_mode_table,
|
|
};
|
|
|
|
|
|
/* K2 Filter list, four per mode */
|
|
struct k2_filt_s
|
|
{
|
|
shortfreq_t width; /* Filter width in Hz */
|
|
char fslot; /* Crystal filter slot number--1-4 */
|
|
char afslot; /* AF filter slot number--0-2 */
|
|
};
|
|
|
|
/* Number of filter slot arrays to allocate (TNX Diane, VA3DB) */
|
|
#define K2_FILT_NUM 4
|
|
|
|
/* K2 Filter List
|
|
*
|
|
* This struct will be populated as modes are queried or in response
|
|
* to a request to set a given mode. This way a cache can be maintained
|
|
* of the installed filters and an appropriate filter can be selected
|
|
* for a requested bandwidth. Each mode has up to four filter slots available.
|
|
*/
|
|
struct k2_filt_lst_s
|
|
{
|
|
struct k2_filt_s filt_list[K2_FILT_NUM];
|
|
};
|
|
|
|
struct k2_filt_lst_s k2_fwmd_ssb;
|
|
struct k2_filt_lst_s k2_fwmd_cw;
|
|
struct k2_filt_lst_s k2_fwmd_rtty;
|
|
|
|
/* K2 specific rig_caps API function declarations */
|
|
int k2_open(RIG *rig);
|
|
int k2_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width);
|
|
int k2_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width);
|
|
int k2_get_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t *val);
|
|
|
|
/* Private function declarations */
|
|
int k2_probe_mdfw(RIG *rig, struct kenwood_priv_data *priv);
|
|
int k2_mdfw_rest(RIG *rig, const char *mode, const char *fw);
|
|
int k2_pop_fw_lst(RIG *rig, const char *cmd);
|
|
|
|
|
|
/*
|
|
* KIO2 rig capabilities.
|
|
* This kit can recognize a large subset of TS-570 commands.
|
|
*
|
|
* Part of info comes from http://www.elecraft.com/K2_Manual_Download_Page.htm#K2
|
|
* look for KIO2 Programmer's Reference PDF
|
|
*/
|
|
const struct rig_caps k2_caps =
|
|
{
|
|
RIG_MODEL(RIG_MODEL_K2),
|
|
.model_name = "K2",
|
|
.mfg_name = "Elecraft",
|
|
.version = BACKEND_VER ".0",
|
|
.copyright = "LGPL",
|
|
.status = RIG_STATUS_STABLE,
|
|
.rig_type = RIG_TYPE_TRANSCEIVER,
|
|
.ptt_type = RIG_PTT_RIG,
|
|
.dcd_type = RIG_DCD_RIG,
|
|
.port_type = RIG_PORT_SERIAL,
|
|
.serial_rate_min = 4800,
|
|
.serial_rate_max = 4800,
|
|
.serial_data_bits = 8,
|
|
.serial_stop_bits = 2,
|
|
.serial_parity = RIG_PARITY_NONE,
|
|
.serial_handshake = RIG_HANDSHAKE_NONE,
|
|
.write_delay = 0, /* Timing between bytes */
|
|
.post_write_delay = 100, /* Timing between command strings */
|
|
// Note that 2000 timeout exceeds usleep but hl_usleep handles it
|
|
.timeout = 2000, /* FA and FB make take up to 500 ms on band change */
|
|
.retry = 10,
|
|
|
|
.has_get_func = K2_FUNC_ALL,
|
|
.has_set_func = K2_FUNC_ALL,
|
|
.has_get_level = K2_LEVEL_ALL,
|
|
.has_set_level = RIG_LEVEL_SET(K2_LEVEL_ALL),
|
|
.has_get_parm = RIG_PARM_NONE,
|
|
.has_set_parm = RIG_PARM_NONE, /* FIXME: parms */
|
|
.level_gran = {}, /* FIXME: granularity */
|
|
.parm_gran = {},
|
|
.extlevels = elecraft_ext_levels,
|
|
.extparms = kenwood_cfg_params,
|
|
.preamp = { 14, RIG_DBLST_END, },
|
|
.attenuator = { 10, RIG_DBLST_END, },
|
|
.max_rit = Hz(9990),
|
|
.max_xit = Hz(9990),
|
|
.max_ifshift = Hz(0),
|
|
.vfo_ops = K2_VFO_OP,
|
|
.targetable_vfo = RIG_TARGETABLE_FREQ,
|
|
.transceive = RIG_TRN_RIG,
|
|
.bank_qty = 0,
|
|
.chan_desc_sz = 0,
|
|
|
|
.chan_list = { RIG_CHAN_END },
|
|
|
|
.rx_range_list1 = {
|
|
{kHz(500), MHz(30), K2_MODES, -1, -1, K2_VFO, K2_ANTS},
|
|
RIG_FRNG_END,
|
|
}, /* rx range */
|
|
.tx_range_list1 = {
|
|
{kHz(1810), kHz(1850) - 1, K2_MODES, 10, W(15), K2_VFO, K2_ANTS}, /* 15W class */
|
|
{kHz(3500), kHz(3800) - 1, K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{MHz(7), kHz(7100), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{kHz(10100), kHz(10150), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{MHz(14), kHz(14350), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{kHz(18068), kHz(18168), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{MHz(21), kHz(21450), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{kHz(24890), kHz(24990), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{MHz(28), kHz(29700), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
RIG_FRNG_END,
|
|
}, /* tx range */
|
|
|
|
.rx_range_list2 = {
|
|
{kHz(500), MHz(30), K2_MODES, -1, -1, K2_VFO, K2_ANTS},
|
|
RIG_FRNG_END,
|
|
}, /* rx range */
|
|
.tx_range_list2 = {
|
|
{kHz(1800), MHz(2) - 1, K2_MODES, 10, W(15), K2_VFO, K2_ANTS}, /* 15W class */
|
|
{kHz(3500), MHz(4) - 1, K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{MHz(7), kHz(7300), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{kHz(10100), kHz(10150), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{MHz(14), kHz(14350), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{kHz(18068), kHz(18168), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{MHz(21), kHz(21450), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{kHz(24890), kHz(24990), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
{MHz(28), kHz(29700), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
|
|
RIG_FRNG_END,
|
|
}, /* tx range */
|
|
.tuning_steps = {
|
|
{K2_MODES, 10},
|
|
RIG_TS_END,
|
|
},
|
|
|
|
/* mode/filter list, remember: order matters! */
|
|
.filters = {
|
|
{RIG_MODE_SSB, kHz(2.5)},
|
|
{RIG_MODE_CW | RIG_MODE_CWR, Hz(500)},
|
|
{RIG_MODE_PKTLSB | RIG_MODE_PKTUSB, kHz(2.5)},
|
|
RIG_FLT_END,
|
|
},
|
|
.priv = (void *)& k2_priv_caps,
|
|
|
|
.rig_init = kenwood_init,
|
|
.rig_cleanup = kenwood_cleanup,
|
|
.rig_open = k2_open,
|
|
.rig_close = kenwood_close,
|
|
.set_freq = kenwood_set_freq,
|
|
.get_freq = kenwood_get_freq,
|
|
.set_mode = k2_set_mode,
|
|
.get_mode = k2_get_mode,
|
|
.set_vfo = kenwood_set_vfo,
|
|
.get_vfo = kenwood_get_vfo_if,
|
|
.set_split_vfo = kenwood_set_split_vfo,
|
|
.get_split_vfo = kenwood_get_split_vfo_if,
|
|
.set_rit = kenwood_set_rit,
|
|
.get_rit = kenwood_get_rit,
|
|
.set_xit = kenwood_set_xit,
|
|
.get_xit = kenwood_get_xit,
|
|
.get_ptt = kenwood_get_ptt,
|
|
.set_ptt = kenwood_set_ptt,
|
|
.get_dcd = kenwood_get_dcd,
|
|
.set_func = kenwood_set_func,
|
|
.get_func = kenwood_get_func,
|
|
.set_ext_parm = kenwood_set_ext_parm,
|
|
.get_ext_parm = kenwood_get_ext_parm,
|
|
.set_level = kenwood_set_level,
|
|
.get_level = kenwood_get_level,
|
|
.get_ext_level = k2_get_ext_level,
|
|
.vfo_op = kenwood_vfo_op,
|
|
.set_trn = kenwood_set_trn,
|
|
.get_powerstat = kenwood_get_powerstat,
|
|
.get_trn = kenwood_get_trn,
|
|
.set_ant = kenwood_set_ant,
|
|
.get_ant = kenwood_get_ant,
|
|
.send_morse = kenwood_send_morse,
|
|
.wait_morse = rig_wait_morse,
|
|
.hamlib_check_rig_caps = "HAMLIB_CHECK_RIG_CAPS"
|
|
};
|
|
|
|
|
|
/*
|
|
* K2 extension function definitions follow
|
|
*/
|
|
|
|
/* k2_open()
|
|
*
|
|
*/
|
|
int k2_open(RIG *rig)
|
|
{
|
|
int err;
|
|
struct kenwood_priv_data *priv = rig->state.priv;
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
|
|
|
err = elecraft_open(rig);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
err = k2_probe_mdfw(rig, priv);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
return RIG_OK;
|
|
}
|
|
|
|
|
|
/* k2_set_mode()
|
|
*
|
|
* Based on the passed in bandwidth, looks up the nearest bandwidth filter
|
|
* wider than the passed value and sets the radio accordingly.
|
|
*/
|
|
|
|
int k2_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
|
|
{
|
|
|
|
int err;
|
|
char f = '*';
|
|
struct k2_filt_lst_s *flt;
|
|
struct kenwood_priv_data *priv = rig->state.priv;
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
|
|
|
/* Select the filter array per mode. */
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
flt = &k2_fwmd_ssb;
|
|
break;
|
|
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
flt = &k2_fwmd_cw;
|
|
break;
|
|
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_PKTUSB:
|
|
if (priv->k2_md_rtty == 0)
|
|
{
|
|
return -RIG_EINVAL; /* RTTY module not installed */
|
|
}
|
|
else
|
|
{
|
|
flt = &k2_fwmd_rtty;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
return -RIG_EINVAL;
|
|
}
|
|
|
|
if (width != RIG_PASSBAND_NOCHANGE)
|
|
{
|
|
shortfreq_t freq = 0;
|
|
|
|
if (width < 0)
|
|
{
|
|
width = labs(width);
|
|
}
|
|
|
|
/* Step through the filter list looking for the best match
|
|
* for the passed in width. The choice is to select the filter
|
|
* that is wide enough for the width without being too narrow
|
|
* if possible.
|
|
*/
|
|
if (width == RIG_PASSBAND_NORMAL)
|
|
{
|
|
width = rig_passband_normal(rig, mode);
|
|
}
|
|
|
|
if ((width > flt->filt_list[0].width) || (width > flt->filt_list[1].width))
|
|
{
|
|
width = flt->filt_list[0].width;
|
|
f = '1';
|
|
}
|
|
else if ((flt->filt_list[1].width >= width)
|
|
&& (width > flt->filt_list[2].width))
|
|
{
|
|
width = flt->filt_list[1].width;
|
|
f = '2';
|
|
}
|
|
else if ((flt->filt_list[2].width >= width)
|
|
&& (width > flt->filt_list[3].width))
|
|
{
|
|
width = flt->filt_list[2].width;
|
|
f = '3';
|
|
}
|
|
else if ((flt->filt_list[3].width >= width) && (width >= freq))
|
|
{
|
|
width = flt->filt_list[3].width;
|
|
f = '4';
|
|
}
|
|
else
|
|
{
|
|
return -RIG_EINVAL;
|
|
}
|
|
}
|
|
|
|
/* kenwood_set_mode() ignores width value for K2/K3/TS-570 */
|
|
err = kenwood_set_mode(rig, vfo, mode, width);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
if (width != RIG_PASSBAND_NOCHANGE)
|
|
{
|
|
char fcmd[16];
|
|
|
|
err = kenwood_transaction(rig, "K22", NULL, 0);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
/* Construct the filter command and set the radio mode and width*/
|
|
SNPRINTF(fcmd, sizeof(fcmd), "FW0000%c", f);
|
|
|
|
/* Set the filter slot */
|
|
err = kenwood_transaction(rig, fcmd, NULL, 0);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
err = kenwood_transaction(rig, "K20", NULL, 0);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
}
|
|
|
|
return RIG_OK;
|
|
}
|
|
|
|
|
|
/* k2_get_mode()
|
|
*
|
|
* Uses the FW command in K22 mode to query the filter bandwidth reported
|
|
* by the radio and returns it to the caller.
|
|
*/
|
|
|
|
int k2_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
|
|
{
|
|
int err;
|
|
char buf[KENWOOD_MAX_BUF_LEN];
|
|
char tmp[16];
|
|
char *bufptr;
|
|
pbwidth_t temp_w;
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
|
|
|
if (!mode || !width)
|
|
{
|
|
return -RIG_EINVAL;
|
|
}
|
|
|
|
err = kenwood_get_mode(rig, vfo, mode, &temp_w);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
err = kenwood_transaction(rig, "K22", NULL, 0);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
err = kenwood_safe_transaction(rig, "FW", buf, KENWOOD_MAX_BUF_LEN, 8);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
err = kenwood_transaction(rig, "K20", NULL, 0);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
/* Convert received filter string value's first four digits to width */
|
|
bufptr = buf;
|
|
|
|
strncpy(tmp, bufptr + 2, 4);
|
|
tmp[4] = '\0';
|
|
*width = atoi(tmp);
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: Mode: %s, Width: %d\n", __func__,
|
|
rig_strrmode(*mode), (int)*width);
|
|
|
|
return RIG_OK;
|
|
}
|
|
|
|
|
|
/* TQ command is a quick transmit status query--K2/K3 only.
|
|
*
|
|
* token Defined in elecraft.h or this file
|
|
* val Type depends on token type from confparams structure:
|
|
* NUMERIC: val.f
|
|
* COMBO: val.i, starting from 0 Index to a string table.
|
|
* STRING: val.cs for set, val.s for get
|
|
* CHECKBUTTON: val.i 0/1
|
|
*/
|
|
int k2_get_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t *val)
|
|
{
|
|
char buf[KENWOOD_MAX_BUF_LEN];
|
|
int err;
|
|
const struct confparams *cfp;
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
|
|
|
if (!val)
|
|
{
|
|
return -RIG_EINVAL;
|
|
}
|
|
|
|
cfp = rig_ext_lookup_tok(rig, token);
|
|
|
|
switch (token)
|
|
{
|
|
case TOK_TX_STAT:
|
|
err = kenwood_safe_transaction(rig, "TQ", buf, KENWOOD_MAX_BUF_LEN, 3);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
if (cfp->type == RIG_CONF_CHECKBUTTON)
|
|
{
|
|
val->i = atoi(&buf[2]);
|
|
}
|
|
else
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: protocol error, invalid token type\n",
|
|
__func__);
|
|
return -RIG_EPROTO;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_WARN, "%s: Unsupported get_ext_level %s\n",
|
|
__func__, rig_strlevel(token));
|
|
return -RIG_EINVAL;
|
|
}
|
|
|
|
return RIG_OK;
|
|
}
|
|
|
|
|
|
/* K2 private helper functions follow */
|
|
|
|
/* Probes for mode and filter settings, based on information
|
|
* by Chris Bryant, G3WIE.
|
|
*/
|
|
int k2_probe_mdfw(RIG *rig, struct kenwood_priv_data *priv)
|
|
{
|
|
int err, i, c;
|
|
char buf[KENWOOD_MAX_BUF_LEN];
|
|
char mode[16];
|
|
char fw[16];
|
|
char cmd[16];
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
|
|
|
if (!priv)
|
|
{
|
|
return -RIG_EINVAL;
|
|
}
|
|
|
|
/* The K2 extension level has been stored by elecraft_open(). Now set rig
|
|
* to K22 for detailed query of mode and filter width values...
|
|
*/
|
|
err = kenwood_transaction(rig, "K22", NULL, 0);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
/* Check for mode and store it for later. */
|
|
err = kenwood_safe_transaction(rig, "MD", buf, KENWOOD_MAX_BUF_LEN, 3);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
strcpy(mode, buf);
|
|
|
|
/* Check for filter width and store it for later. */
|
|
err = kenwood_safe_transaction(rig, "FW", buf, KENWOOD_MAX_BUF_LEN, 8);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
strcpy(fw, buf);
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: Mode value: %s, Filter Width value: %s\n",
|
|
__func__, mode, fw);
|
|
|
|
/* Now begin the process of querying the available modes and filters. */
|
|
|
|
/* First try to put the K2 into RTTY mode and check if it's available. */
|
|
priv->k2_md_rtty = 0; /* Assume RTTY module not installed */
|
|
err = kenwood_transaction(rig, "MD6", NULL, 0);
|
|
|
|
if (err != RIG_OK && err != -RIG_ERJCTED)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
if (RIG_OK == err)
|
|
{
|
|
/* Read back mode and test to see if K2 reports RTTY. */
|
|
err = kenwood_safe_transaction(rig, "MD", buf, KENWOOD_MAX_BUF_LEN, 3);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
if (!strcmp("MD6", buf))
|
|
{
|
|
priv->k2_md_rtty = 1; /* set flag for RTTY mode enabled */
|
|
}
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: RTTY flag is: %d\n", __func__,
|
|
priv->k2_md_rtty);
|
|
|
|
i = (priv->k2_md_rtty == 1) ? 2 : 1;
|
|
|
|
/* Now loop through the modes checking for installed filters. */
|
|
for (c = 0; i > -1; i--, c++)
|
|
{
|
|
if (c == 0)
|
|
{
|
|
strcpy(cmd, "MD1"); /* SSB */
|
|
}
|
|
else if (c == 1)
|
|
{
|
|
strcpy(cmd, "MD3"); /* CW */
|
|
}
|
|
else if (c == 2)
|
|
{
|
|
strcpy(cmd, "MD6"); /* RTTY */
|
|
}
|
|
else /* Oops! */
|
|
{
|
|
err = k2_mdfw_rest(rig, mode, fw);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
return -RIG_EINVAL;
|
|
}
|
|
|
|
/* Now populate the Filter arrays */
|
|
err = k2_pop_fw_lst(rig, cmd);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
}
|
|
|
|
/* Restore mode, filter, extension level */
|
|
if (strlen(fw) == 8)
|
|
{
|
|
fw[7] = '\0'; /* Truncate AFSlot to set filter slot */
|
|
}
|
|
|
|
err = k2_mdfw_rest(rig, mode, fw);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
return RIG_OK;
|
|
}
|
|
|
|
|
|
/* Restore mode, filter, and ext_lvl to original values */
|
|
int k2_mdfw_rest(RIG *rig, const char *mode, const char *fw)
|
|
{
|
|
int err;
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
|
|
|
if (!mode || !fw)
|
|
{
|
|
return -RIG_EINVAL;
|
|
}
|
|
|
|
if (strlen(mode) != 3 || strlen(fw) != 7)
|
|
{
|
|
return -RIG_EINVAL;
|
|
}
|
|
|
|
err = kenwood_transaction(rig, mode, NULL, 0);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
err = kenwood_transaction(rig, fw, NULL, 0);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
err = kenwood_transaction(rig, "K20", NULL, 0);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
return RIG_OK;
|
|
}
|
|
|
|
|
|
/* Populate k2_filt_lst_s structure for each mode */
|
|
int k2_pop_fw_lst(RIG *rig, const char *cmd)
|
|
{
|
|
int err, f;
|
|
char fcmd[16];
|
|
char buf[KENWOOD_MAX_BUF_LEN];
|
|
char tmp[16];
|
|
struct k2_filt_lst_s *flt;
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
|
|
|
if (!cmd)
|
|
{
|
|
return -RIG_EINVAL;
|
|
}
|
|
|
|
/* Store filter data in the correct structure depending on mode */
|
|
if (strcmp(cmd, "MD1") == 0)
|
|
{
|
|
flt = &k2_fwmd_ssb;
|
|
}
|
|
else if (strcmp(cmd, "MD3") == 0)
|
|
{
|
|
flt = &k2_fwmd_cw;
|
|
}
|
|
else if (strcmp(cmd, "MD6") == 0)
|
|
{
|
|
flt = &k2_fwmd_rtty;
|
|
}
|
|
else
|
|
{
|
|
return -RIG_EINVAL;
|
|
}
|
|
|
|
/* Set the mode */
|
|
err = kenwood_transaction(rig, cmd, NULL, 0);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
for (f = 1; f < 5; f++)
|
|
{
|
|
char *bufptr = buf;
|
|
|
|
SNPRINTF(fcmd, sizeof(fcmd), "FW0000%d", f);
|
|
|
|
err = kenwood_transaction(rig, fcmd, NULL, 0);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
err = kenwood_safe_transaction(rig, "FW", buf, KENWOOD_MAX_BUF_LEN, 8);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
/* buf should contain a string "FWxxxxfa;" which corresponds to:
|
|
* xxxx = filter width in Hz
|
|
* f = crystal filter slot number--1-4
|
|
* a = audio filter slot number--0-2
|
|
*/
|
|
strncpy(tmp, bufptr + 2, 4);
|
|
tmp[4] = '\0';
|
|
flt->filt_list[f - 1].width = atoi(tmp);
|
|
|
|
strncpy(tmp, bufptr + 6, 1);
|
|
tmp[1] = '\0';
|
|
flt->filt_list[f - 1].fslot = atoi(tmp);
|
|
|
|
strncpy(tmp, bufptr + 7, 1);
|
|
tmp[1] = '\0';
|
|
flt->filt_list[f - 1].afslot = atoi(tmp);
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: Width: %04li, FSlot: %i, AFSlot %i\n",
|
|
__func__, flt->filt_list[f - 1].width, flt->filt_list[f - 1].fslot,
|
|
flt->filt_list[f - 1].afslot);
|
|
}
|
|
|
|
return RIG_OK;
|
|
}
|
|
|