Better set frequency semantics for the IC-910(h)

Allows for the optional 23cms module.

No longer tries to preserve the pre-amp/attn/bandwidth settings as the
does this (correctly) already.
Hamlib-3.1
Bill Somerville 2016-03-17 17:49:12 +00:00
rodzic 48102caeaa
commit 398bd3ccaa
2 zmienionych plików z 362 dodań i 302 usunięć

Wyświetl plik

@ -1,6 +1,6 @@
/*
* Hamlib CI-V backend - description of IC-910 (VHF/UHF All-Mode Tranceiver)
* Contributed by Francois Retief <fgretief@sun.ac.za>
* Hamlib CI-V backend - description of IC-910 (VHF/UHF All-Mode
* Tranceiver) Contributed by Francois Retief <fgretief@sun.ac.za>
* Copyright (c) 2000-2010 by Stephane Fillod
*
*
@ -41,24 +41,24 @@
#ifdef HAVE_WEIRD_IC910_MODES
static int ic910_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
{
/* FIX: The IC-910 has "Set FM" = 4, which is RTTY in for other radios */
if (mode == RIG_MODE_FM) {
mode = RIG_MODE_RTTY;
}
/* FIX: The IC-910 has "Set FM" = 4, which is RTTY in for other radios */
if (mode == RIG_MODE_FM) {
mode = RIG_MODE_RTTY;
}
return icom_set_mode(rig, vfo, mode, width);
return icom_set_mode(rig, vfo, mode, width);
}
static int ic910_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
{
/* FIX: The IC-910 has "Set FM" = 4, which is RTTY in for other radios */
int retval = icom_get_mode(rig, vfo, mode, width);
/* FIX: The IC-910 has "Set FM" = 4, which is RTTY in for other radios */
int retval = icom_get_mode(rig, vfo, mode, width);
if (*mode == RIG_MODE_RTTY) {
*mode = RIG_MODE_FM;
}
if (*mode == RIG_MODE_RTTY) {
*mode = RIG_MODE_FM;
}
return retval;
return retval;
}
#endif /* HAVE_WEIRD_IC910_MODES */
@ -69,126 +69,149 @@ static int ic910_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
static int compareFrequencies(RIG *rig, freq_t freq1, freq_t freq2)
{
int freq1band = 0, freq2band = 0;
freq_range_t noband = RIG_FRNG_END;
int freq1band = 0, freq2band = 0;
freq_range_t noband = RIG_FRNG_END;
while (rig->caps->rx_range_list1[freq1band].start != noband.start) {
if (freq1 >= rig->caps->rx_range_list1[freq1band].start &&
freq1 <= rig->caps->rx_range_list1[freq1band].end)
break;
while (rig->caps->rx_range_list1[freq1band].start != noband.start) {
if (freq1 >= rig->caps->rx_range_list1[freq1band].start &&
freq1 <= rig->caps->rx_range_list1[freq1band].end)
break;
++freq1band;
//fprintf(stderr, "%i\n", freq1band);
}
++freq1band;
//fprintf(stderr, "%i\n", freq1band);
}
while (rig->caps->rx_range_list1[freq2band].start != noband.start) {
if (freq2 >= rig->caps->rx_range_list1[freq2band].start &&
freq2 <= rig->caps->rx_range_list1[freq2band].end)
break;
while (rig->caps->rx_range_list1[freq2band].start != noband.start) {
if (freq2 >= rig->caps->rx_range_list1[freq2band].start &&
freq2 <= rig->caps->rx_range_list1[freq2band].end)
break;
++freq2band;
}
++freq2band;
}
if (freq2band == freq1band) return 1;
else return 0;
}
/* swaps main and sub band - but preserves PREAMP, MODE
* they are also exchanged, but we do not want that
*/
static int icom_swap_bands(RIG *rig)
{
/* TODO: actually use retval! */
int retval = 0;
rmode_t mmode, smode; /* used to store the mode */
pbwidth_t mwidth, swidth; /* used to store the width */
value_t mpreamp, spreamp; /* used to store preamp */
value_t matt, satt; /* used to store attenuation */
/* main band get values */
icom_set_vfo(rig, RIG_VFO_MAIN);
/* get the mode, width, preamp */
icom_get_mode(rig, RIG_VFO_CURR, &mmode, &mwidth);
icom_get_level(rig, RIG_VFO_CURR, RIG_LEVEL_PREAMP, &mpreamp);
icom_get_level(rig, RIG_VFO_CURR, RIG_LEVEL_ATT, &matt);
/* sub band get values */
icom_set_vfo(rig, RIG_VFO_SUB);
/* get the mode, width, preamp, att */
icom_get_mode(rig, RIG_VFO_CURR, &smode, &swidth);
icom_get_level(rig, RIG_VFO_CURR, RIG_LEVEL_PREAMP, &spreamp);
icom_get_level(rig, RIG_VFO_CURR, RIG_LEVEL_ATT, &satt);
/* now, we can exchange the bands */
icom_vfo_op(rig, RIG_VFO_CURR, RIG_OP_XCHG);
/* restore the sub vales NOTE: sub band is still active */
/* set the mode, width, preamp */
icom_set_mode(rig, RIG_VFO_CURR, smode, swidth);
icom_set_level(rig, RIG_VFO_CURR, RIG_LEVEL_PREAMP, spreamp);
icom_set_level(rig, RIG_VFO_CURR, RIG_LEVEL_ATT, satt);
/* restore main band values */
icom_set_vfo(rig, RIG_VFO_MAIN);
/* set the mode, width, preamp */
icom_set_mode(rig, RIG_VFO_CURR, mmode, mwidth);
icom_set_level(rig, RIG_VFO_CURR, RIG_LEVEL_PREAMP, mpreamp);
icom_set_level(rig, RIG_VFO_CURR, RIG_LEVEL_ATT, matt);
return retval;
if (freq2band == freq1band) return 1;
else return 0;
}
static int ic910_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
{
int retval;
freq_t otherfreq;
freq_t oldfreq;
int retval;
freq_t otherfreq;
freq_t origfreq;
retval = icom_get_freq(rig, vfo, &oldfreq);
if (retval != RIG_OK) return retval;
if (!compareFrequencies(rig, freq, oldfreq)) {
/* we are on the wrong band */
if (vfo == RIG_VFO_CURR) {
/* try to detect active subband */
icom_set_vfo(rig, RIG_VFO_SUB);
retval = icom_get_freq(rig, RIG_VFO_CURR, &otherfreq);
if (retval != RIG_OK) return retval;
if (otherfreq == oldfreq) {
/* were already in subband */
vfo = RIG_VFO_SUB;
icom_set_vfo(rig, RIG_VFO_MAIN);
retval = icom_get_freq(rig, RIG_VFO_CURR, &otherfreq);
if (retval != RIG_OK) return retval;
} else {
/* we were in mainband */
vfo = RIG_VFO_MAIN;
}
} else {
/* get the freq of the other band */
if (vfo == RIG_VFO_MAIN)
icom_set_vfo(rig, RIG_VFO_SUB);
else
icom_set_vfo(rig, RIG_VFO_MAIN);
retval = icom_get_freq(rig, RIG_VFO_CURR, &otherfreq);
if (retval != RIG_OK) return retval;
}
if (compareFrequencies(rig, freq, otherfreq))
icom_swap_bands(rig);
icom_set_vfo(rig, vfo);
}
return icom_set_freq(rig, RIG_VFO_CURR, freq);
if ((retval = icom_get_freq(rig, RIG_VFO_CURR, &origfreq)) != RIG_OK) return retval;
if (compareFrequencies (rig, freq, origfreq))
{
/* correct band already */
if (RIG_VFO_A == vfo || RIG_VFO_B == vfo)
{
/* switch to desired VFO and read its frequency */
if ((retval = icom_set_vfo (rig, vfo)) != RIG_OK) return retval;
if ((retval = icom_get_freq(rig, vfo, &otherfreq)) != RIG_OK) return retval;
retval = icom_set_freq (rig, RIG_VFO_CURR, freq);
if (otherfreq != origfreq)
{
/* swap VFOs back as original was the other one */
icom_set_vfo (rig, RIG_VFO_A == vfo ? RIG_VFO_B : RIG_VFO_A);
}
}
else if (RIG_VFO_MAIN == vfo || RIG_VFO_SUB == vfo)
{
/* switch to the desired of MAIN and SUB and read its frequency */
if ((retval = icom_set_vfo (rig, vfo)) != RIG_OK) return retval;
if ((retval = icom_get_freq(rig, vfo, &otherfreq)) != RIG_OK) return retval;
if (otherfreq != origfreq)
{
/* started on a different so band exchange MAIN and SUB */
if ((retval = icom_vfo_op(rig, RIG_VFO_CURR, RIG_OP_XCHG)) != RIG_OK) return retval;
retval = icom_set_freq (rig, RIG_VFO_CURR, freq);
/* swap MAIN/SUB back as original was the other one */
icom_set_vfo (rig, RIG_VFO_MAIN == vfo ? RIG_VFO_SUB : RIG_VFO_MAIN);
}
else
{
/* already correct one of MAIN and SUB */
retval = icom_set_freq (rig, RIG_VFO_CURR, freq);
}
}
else if (RIG_VFO_CURR == vfo)
{
retval = icom_set_freq (rig, RIG_VFO_CURR, freq);
}
else retval = -RIG_EVFO;
}
else
{
/* wrong band */
if (RIG_VFO_A == vfo || RIG_VFO_B == vfo)
{
/* try and set frequency, may fail if band is already on other of MAIN/SUB */
retval = icom_set_freq (rig, RIG_VFO_CURR, freq);
if (-RIG_ERJCTED == retval)
{
/* exchange MAIN & SUB */
if ((retval = icom_vfo_op(rig, RIG_VFO_CURR, RIG_OP_XCHG)) != RIG_OK) return retval;
if ((retval = icom_get_freq(rig, vfo, &origfreq)) != RIG_OK) return retval;
if ((retval = icom_set_vfo (rig, vfo)) != RIG_OK) return retval;
if ((retval = icom_get_freq(rig, vfo, &otherfreq)) != RIG_OK) return retval;
retval = icom_set_freq (rig, RIG_VFO_CURR, freq);
if (-RIG_ERJCTED == retval)
{
/* band not fitted so swap MAIN & SUB back and give up */
icom_vfo_op(rig, RIG_VFO_CURR, RIG_OP_XCHG);
return retval;
}
else if (retval != RIG_OK) return retval;
if (otherfreq != origfreq)
{
/* swap VFOs back as original was the other one */
icom_set_vfo (rig, RIG_VFO_A == vfo ? RIG_VFO_B : RIG_VFO_A);
}
/* we do not exchange bands back as this is taken to
mean set VFOA/B on MAIN to the specified frequency
as Hamlib does not recognize A on MAIN or B on SUB
etc. This is probably reasonable since we cannot Tx
on SUB */
return retval;
}
/* we changed band to the "third band" which always makes
VFO A current so just make the requested one the
specified frequency as well if it is VFO B. There is no
way of going to the "third band" without changing VFO
A */
if (RIG_VFO_B == vfo) {
if ((retval = icom_set_vfo (rig, vfo)) != RIG_OK) return retval;
retval = icom_set_freq (rig, RIG_VFO_CURR, freq);
icom_set_vfo (rig, RIG_VFO_A);
}
}
else if (RIG_VFO_MAIN == vfo || RIG_VFO_SUB == vfo)
{
if ((retval = icom_set_vfo (rig, vfo)) != RIG_OK) return retval;
if ((retval = icom_get_freq(rig, vfo, &otherfreq)) != RIG_OK) return retval;
retval = icom_set_freq (rig, RIG_VFO_CURR, freq);
if (-RIG_ERJCTED == retval)
{
/* required band is on other of MAIN or SUB */
if ((retval = icom_vfo_op(rig, RIG_VFO_CURR, RIG_OP_XCHG)) != RIG_OK) return retval;
retval = icom_set_freq (rig, RIG_VFO_CURR, freq);
}
else if (retval != RIG_OK) return retval;
if (otherfreq != origfreq)
{
/* started on other of MAIN & SUB so switch back */
icom_set_vfo (rig,
RIG_VFO_MAIN == vfo ?
RIG_VFO_SUB : RIG_VFO_MAIN);
}
}
else if (RIG_VFO_CURR == vfo)
{
retval = icom_set_freq (rig, RIG_VFO_CURR, freq);
}
else retval = -RIG_EVFO;
}
return retval;
}
/*
@ -196,16 +219,16 @@ static int ic910_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
* (1 - normal, 2 - narrow)
*/
static int ic910_r2i_mode(RIG *rig, rmode_t mode, pbwidth_t width,
unsigned char *md, signed char *pd)
unsigned char *md, signed char *pd)
{
int err;
int err;
err = rig2icom_mode(rig, mode, width, md, pd);
err = rig2icom_mode(rig, mode, width, md, pd);
if (*pd == PD_NARROW_3)
*pd = PD_NARROW_2;
if (*pd == PD_NARROW_3)
*pd = PD_NARROW_2;
return err;
return err;
}
@ -252,141 +275,141 @@ static int ic910_r2i_mode(RIG *rig, rmode_t mode, pbwidth_t width,
RIG_LEVEL_ATT| \
RIG_LEVEL_PREAMP)
#define IC910_STR_CAL UNKNOWN_IC_STR_CAL /* FIXME */
#define IC910_STR_CAL UNKNOWN_IC_STR_CAL /* FIXME */
/*
*/
static const struct icom_priv_caps ic910_priv_caps = {
0x60, /* default address */
0, /* 731 mode */
0, /* no XCHG */
ic910_ts_sc_list,
.r2i_mode = ic910_r2i_mode
0x60, /* default address */
0, /* 731 mode */
0, /* no XCHG */
ic910_ts_sc_list,
.r2i_mode = ic910_r2i_mode
};
const struct rig_caps ic910_caps = {
.rig_model = RIG_MODEL_IC910,
.model_name = "IC-910",
.mfg_name = "Icom",
.version = BACKEND_VER ".1",
.copyright = "LGPL",
.status = RIG_STATUS_BETA,
.rig_type = RIG_TYPE_TRANSCEIVER,
.ptt_type = RIG_PTT_NONE,
.dcd_type = RIG_DCD_RIG,
.port_type = RIG_PORT_SERIAL,
.serial_rate_min = 300,
.serial_rate_max = 19200,
.serial_data_bits = 8,
.serial_stop_bits = 1,
.serial_parity = RIG_PARITY_NONE,
.serial_handshake = RIG_HANDSHAKE_NONE,
.write_delay = 0,
.post_write_delay = 0,
.timeout = 1000,
.retry = 3,
.has_get_func = IC910_FUNC_ALL,
.has_set_func = IC910_FUNC_ALL | RIG_FUNC_RESUME,
.has_get_level = IC910_LEVEL_ALL | (RIG_LEVEL_RAWSTR),
.has_set_level = IC910_LEVEL_ALL,
.has_get_parm = RIG_PARM_NONE,
.has_set_parm = RIG_PARM_NONE,
.level_gran = {
[LVL_RAWSTR] = { .min = { .i = 0 }, .max = { .i = 255 } },
},
.parm_gran = {},
.ctcss_list = NULL,
.dcs_list = NULL,
.preamp = { 20, RIG_DBLST_END, },
.attenuator = { 20, RIG_DBLST_END, },
.max_rit = Hz(0), /* SSB,CW: +-1.0kHz FM: +-5.0kHz */
.max_xit = Hz(0),
.max_ifshift = Hz(0), /* 1.2kHz manual knob */
.targetable_vfo = 0,
.vfo_ops = IC910_VFO_OPS,
.scan_ops = IC910_SCAN_OPS,
.transceive = RIG_TRN_RIG,
.bank_qty = 0,
.chan_desc_sz = 0,
.rig_model = RIG_MODEL_IC910,
.model_name = "IC-910",
.mfg_name = "Icom",
.version = BACKEND_VER ".1",
.copyright = "LGPL",
.status = RIG_STATUS_BETA,
.rig_type = RIG_TYPE_TRANSCEIVER,
.ptt_type = RIG_PTT_NONE,
.dcd_type = RIG_DCD_RIG,
.port_type = RIG_PORT_SERIAL,
.serial_rate_min = 300,
.serial_rate_max = 19200,
.serial_data_bits = 8,
.serial_stop_bits = 1,
.serial_parity = RIG_PARITY_NONE,
.serial_handshake = RIG_HANDSHAKE_NONE,
.write_delay = 0,
.post_write_delay = 0,
.timeout = 1000,
.retry = 3,
.has_get_func = IC910_FUNC_ALL,
.has_set_func = IC910_FUNC_ALL | RIG_FUNC_RESUME,
.has_get_level = IC910_LEVEL_ALL | (RIG_LEVEL_RAWSTR),
.has_set_level = IC910_LEVEL_ALL,
.has_get_parm = RIG_PARM_NONE,
.has_set_parm = RIG_PARM_NONE,
.level_gran = {
[LVL_RAWSTR] = { .min = { .i = 0 }, .max = { .i = 255 } },
},
.parm_gran = {},
.ctcss_list = NULL,
.dcs_list = NULL,
.preamp = { 20, RIG_DBLST_END, },
.attenuator = { 20, RIG_DBLST_END, },
.max_rit = Hz(0), /* SSB,CW: +-1.0kHz FM: +-5.0kHz */
.max_xit = Hz(0),
.max_ifshift = Hz(0), /* 1.2kHz manual knob */
.targetable_vfo = RIG_TARGETABLE_FREQ,
.vfo_ops = IC910_VFO_OPS,
.scan_ops = IC910_SCAN_OPS,
.transceive = RIG_TRN_RIG,
.bank_qty = 0,
.chan_desc_sz = 0,
.chan_list = {
{ 1, 99, RIG_MTYPE_MEM },
{ 100, 105, RIG_MTYPE_EDGE },
{ 106, 106, RIG_MTYPE_CALL },
RIG_CHAN_END,
},
.chan_list = {
{ 1, 99, RIG_MTYPE_MEM },
{ 100, 105, RIG_MTYPE_EDGE },
{ 106, 106, RIG_MTYPE_CALL },
RIG_CHAN_END,
},
.rx_range_list1 = { /* USA */
{MHz(144), MHz(148), IC910_MODES, -1, -1, IC910_VFO_ALL},
{MHz(430), MHz(450), IC910_MODES, -1, -1, IC910_VFO_ALL},
{MHz(1240), MHz(1300), IC910_MODES, -1, -1, IC910_VFO_ALL},
RIG_FRNG_END,
},
.tx_range_list1 = {
{MHz(144), MHz(148), IC910_MODES, W(5), W(100), IC910_VFO_ALL},
{MHz(430), MHz(450), IC910_MODES, W(5), W(75), IC910_VFO_ALL},
{MHz(1240), MHz(1300), IC910_MODES, -1, -1, IC910_VFO_ALL},
RIG_FRNG_END,
},
.rx_range_list1 = { /* USA */
{MHz(144), MHz(148), IC910_MODES, -1, -1, IC910_VFO_ALL},
{MHz(430), MHz(450), IC910_MODES, -1, -1, IC910_VFO_ALL},
{MHz(1240), MHz(1300), IC910_MODES, -1, -1, IC910_VFO_ALL},
RIG_FRNG_END,
},
.tx_range_list1 = {
{MHz(144), MHz(148), IC910_MODES, W(5), W(100), IC910_VFO_ALL},
{MHz(430), MHz(450), IC910_MODES, W(5), W(75), IC910_VFO_ALL},
{MHz(1240), MHz(1300), IC910_MODES, -1, -1, IC910_VFO_ALL},
RIG_FRNG_END,
},
.rx_range_list2 = { /* Europe */
{MHz(144), MHz(146), IC910_MODES, -1, -1, IC910_VFO_ALL},
{MHz(430), MHz(440), IC910_MODES, -1, -1, IC910_VFO_ALL},
{MHz(1240), MHz(1300), IC910_MODES, -1, -1, IC910_VFO_ALL},
RIG_FRNG_END,
},
.tx_range_list2 = {
{MHz(144), MHz(146), IC910_MODES, W(5), W(100), IC910_VFO_ALL},
{MHz(430), MHz(440), IC910_MODES, W(5), W(75), IC910_VFO_ALL},
{MHz(1240), MHz(1300), IC910_MODES, -1, -1, IC910_VFO_ALL},
RIG_FRNG_END,
},
.rx_range_list2 = { /* Europe */
{MHz(144), MHz(146), IC910_MODES, -1, -1, IC910_VFO_ALL},
{MHz(430), MHz(440), IC910_MODES, -1, -1, IC910_VFO_ALL},
{MHz(1240), MHz(1300), IC910_MODES, -1, -1, IC910_VFO_ALL},
RIG_FRNG_END,
},
.tx_range_list2 = {
{MHz(144), MHz(146), IC910_MODES, W(5), W(100), IC910_VFO_ALL},
{MHz(430), MHz(440), IC910_MODES, W(5), W(75), IC910_VFO_ALL},
{MHz(1240), MHz(1300), IC910_MODES, -1, -1, IC910_VFO_ALL},
RIG_FRNG_END,
},
.tuning_steps = {
{RIG_MODE_SSB | RIG_MODE_CW, 1},
{RIG_MODE_SSB | RIG_MODE_CW, 10},
{RIG_MODE_SSB | RIG_MODE_CW, 50},
{RIG_MODE_SSB | RIG_MODE_CW, 100},
{RIG_MODE_FM, kHz(0.1)},
{RIG_MODE_FM, kHz(5)},
{RIG_MODE_FM, kHz(6.25)},
{RIG_MODE_FM, kHz(10)},
{RIG_MODE_FM, kHz(12.5)},
{RIG_MODE_FM, kHz(20)},
{RIG_MODE_FM, kHz(25)},
{RIG_MODE_FM, kHz(100)},
RIG_TS_END,
},
/* mode/filter list, remember: order matters! */
.filters = {
{RIG_MODE_CW | RIG_MODE_SSB, kHz(2.3)}, /* builtin */
{RIG_MODE_CW, Hz(600)}, /* with optional FL-132/Fl133 CW filters */
{RIG_MODE_FM, kHz(15)}, /* builtin */
{RIG_MODE_FM, kHz(6)}, /* builtin */
RIG_FLT_END,
},
.str_cal = IC910_STR_CAL,
.tuning_steps = {
{RIG_MODE_SSB | RIG_MODE_CW, 1},
{RIG_MODE_SSB | RIG_MODE_CW, 10},
{RIG_MODE_SSB | RIG_MODE_CW, 50},
{RIG_MODE_SSB | RIG_MODE_CW, 100},
{RIG_MODE_FM, kHz(0.1)},
{RIG_MODE_FM, kHz(5)},
{RIG_MODE_FM, kHz(6.25)},
{RIG_MODE_FM, kHz(10)},
{RIG_MODE_FM, kHz(12.5)},
{RIG_MODE_FM, kHz(20)},
{RIG_MODE_FM, kHz(25)},
{RIG_MODE_FM, kHz(100)},
RIG_TS_END,
},
/* mode/filter list, remember: order matters! */
.filters = {
{RIG_MODE_CW | RIG_MODE_SSB, kHz(2.3)}, /* builtin */
{RIG_MODE_CW, Hz(600)}, /* with optional FL-132/Fl133 CW filters */
{RIG_MODE_FM, kHz(15)}, /* builtin */
{RIG_MODE_FM, kHz(6)}, /* builtin */
RIG_FLT_END,
},
.str_cal = IC910_STR_CAL,
.priv = (void *)& ic910_priv_caps,
.rig_init = icom_init,
.rig_cleanup = icom_cleanup,
.rig_open = NULL,
.rig_close = NULL,
.priv = (void *)& ic910_priv_caps,
.rig_init = icom_init,
.rig_cleanup = icom_cleanup,
.rig_open = NULL,
.rig_close = NULL,
.cfgparams = icom_cfg_params,
.set_conf = icom_set_conf,
.get_conf = icom_get_conf,
.cfgparams = icom_cfg_params,
.set_conf = icom_set_conf,
.get_conf = icom_get_conf,
.get_freq = icom_get_freq,
.set_freq = ic910_set_freq,
.get_freq = icom_get_freq,
.set_freq = ic910_set_freq,
#ifdef HAVE_WEIRD_IC910_MODES
.get_mode = ic910_get_mode,
.set_mode = ic910_set_mode,
.get_mode = ic910_get_mode,
.set_mode = ic910_set_mode,
#else
.get_mode = icom_get_mode,
.set_mode = icom_set_mode,
.get_mode = icom_get_mode,
.set_mode = icom_set_mode,
#endif
.get_vfo = NULL,

Wyświetl plik

@ -1655,7 +1655,8 @@ static int get_split_vfos(const RIG *rig, vfo_t *rx_vfo, vfo_t *tx_vfo)
{
if ((rig->state.vfo_list & (RIG_VFO_A|RIG_VFO_B)) == (RIG_VFO_A|RIG_VFO_B)) {
*rx_vfo = RIG_VFO_A;
*tx_vfo = RIG_VFO_B;
*tx_vfo = RIG_VFO_B; /* rig doesn't enforce this but
convention is needed here */
} else if ((rig->state.vfo_list & (RIG_VFO_MAIN|RIG_VFO_SUB)) == (RIG_VFO_MAIN|RIG_VFO_SUB)) {
*rx_vfo = RIG_VFO_MAIN;
*tx_vfo = RIG_VFO_SUB;
@ -1989,55 +1990,48 @@ int icom_get_split_mode(RIG *rig, vfo_t vfo, rmode_t *tx_mode, pbwidth_t *tx_wid
return status;
}
/*
* icom_set_split_freq_mode
* Assumes rig!=NULL, rig->state.priv!=NULL,
* icom_set_vfo,icom_set_mode works for this rig
* FIXME: status
*/
int icom_set_split_freq_mode(RIG *rig, vfo_t vfo, freq_t tx_freq, rmode_t tx_mode, pbwidth_t tx_width)
/* find out what the split VFO, Freq, Mode and Width are.
Leaves the split VFO as current and returns a current VFO to switch
back to. The current VFO may be NONE in which case no switch back is
required */
static int get_split_status (RIG * rig, vfo_t * curr_vfo,
freq_t * split_freq,
rmode_t * split_mode,
pbwidth_t * split_width)
{
struct icom_priv_data * priv = (struct icom_priv_data *)rig->state.priv;
int status;
vfo_t rx_vfo, tx_vfo;
/* This method works also in memory mode(RIG_VFO_MEM) */
if (!priv->no_xchg && rig_has_vfo_op(rig, RIG_OP_XCHG)) {
status = icom_vfo_op(rig, vfo, RIG_OP_XCHG);
if (status != RIG_OK)
return status;
status = rig_set_freq(rig, RIG_VFO_CURR, tx_freq);
if (status != RIG_OK)
return status;
status = rig->caps->set_mode(rig, RIG_VFO_CURR, tx_mode, tx_width);
if (status != RIG_OK)
return status;
status = icom_vfo_op(rig, vfo, RIG_OP_XCHG);
if (status != RIG_OK)
return status;
return 0;
}
/* strategy here is to attempt to leave the original VFO selected
/* Strategy here is to attempt to leave the original VFO selected
even though Icom provides no way to tell what the current VFO is. So
we read current frequency and mode and compare with SUB/B, this
gives up a clue so long as both VFOs are not the same frequency and
mode (and we don't really care if they are, the price for not using
VFO_XCHG, which will glitch the RX and TX and, possibly clatter the
rig relays). */
rig relays).
freq_t orig_freq, second_freq;
rmode_t orig_mode, second_mode;
pbwidth_t orig_width, second_width;
There is a further complication in that A/B VFO style Icoms swap
VFOs during split Tx but there is no guaranteed way of querying Tx
status. In this case we must briefly turn off split to read the Rx
VFO details. Even more complex if the VFOs are set the same then
only by adjusting one before disabling split can we be sure that we
have identified which is which.
This all relies on some assumptions:- the rig can only be set or
reset to and from split mode via this library, when split the Tx
status must remain constant through this sequence. */
int status;
struct icom_priv_data * priv = (struct icom_priv_data *)rig->state.priv;
vfo_t rx_vfo, tx_vfo;
freq_t orig_freq;
rmode_t orig_mode;
pbwidth_t orig_width;
unsigned char ackbuf[MAXFRAMELEN];
int ack_len = sizeof(ackbuf);
int tx_split = 0;
freq_t offset = 0;
*curr_vfo = RIG_VFO_NONE;
status = get_split_vfos(rig, &rx_vfo, &tx_vfo);
if (status != RIG_OK) return status;
@ -2049,7 +2043,7 @@ int icom_set_split_freq_mode(RIG *rig, vfo_t vfo, freq_t tx_freq, rmode_t tx_mod
if ((rig->state.vfo_list & (RIG_VFO_A | RIG_VFO_B)) == (RIG_VFO_A | RIG_VFO_B)) {
/* A/B VFO rigs swap VFO on split Tx so we need to find out if we are in Tx */
if (priv->split_on) {
if (priv->split_on) { /* broken if user changes split on rig :( */
status = icom_transaction (rig, C_CTL_SPLT, S_SPLT_OFF, NULL, 0, ackbuf, &ack_len);
if (status != RIG_OK) return status;
if (ack_len != 1 || ackbuf[0] != ACK) {
@ -2057,13 +2051,13 @@ int icom_set_split_freq_mode(RIG *rig, vfo_t vfo, freq_t tx_freq, rmode_t tx_mod
"len=%d\n", ackbuf[0],ack_len);
return -RIG_ERJCTED;
}
status = icom_get_freq(rig, RIG_VFO_CURR, &second_freq);
status = icom_get_freq(rig, RIG_VFO_CURR, split_freq);
if (status != RIG_OK) return status;
if (second_freq == orig_freq) {
status = rig->caps->get_mode (rig, RIG_VFO_CURR, &second_mode, &second_width);
if (*split_freq == orig_freq) {
status = rig->caps->get_mode (rig, RIG_VFO_CURR, split_mode, split_width);
if (status != RIG_OK) return status;
}
if (second_freq != orig_freq || second_mode != orig_mode || second_width != orig_width) {
if (*split_freq != orig_freq || *split_mode != orig_mode || *split_width != orig_width) {
/* definitely split tx as turning off split changed VFO */
tx_split = -1;
/* restore split state */
@ -2080,7 +2074,7 @@ int icom_set_split_freq_mode(RIG *rig, vfo_t vfo, freq_t tx_freq, rmode_t tx_mod
status = icom_set_vfo(rig, tx_vfo);
if (status != RIG_OK) return status;
offset = Hz(10);
status = icom_set_freq(rig, RIG_VFO_CURR, second_freq + offset);
status = icom_set_freq(rig, RIG_VFO_CURR, *split_freq + offset);
if (status != RIG_OK) return status;
/* restore split state */
status = icom_transaction (rig, C_CTL_SPLT, S_SPLT_ON, NULL, 0, ackbuf, &ack_len);
@ -2093,7 +2087,7 @@ int icom_set_split_freq_mode(RIG *rig, vfo_t vfo, freq_t tx_freq, rmode_t tx_mod
freq_t temp_freq;
status = icom_get_freq(rig, RIG_VFO_CURR, &temp_freq);
if (status != RIG_OK) return status;
if (temp_freq != second_freq + offset) {
if (temp_freq != *split_freq + offset) {
/* frequency changed so we must be in Tx */
tx_split = -1;
/* VFO B current since split Tx */
@ -2108,26 +2102,69 @@ int icom_set_split_freq_mode(RIG *rig, vfo_t vfo, freq_t tx_freq, rmode_t tx_mod
if (0 == offset) {
status = icom_set_vfo(rig, tx_vfo);
if (status != RIG_OK) return status;
status = icom_get_freq(rig, RIG_VFO_CURR, &second_freq);
status = icom_get_freq(rig, RIG_VFO_CURR, split_freq);
if (status != RIG_OK) return status;
status = rig->caps->get_mode (rig, RIG_VFO_CURR, &second_mode, &second_width);
status = rig->caps->get_mode (rig, RIG_VFO_CURR, split_mode, split_width);
if (status != RIG_OK) return status;
}
}
if (!tx_split && (*split_freq != orig_freq
|| *split_mode != orig_mode
|| *split_width != orig_width
|| priv->split_on)) {
/* Rx VFO must have been selected when we started so switch back
to it. We may be wrong but in that case A & B are the same so
it doesn't matter so long as in split Tx is always VFO B */
*curr_vfo = rx_vfo;
}
return RIG_OK;
}
/*
* icom_set_split_freq_mode
* Assumes rig!=NULL, rig->state.priv!=NULL,
* icom_set_vfo,icom_set_mode works for this rig
* FIXME: status
*/
int icom_set_split_freq_mode(RIG *rig, vfo_t vfo, freq_t tx_freq, rmode_t tx_mode, pbwidth_t tx_width)
{
int status;
struct icom_priv_data * priv = (struct icom_priv_data *)rig->state.priv;
/* This method works also in memory mode(RIG_VFO_MEM) */
if (!priv->no_xchg && rig_has_vfo_op(rig, RIG_OP_XCHG)) {
status = icom_vfo_op(rig, vfo, RIG_OP_XCHG);
if (status != RIG_OK) return status;
status = rig_set_freq(rig, RIG_VFO_CURR, tx_freq);
if (status != RIG_OK) return status;
status = rig->caps->set_mode(rig, RIG_VFO_CURR, tx_mode, tx_width);
if (status != RIG_OK) return status;
status = icom_vfo_op(rig, vfo, RIG_OP_XCHG);
if (status != RIG_OK) return status;
return 0;
}
vfo_t curr_vfo;
freq_t split_freq;
rmode_t split_mode;
pbwidth_t split_width;
status = get_split_status (rig, &curr_vfo, &split_freq,
&split_mode, &split_width);
if (status != RIG_OK) return status;
status = rig_set_freq(rig, RIG_VFO_CURR, tx_freq);
if (status != RIG_OK) return status;
status = rig->caps->set_mode(rig, RIG_VFO_CURR, tx_mode, tx_width);
if (status != RIG_OK) return status;
if (!tx_split && (second_freq != orig_freq
|| second_mode != orig_mode
|| second_width != orig_width
|| priv->split_on)) {
/* Rx VFO must have been selected when we started so switch back
to it. We may be wrong but in that case A & B are the same so
it doesn't matter so long as changing split Tx is always B */
status = icom_set_vfo(rig, rx_vfo);
}
if (curr_vfo != RIG_VFO_NONE)
{
status = icom_set_vfo(rig, curr_vfo);
}
return status;
}