kopia lustrzana https://github.com/Hamlib/Hamlib
11551 wiersze
303 KiB
C
11551 wiersze
303 KiB
C
/*
|
|
* hamlib - (C) Frank Singleton 2000 (javabear at users.sourceforge.net)
|
|
* and the Hamlib Group (hamlib-developer at lists.sourceforge.net)
|
|
*
|
|
* newcat.c - (C) Nate Bargmann 2007 (n0nb at arrl.net)
|
|
* (C) Stephane Fillod 2008-2010
|
|
* (C) Terry Embry 2008-2010
|
|
* (C) David Fannin (kk6df at arrl.net)
|
|
*
|
|
* This shared library provides an API for communicating
|
|
* via serial interface to any newer Yaesu radio using the
|
|
* "new" text CAT interface.
|
|
*
|
|
* 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
|
|
*
|
|
*/
|
|
|
|
|
|
#include <hamlib/config.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h> /* String function definitions */
|
|
#include <math.h>
|
|
|
|
#include "hamlib/rig.h"
|
|
#include "iofunc.h"
|
|
#include "misc.h"
|
|
#include "cal.h"
|
|
#include "newcat.h"
|
|
|
|
/* global variables */
|
|
static const char cat_term = ';'; /* Yaesu command terminator */
|
|
// static const char cat_unknown_cmd[] = "?;"; /* Yaesu ? */
|
|
|
|
/* Internal Backup and Restore VFO Memory Channels */
|
|
#define NC_MEM_CHANNEL_NONE 2012
|
|
#define NC_MEM_CHANNEL_VFO_A 2013
|
|
#define NC_MEM_CHANNEL_VFO_B 2014
|
|
|
|
/* ID 0310 == 310, Must drop leading zero */
|
|
typedef enum nc_rigid_e
|
|
{
|
|
NC_RIGID_NONE = 0,
|
|
NC_RIGID_FT450 = 241,
|
|
NC_RIGID_FT450D = 244,
|
|
NC_RIGID_FT950 = 310,
|
|
NC_RIGID_FT891 = 135,
|
|
NC_RIGID_FT991 = 135,
|
|
NC_RIGID_FT2000 = 251,
|
|
NC_RIGID_FT2000D = 252,
|
|
NC_RIGID_FTDX1200 = 583,
|
|
NC_RIGID_FTDX9000D = 101,
|
|
NC_RIGID_FTDX9000Contest = 102,
|
|
NC_RIGID_FTDX9000MP = 103,
|
|
NC_RIGID_FTDX5000 = 362,
|
|
NC_RIGID_FTDX3000 = 460,
|
|
NC_RIGID_FTDX3000DM = 462, // an undocumented FT-DX3000DM 50W rig
|
|
NC_RIGID_FTDX101D = 681,
|
|
NC_RIGID_FTDX101MP = 682
|
|
} nc_rigid_t;
|
|
|
|
|
|
/*
|
|
* The following table defines which commands are valid for any given
|
|
* rig supporting the "new" CAT interface.
|
|
*/
|
|
|
|
typedef struct _yaesu_newcat_commands
|
|
{
|
|
char *command;
|
|
ncboolean ft450;
|
|
ncboolean ft950;
|
|
ncboolean ft891;
|
|
ncboolean ft991;
|
|
ncboolean ft2000;
|
|
ncboolean ft9000;
|
|
ncboolean ft5000;
|
|
ncboolean ft1200;
|
|
ncboolean ft3000;
|
|
ncboolean ft101d;
|
|
ncboolean ft10;
|
|
ncboolean ft101mp;
|
|
} yaesu_newcat_commands_t;
|
|
|
|
/**
|
|
* Yaesu FT-991 S-meter scale, default for new Yaesu rigs.
|
|
* Determined by data from W6HN -- seems to be pretty linear
|
|
*
|
|
* SMeter, rig answer, %fullscale
|
|
* S0 SM0000 0
|
|
* S2 SM0026 10
|
|
* S4 SM0051 20
|
|
* S6 SM0081 30
|
|
* S7.5 SM0105 40
|
|
* S9 SM0130 50
|
|
* +12db SM0157 60
|
|
* +25db SM0186 70
|
|
* +35db SM0203 80
|
|
* +50db SM0237 90
|
|
* +60db SM0255 100
|
|
*
|
|
* 114dB range over 0-255 referenced to S0 of -54dB
|
|
*/
|
|
const cal_table_t yaesu_default_str_cal =
|
|
{
|
|
11,
|
|
{
|
|
{ 0, -54, }, // S0
|
|
{ 26, -42, }, // S2
|
|
{ 51, -30, }, // S4
|
|
{ 81, -18, }, // S6
|
|
{ 105, -9, }, // S7.5
|
|
{ 130, 0, }, // S9
|
|
{ 157, 12, }, // S9+12dB
|
|
{ 186, 25, }, // S9+25dB
|
|
{ 203, 35, }, // S9+35dB
|
|
{ 237, 50, }, // S9+50dB
|
|
{ 255, 60, }, // S9+60dB
|
|
}
|
|
};
|
|
|
|
/**
|
|
* First cut at generic Yaesu table, need more points probably
|
|
* based on testing by Adam M7OTP on FT-991
|
|
*/
|
|
const cal_table_float_t yaesu_default_swr_cal =
|
|
{
|
|
5,
|
|
{
|
|
{12, 1.0f},
|
|
{39, 1.35f},
|
|
{65, 1.5f},
|
|
{89, 2.0f},
|
|
{242, 5.0f}
|
|
}
|
|
};
|
|
|
|
// TODO: Provide sane defaults
|
|
const cal_table_float_t yaesu_default_alc_cal =
|
|
{
|
|
2,
|
|
{
|
|
{0, 0.0f},
|
|
{64, 1.0f}
|
|
}
|
|
};
|
|
|
|
const cal_table_float_t yaesu_default_comp_meter_cal =
|
|
{
|
|
9,
|
|
{
|
|
{ 0, 0.0f },
|
|
{ 40, 2.5f },
|
|
{ 60, 5.0f },
|
|
{ 85, 7.5f },
|
|
{ 135, 10.0f },
|
|
{ 150, 12.5f },
|
|
{ 175, 15.0f },
|
|
{ 195, 17.5f },
|
|
{ 220, 20.0f }
|
|
}
|
|
};
|
|
|
|
// TODO: Provide sane defaults
|
|
const cal_table_float_t yaesu_default_rfpower_meter_cal =
|
|
{
|
|
3,
|
|
{
|
|
{0, 0.0f},
|
|
{148, 50.0f},
|
|
{255, 100.0f},
|
|
}
|
|
};
|
|
|
|
const cal_table_float_t yaesu_default_vd_meter_cal =
|
|
{
|
|
3,
|
|
{
|
|
{0, 0.0f},
|
|
{196, 13.8f},
|
|
{255, 17.95f},
|
|
}
|
|
};
|
|
|
|
const cal_table_float_t yaesu_default_id_meter_cal =
|
|
{
|
|
3,
|
|
{
|
|
{0, 0.0f},
|
|
{100, 10.0f},
|
|
{255, 25.5f},
|
|
}
|
|
};
|
|
|
|
// Easy reference to rig model -- it is set in newcat_valid_command
|
|
static ncboolean is_ft450;
|
|
static ncboolean is_ft891;
|
|
static ncboolean is_ft950;
|
|
static ncboolean is_ft991;
|
|
static ncboolean is_ft2000;
|
|
static ncboolean is_ftdx9000;
|
|
static ncboolean is_ftdx5000;
|
|
static ncboolean is_ftdx1200;
|
|
static ncboolean is_ftdx3000;
|
|
static ncboolean is_ftdx3000dm;
|
|
static ncboolean is_ftdx101d;
|
|
static ncboolean is_ftdx101mp;
|
|
static ncboolean is_ftdx10;
|
|
|
|
/*
|
|
* Even thought this table does make a handy reference, it could be depreciated as it is not really needed.
|
|
* All of the CAT commands used in the newcat interface are available on the FT-950, FT-2000, FT-5000, and FT-9000.
|
|
* There are 5 CAT commands used in the newcat interface that are not available on the FT-450.
|
|
* Thesec CAT commands are XT -TX Clarifier ON/OFF, AN - Antenna select, PL - Speech Proc Level,
|
|
* PR - Speech Proc ON/OFF, and BC - Auto Notch filter ON/OFF.
|
|
* The FT-450 returns -RIG_ENVAIL for these unavailable CAT commands.
|
|
*
|
|
* NOTE: The following table must be in alphabetical order by the
|
|
* command. This is because it is searched using a binary search
|
|
* to determine whether or not a command is valid for a given rig.
|
|
*
|
|
* The list of supported commands is obtained from the rig's operator's
|
|
* or CAT programming manual.
|
|
*
|
|
*/
|
|
static const yaesu_newcat_commands_t valid_commands[] =
|
|
{
|
|
/* Command FT-450 FT-950 FT-891 FT-991 FT-2000 FT-9000 FT-5000 FT-1200 FT-3000 FTDX101D FTDX10 FTDX101MP */
|
|
{"AB", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"AC", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"AG", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"AI", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"AM", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"AN", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE },
|
|
{"AO", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE },
|
|
{"BA", FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"BC", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"BD", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"BI", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"BM", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE },
|
|
{"BP", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"BS", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"BU", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"BY", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"CH", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"CN", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"CO", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"CS", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"CT", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"DA", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"DN", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"DT", FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE },
|
|
{"DP", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE },
|
|
{"DS", TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE },
|
|
{"ED", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"EK", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE },
|
|
{"EM", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE },
|
|
{"EN", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"EU", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"EX", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"FA", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"FB", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"FK", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE },
|
|
{"FN", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE },
|
|
{"FR", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"FS", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"FT", TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"GT", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"ID", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"IF", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"IS", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"KM", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"KP", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"KR", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"KS", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"KY", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"LK", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"LM", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"MA", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"MB", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE },
|
|
{"MC", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"MD", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"MG", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"MK", TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE },
|
|
{"ML", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"MR", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"MS", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"MT", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE },
|
|
{"MW", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"MX", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"NA", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"NB", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"NL", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"NR", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"OI", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"OS", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"PA", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"PB", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"PC", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"PL", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"PR", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"PS", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"QI", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"QR", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"QS", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"RA", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"RC", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"RD", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"RF", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"RG", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"RI", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"RL", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"RM", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"RO", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE },
|
|
{"RP", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE },
|
|
{"RS", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"RT", TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"RU", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"SC", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"SD", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"SF", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"SH", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"SM", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"SQ", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"SS", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE },
|
|
// ST command has two meanings Step or Split Status
|
|
// If new rig is added that has ST ensure it means Split
|
|
// Otherwise modify newcat_get_tx_vfo
|
|
{"ST", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE },
|
|
{"SV", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"SY", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE },
|
|
{"TS", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"TX", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"UL", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"UP", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"VD", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"VF", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE },
|
|
{"VG", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"VM", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"VR", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE },
|
|
{"VS", TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"VT", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE },
|
|
{"VV", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE },
|
|
{"VX", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"XT", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
|
|
{"ZI", FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE },
|
|
} ;
|
|
|
|
int valid_commands_count = sizeof(valid_commands) / sizeof(
|
|
yaesu_newcat_commands_t);
|
|
|
|
/*
|
|
* configuration Tokens
|
|
*
|
|
*/
|
|
|
|
#define TOK_FAST_SET_CMD TOKEN_BACKEND(1)
|
|
|
|
const struct confparams newcat_cfg_params[] =
|
|
{
|
|
{
|
|
TOK_FAST_SET_CMD, "fast_commands_token", "High throughput of commands", "Enabled high throughput of >200 messages/sec by not waiting for ACK/NAK of messages", "0", RIG_CONF_NUMERIC, { .n = { 0, 1, 1 } }
|
|
},
|
|
{ RIG_CONF_END, NULL, }
|
|
};
|
|
|
|
/* NewCAT Internal Functions */
|
|
static ncboolean newcat_is_rig(RIG *rig, rig_model_t model);
|
|
|
|
static int newcat_set_vfo_from_alias(RIG *rig, vfo_t *vfo);
|
|
static int newcat_scale_float(int scale, float fval);
|
|
static int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode,
|
|
pbwidth_t *width);
|
|
static int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode,
|
|
pbwidth_t width);
|
|
static int newcat_set_narrow(RIG *rig, vfo_t vfo, ncboolean narrow);
|
|
static int newcat_get_narrow(RIG *rig, vfo_t vfo, ncboolean *narrow);
|
|
static int newcat_set_faststep(RIG *rig, ncboolean fast_step);
|
|
static int newcat_get_faststep(RIG *rig, ncboolean *fast_step);
|
|
static int newcat_get_rigid(RIG *rig);
|
|
static int newcat_get_vfo_mode(RIG *rig, vfo_t vfo, rmode_t *vfo_mode);
|
|
static int newcat_vfomem_toggle(RIG *rig);
|
|
static int set_roofing_filter(RIG *rig, vfo_t vfo, int index);
|
|
static int set_roofing_filter_for_width(RIG *rig, vfo_t vfo, int width);
|
|
static int get_roofing_filter(RIG *rig, vfo_t vfo,
|
|
struct newcat_roofing_filter **roofing_filter);
|
|
static int newcat_set_apf_frequency(RIG *rig, vfo_t vfo, int freq);
|
|
static int newcat_get_apf_frequency(RIG *rig, vfo_t vfo, int *freq);
|
|
static int newcat_set_apf_width(RIG *rig, vfo_t vfo, int choice);
|
|
static int newcat_get_apf_width(RIG *rig, vfo_t vfo, int *choice);
|
|
static int newcat_set_contour(RIG *rig, vfo_t vfo, int status);
|
|
static int newcat_get_contour(RIG *rig, vfo_t vfo, int *status);
|
|
static int newcat_set_contour_frequency(RIG *rig, vfo_t vfo, int freq);
|
|
static int newcat_get_contour_frequency(RIG *rig, vfo_t vfo, int *freq);
|
|
static int newcat_set_contour_level(RIG *rig, vfo_t vfo, int level);
|
|
static int newcat_get_contour_level(RIG *rig, vfo_t vfo, int *level);
|
|
static int newcat_set_contour_width(RIG *rig, vfo_t vfo, int width);
|
|
static int newcat_get_contour_width(RIG *rig, vfo_t vfo, int *width);
|
|
static ncboolean newcat_valid_command(RIG *rig, char const *const command);
|
|
|
|
/*
|
|
* The BS command needs to know what band we're on so we can restore band info
|
|
* So this converts freq to band index
|
|
*/
|
|
static int newcat_band_index(freq_t freq)
|
|
{
|
|
int band = 11; // general
|
|
|
|
// restrict band memory recall to ITU 1,2,3 band ranges
|
|
// using < instead of <= for the moment
|
|
// does anybody work LSB or RTTYR at the upper band edge?
|
|
// what about band 13 -- what is it?
|
|
if (freq >= MHz(420) && freq < MHz(470)) { band = 16; }
|
|
else if (freq >= MHz(144) && freq < MHz(148)) { band = 15; }
|
|
// band 14 is RX only
|
|
// override band 15 with 14 if needed
|
|
else if (freq >= MHz(118) && freq < MHz(164)) { band = 14; }
|
|
else if (freq >= MHz(70) && freq < MHz(70.5)) { band = 17; }
|
|
else if (freq >= MHz(50) && freq < MHz(55)) { band = 10; }
|
|
else if (freq >= MHz(28) && freq < MHz(29.7)) { band = 9; }
|
|
else if (freq >= MHz(24.890) && freq < MHz(24.990)) { band = 8; }
|
|
else if (freq >= MHz(21) && freq < MHz(21.45)) { band = 7; }
|
|
else if (freq >= MHz(18) && freq < MHz(18.168)) { band = 6; }
|
|
else if (freq >= MHz(14) && freq < MHz(14.35)) { band = 5; }
|
|
else if (freq >= MHz(10) && freq < MHz(10.15)) { band = 4; }
|
|
else if (freq >= MHz(7) && freq < MHz(7.3)) { band = 3; }
|
|
else if (freq >= MHz(5.3515) && freq < MHz(5.3665)) { band = 2; }
|
|
else if (freq >= MHz(3.5) && freq < MHz(4)) { band = 1; }
|
|
else if (freq >= MHz(1.8) && freq < MHz(2)) { band = 0; }
|
|
else if (freq >= MHz(0.5) && freq < MHz(1.705)) { band = 12; } // MW Medium Wave
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: freq=%g, band=%d\n", __func__, freq, band);
|
|
return (band);
|
|
}
|
|
|
|
/*
|
|
* ************************************
|
|
*
|
|
* Hamlib API functions
|
|
*
|
|
* ************************************
|
|
*/
|
|
|
|
/*
|
|
* rig_init
|
|
*
|
|
*/
|
|
|
|
int newcat_init(RIG *rig)
|
|
{
|
|
struct newcat_priv_data *priv;
|
|
|
|
ENTERFUNC;
|
|
|
|
rig->state.priv = (struct newcat_priv_data *) calloc(1,
|
|
sizeof(struct newcat_priv_data));
|
|
|
|
if (!rig->state.priv) /* whoops! memory shortage! */
|
|
{
|
|
RETURNFUNC(-RIG_ENOMEM);
|
|
}
|
|
|
|
priv = rig->state.priv;
|
|
|
|
// priv->current_vfo = RIG_VFO_MAIN; /* default to whatever */
|
|
// priv->current_vfo = RIG_VFO_A;
|
|
|
|
priv->rig_id = NC_RIGID_NONE;
|
|
priv->current_mem = NC_MEM_CHANNEL_NONE;
|
|
priv->fast_set_commands = FALSE;
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_cleanup
|
|
*
|
|
* the serial port is closed by the frontend
|
|
*
|
|
*/
|
|
|
|
int newcat_cleanup(RIG *rig)
|
|
{
|
|
|
|
ENTERFUNC;
|
|
|
|
if (rig->state.priv)
|
|
{
|
|
free(rig->state.priv);
|
|
}
|
|
|
|
rig->state.priv = NULL;
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_open
|
|
*
|
|
* New CAT does not support pacing
|
|
*
|
|
*/
|
|
|
|
int newcat_open(RIG *rig)
|
|
{
|
|
struct newcat_priv_data *priv = rig->state.priv;
|
|
struct rig_state *rig_s = &rig->state;
|
|
const char *handshake[3] = {"None", "Xon/Xoff", "Hardware"};
|
|
|
|
ENTERFUNC;
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: Rig=%s, version=%s\n", __func__,
|
|
rig->caps->model_name, rig->caps->version);
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: write_delay = %i msec\n",
|
|
__func__, rig_s->rigport.write_delay);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: post_write_delay = %i msec\n",
|
|
__func__, rig_s->rigport.post_write_delay);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: serial_handshake = %s \n",
|
|
__func__, handshake[rig->caps->serial_handshake]);
|
|
|
|
/* Ensure rig is powered on */
|
|
if (priv->poweron == 0 && rig_s->auto_power_on)
|
|
{
|
|
rig_set_powerstat(rig, 1);
|
|
priv->poweron = 1;
|
|
}
|
|
|
|
priv->question_mark_response_means_rejected = 0;
|
|
|
|
/* get current AI state so it can be restored */
|
|
priv->trn_state = -1;
|
|
|
|
// for this sequence we will shorten the timeout so we can detect rig is powered off faster
|
|
int timeout = rig->state.rigport.timeout;
|
|
rig->state.rigport.timeout = 100;
|
|
newcat_get_trn(rig, &priv->trn_state); /* ignore errors */
|
|
|
|
/* Currently we cannot cope with AI mode so turn it off in case
|
|
last client left it on */
|
|
if (priv->trn_state > 0)
|
|
{
|
|
newcat_set_trn(rig, RIG_TRN_OFF);
|
|
} /* ignore status in case it's not supported */
|
|
|
|
/* Initialize rig_id in case any subsequent commands need it */
|
|
(void)newcat_get_rigid(rig);
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: rig_id=%d\n", __func__, priv->rig_id);
|
|
rig->state.rigport.timeout = timeout;
|
|
|
|
#if 0 // possible future enhancement?
|
|
|
|
// some rigs have a CAT TOT timeout that defaults to 10ms
|
|
// so we'll increase CAT timeout to 100ms
|
|
if (priv->rig_id == NC_RIGID_FT2000
|
|
|| priv->rig_id == NC_RIGID_FT2000D
|
|
|| priv->rig_id == NC_RIGID_FT891
|
|
|| priv->rig_id == NC_RIGID_FT991
|
|
|| priv->rig_id == NC_RIGID_FT950)
|
|
{
|
|
int err;
|
|
char *cmd = "EX0291%c";
|
|
|
|
if (priv->rig_id == NC_RIGID_FT950) { cmd = "EX0271%c"; }
|
|
else if (priv->rig_id == NC_RIGID_FT891) { cmd = "EX05071c"; }
|
|
else if (priv->rig_id == NC_RIGID_FT991) { cmd = "EX0321c"; }
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), cmd, cat_term);
|
|
|
|
if (RIG_OK != (err = newcat_set_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
if (priv->rig_id == NC_RIGID_FTDX3000)
|
|
{
|
|
rig->state.disable_yaesu_bandselect = 1;
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: disabling FTDX3000 band select\n", __func__);
|
|
}
|
|
|
|
if (priv->rig_id == NC_RIGID_FTDX5000)
|
|
{
|
|
int err;
|
|
// set the CAT TIME OUT TIMER to 100ms
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX0331");
|
|
if (RIG_OK != (err = newcat_set_cmd(rig)))
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: FTDX5000 CAT RATE error: %s\n", __func__, rigerror(err));
|
|
}
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_close
|
|
*
|
|
*/
|
|
|
|
int newcat_close(RIG *rig)
|
|
{
|
|
|
|
struct newcat_priv_data *priv = rig->state.priv;
|
|
struct rig_state *rig_s = &rig->state;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!no_restore_ai && priv->trn_state >= 0)
|
|
{
|
|
/* restore AI state */
|
|
newcat_set_trn(rig, priv->trn_state); /* ignore status in
|
|
case it's not
|
|
supported */
|
|
}
|
|
|
|
if (priv->poweron != 0 && rig_s->auto_power_off)
|
|
{
|
|
rig_set_powerstat(rig, 0);
|
|
priv->poweron = 0;
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_set_config
|
|
*
|
|
* Set Configuration Token for Yaesu Radios
|
|
*/
|
|
|
|
int newcat_set_conf(RIG *rig, token_t token, const char *val)
|
|
{
|
|
int ret = RIG_OK;
|
|
struct newcat_priv_data *priv;
|
|
|
|
ENTERFUNC;
|
|
|
|
priv = (struct newcat_priv_data *)rig->state.priv;
|
|
|
|
if (priv == NULL)
|
|
{
|
|
RETURNFUNC(-RIG_EINTERNAL);
|
|
}
|
|
|
|
switch (token)
|
|
{
|
|
char *end;
|
|
long value;
|
|
|
|
case TOK_FAST_SET_CMD: ;
|
|
//using strtol because atoi can lead to undefined behaviour
|
|
value = strtol(val, &end, 10);
|
|
|
|
if (end == val)
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
if ((value == 0) || (value == 1))
|
|
{
|
|
priv->fast_set_commands = (int)value;
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
ret = -RIG_EINVAL;
|
|
}
|
|
|
|
RETURNFUNC(ret);
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_get_config
|
|
*
|
|
* Get Configuration Token for Yaesu Radios
|
|
*/
|
|
|
|
int newcat_get_conf2(RIG *rig, token_t token, char *val, int val_len)
|
|
{
|
|
int ret = RIG_OK;
|
|
struct newcat_priv_data *priv;
|
|
|
|
ENTERFUNC;
|
|
|
|
priv = (struct newcat_priv_data *)rig->state.priv;
|
|
|
|
if (priv == NULL)
|
|
{
|
|
RETURNFUNC(-RIG_EINTERNAL);
|
|
}
|
|
|
|
switch (token)
|
|
{
|
|
case TOK_FAST_SET_CMD:
|
|
if (sizeof(val) < 2)
|
|
{
|
|
RETURNFUNC(-RIG_ENOMEM);
|
|
}
|
|
|
|
SNPRINTF(val, val_len, "%d", priv->fast_set_commands);
|
|
break;
|
|
|
|
default:
|
|
ret = -RIG_EINVAL;
|
|
}
|
|
|
|
RETURNFUNC(ret);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* newcat_set_freq
|
|
*
|
|
* Set frequency for a given VFO
|
|
* RIG_TARGETABLE_VFO
|
|
* Does not SET priv->current_vfo
|
|
*
|
|
*/
|
|
|
|
int newcat_60m_exception(RIG *rig, freq_t freq)
|
|
{
|
|
// can we improve this to set memory mode and pick the memory slot?
|
|
if (is_ftdx10 && freq > 5.2 && freq < 5.5)
|
|
{
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: 60M exception ignoring freq/mode commands\n", __func__);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int newcat_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
|
|
{
|
|
char c;
|
|
char target_vfo;
|
|
int err;
|
|
const struct rig_caps *caps;
|
|
struct newcat_priv_data *priv;
|
|
int special_60m = 0;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (newcat_60m_exception(rig,freq)) RETURNFUNC(RIG_OK); // we don't set freq in this case
|
|
|
|
if (!newcat_valid_command(rig, "FA"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (!newcat_valid_command(rig, "FB"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
priv = (struct newcat_priv_data *)rig->state.priv;
|
|
caps = rig->caps;
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: passed vfo = %s\n", __func__, rig_strvfo(vfo));
|
|
// rig_debug(RIG_DEBUG_TRACE, "%s: translated vfo = %s\n", __func__, rig_strvfo(tvfo));
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: passed freq = %"PRIfreq" Hz\n", __func__, freq);
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
ERRMSG(err, "newcat_set_vfo_from_alias");
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/* vfo should now be modified to a valid VFO constant. */
|
|
/* DX3000/DX5000/450 can only do VFO_MEM on 60M */
|
|
/* So we will not change freq in that case */
|
|
// did have FTDX3000 as not capable of 60M set_freq but as of 2021-01-21 it works
|
|
// special_60m = newcat_is_rig(rig, RIG_MODEL_FTDX3000);
|
|
/* duplicate the following line to add more rigs */
|
|
// disabled to check 2019 firmware on FTDX5000 and FT450 behavior
|
|
//special_60m = newcat_is_rig(rig, RIG_MODEL_FTDX5000);
|
|
//special_60m |= newcat_is_rig(rig, RIG_MODEL_FT450);
|
|
rig_debug(RIG_DEBUG_TRACE,
|
|
"%s: special_60m=%d, 60m freq=%d, is_ftdx3000=%d,is_ftdx3000dm=%d\n",
|
|
__func__, special_60m, freq >= 5300000
|
|
&& freq <= 5410000, is_ftdx3000, is_ftdx3000dm);
|
|
|
|
if (special_60m && (freq >= 5300000 && freq <= 5410000))
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: 60M VFO_MEM exception, no freq change done\n",
|
|
__func__);
|
|
RETURNFUNC(RIG_OK); /* make it look like we changed */
|
|
}
|
|
|
|
switch (vfo)
|
|
{
|
|
case RIG_VFO_A:
|
|
case RIG_VFO_MAIN:
|
|
case RIG_VFO_MEM:
|
|
c = 'A';
|
|
break;
|
|
|
|
case RIG_VFO_B:
|
|
case RIG_VFO_SUB:
|
|
c = 'B';
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_ENIMPL); /* Only VFO_A or VFO_B are valid */
|
|
}
|
|
|
|
target_vfo = 'A' == c ? '0' : '1';
|
|
|
|
// some rigs like FTDX101D cannot change non-TX vfo freq
|
|
// but they can change the TX vfo
|
|
if ((is_ftdx101d || is_ftdx101mp) && rig->state.cache.ptt == RIG_PTT_ON)
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: ftdx101 check vfo OK, vfo=%s, tx_vfo=%s\n",
|
|
__func__, rig_strvfo(vfo), rig_strvfo(rig->state.tx_vfo));
|
|
|
|
// when in split we can change VFOB but not VFOA
|
|
if (rig->state.cache.split == RIG_SPLIT_ON && target_vfo == '0') { return -RIG_ENTARGET; }
|
|
|
|
// when not in split we can't change VFOA at all
|
|
if (rig->state.cache.split == RIG_SPLIT_OFF && target_vfo == '0') { return -RIG_ENTARGET; }
|
|
|
|
if (vfo != rig->state.tx_vfo) { return -RIG_ENTARGET; }
|
|
}
|
|
|
|
if (is_ftdx3000 || is_ftdx3000dm || is_ftdx5000)
|
|
{
|
|
// we have a few rigs that can't set freq while PTT_ON
|
|
// so we'll try a few times to see if we just need to wait a bit
|
|
// 3 retries should be about 400ms -- hopefully more than enough
|
|
ptt_t ptt;
|
|
int retry = 3;
|
|
|
|
do
|
|
{
|
|
if (RIG_OK != (err = newcat_get_ptt(rig, vfo, &ptt)))
|
|
{
|
|
ERRMSG(err, "newcat_set_cmd failed");
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (ptt == RIG_PTT_ON)
|
|
{
|
|
rig_debug(RIG_DEBUG_WARN, "%s: ptt still on...retry#%d\n", __func__, retry);
|
|
hl_usleep(100 * 1000); // 100ms pause if ptt still on
|
|
}
|
|
}
|
|
while (err == RIG_OK && ptt == RIG_PTT_ON && retry-- > 0);
|
|
|
|
if (ptt) { return -RIG_ENTARGET; }
|
|
}
|
|
|
|
if (RIG_MODEL_FT450 == caps->rig_model)
|
|
{
|
|
/* The FT450 only accepts F[A|B]nnnnnnnn; commands for the
|
|
current VFO so we must use the VS[0|1]; command to check
|
|
and select the correct VFO before setting the frequency
|
|
*/
|
|
// Plus we can't do the VFO swap if transmitting
|
|
if (target_vfo == '1' && rig->state.cache.ptt == RIG_PTT_ON) { RETURNFUNC(-RIG_ENTARGET); }
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VS%c", cat_term);
|
|
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
ERRMSG(err, "newcat_get_cmd");
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (priv->ret_data[2] != target_vfo)
|
|
{
|
|
HAMLIB_TRACE;
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VS%c%c", target_vfo, cat_term);
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
if (RIG_OK != (err = newcat_set_cmd(rig)))
|
|
{
|
|
ERRMSG(err, "newcat_set_cmd failed");
|
|
RETURNFUNC(err);
|
|
}
|
|
}
|
|
}
|
|
|
|
// W1HKJ
|
|
// creation of the priv structure guarantees that the string can be NEWCAT_DATA_LEN
|
|
// bytes in length. the SNPRINTF will only allow (NEWCAT_DATA_LEN - 1) chars
|
|
// followed by the NULL terminator.
|
|
// CAT command string for setting frequency requires that 8 digits be sent
|
|
// including leading fill zeros
|
|
// Call this after open to set width_frequency for later use
|
|
if (priv->width_frequency == 0)
|
|
{
|
|
rmode_t vfo_mode;
|
|
newcat_get_vfo_mode(rig, vfo, &vfo_mode);
|
|
}
|
|
|
|
//
|
|
// Restore band memory if we can and band is changing -- we do it before we set the frequency
|
|
// And only when not in split mode (note this check has been removed for testing)
|
|
int changing;
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s(%d)%s: rig->state.current_vfo=%s\n", __FILE__,
|
|
__LINE__, __func__, rig_strvfo(rig->state.current_vfo));
|
|
|
|
CACHE_RESET;
|
|
|
|
if (vfo == RIG_VFO_A || vfo == RIG_VFO_MAIN)
|
|
{
|
|
freq_t freqA;
|
|
rig_get_freq(rig, RIG_VFO_A, &freqA);
|
|
rig_debug(RIG_DEBUG_TRACE, "%s(%d)%s: checking VFOA for band change \n",
|
|
__FILE__, __LINE__, __func__);
|
|
|
|
changing = newcat_band_index(freq) != newcat_band_index(freqA);
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: VFO_A band changing=%d\n", __func__, changing);
|
|
}
|
|
else
|
|
{
|
|
freq_t freqB;
|
|
rig_get_freq(rig, RIG_VFO_B, &freqB);
|
|
rig_debug(RIG_DEBUG_TRACE, "%s(%d)%s: checking VFOB for band change \n",
|
|
__FILE__, __LINE__, __func__);
|
|
|
|
changing = newcat_band_index(freq) != newcat_band_index(freqB);
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: VFO_B band changing=%d\n", __func__, changing);
|
|
}
|
|
|
|
if (newcat_valid_command(rig, "BS") && changing
|
|
&& !rig->state.disable_yaesu_bandselect
|
|
// remove the split check here -- hopefully works OK
|
|
//&& !rig->state.cache.split
|
|
// seems some rigs are problematic
|
|
// && !(is_ftdx3000 || is_ftdx3000dm)
|
|
// some rigs can't do BS command on 60M
|
|
// && !(is_ftdx3000 || is_ftdx3000dm && newcat_band_index(freq) == 2)
|
|
&& !(is_ft2000 && newcat_band_index(freq) == 2)
|
|
&& !(is_ftdx1200 && newcat_band_index(freq) == 2)
|
|
&& !is_ft891 // 891 does not remember bandwidth so don't do this
|
|
&& !is_ft991 // 991 does not behave well with bandstack changes
|
|
&& rig->caps->get_vfo != NULL
|
|
&& rig->caps->set_vfo != NULL) // gotta' have get_vfo too
|
|
{
|
|
HAMLIB_TRACE;
|
|
|
|
if (rig->state.current_vfo != vfo)
|
|
{
|
|
int vfo1 = 1, vfo2 = 0;
|
|
|
|
if (vfo == RIG_VFO_A || vfo == RIG_VFO_MAIN)
|
|
{
|
|
vfo1 = 0;
|
|
vfo2 = 1;
|
|
}
|
|
|
|
// we need to change vfos, BS, and change back
|
|
if (!is_ft991 && !is_ft891 && newcat_valid_command(rig, "VS"))
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VS%d;BS%02d%c",
|
|
vfo1, newcat_band_index(freq), cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BS%02d%c",
|
|
newcat_band_index(freq), cat_term);
|
|
}
|
|
|
|
|
|
if (RIG_OK != (err = newcat_set_cmd(rig)))
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: Unexpected error with BS command#1=%s\n",
|
|
__func__, rigerror(err));
|
|
}
|
|
|
|
hl_usleep(500 * 1000); // wait for BS to do it's thing and swap back
|
|
|
|
if (newcat_valid_command(rig, "VS"))
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VS%d;", vfo2);
|
|
|
|
if (RIG_OK != (err = newcat_set_cmd(rig)))
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: Unexpected error with BS command#3=%s\n",
|
|
__func__, rigerror(err));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BS%02d%c",
|
|
newcat_band_index(freq), cat_term);
|
|
|
|
if (RIG_OK != (err = newcat_set_cmd(rig)))
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: Unexpected error with BS command#2=%s\n",
|
|
__func__, rigerror(err));
|
|
}
|
|
|
|
hl_usleep(500 * 1000); // wait for BS to do it's thing
|
|
}
|
|
|
|
|
|
#if 0 // disable for testing
|
|
else
|
|
{
|
|
// Also need to do this for the other VFO on some Yaesu rigs
|
|
// is redundant for rigs where band stack includes both vfos
|
|
vfo_t vfotmp;
|
|
freq_t freqtmp;
|
|
err = rig_get_vfo(rig, &vfotmp);
|
|
|
|
if (err != RIG_OK) { RETURNFUNC(err); }
|
|
|
|
if (rig->state.vfo_list & RIG_VFO_MAIN)
|
|
{
|
|
err = rig_set_vfo(rig, vfotmp == RIG_VFO_MAIN ? RIG_VFO_SUB : RIG_VFO_MAIN);
|
|
}
|
|
else
|
|
{
|
|
err = rig_set_vfo(rig, vfotmp == RIG_VFO_A ? RIG_VFO_B : RIG_VFO_A);
|
|
}
|
|
|
|
if (err != RIG_OK) { RETURNFUNC(err); }
|
|
|
|
rig_get_freq(rig, RIG_VFO_CURR, &freqtmp);
|
|
|
|
if (err != RIG_OK) { RETURNFUNC(err); }
|
|
|
|
// Cross band should work too
|
|
// If the BS works on both VFOs then VFOB will have the band select answer
|
|
// so now change needed
|
|
// If the BS is by VFO then we'll need to do BS for the other VFO too
|
|
if (newcat_band_index(freqtmp) != newcat_band_index(freq))
|
|
{
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BS%02d%c",
|
|
newcat_band_index(freq), cat_term);
|
|
|
|
if (RIG_OK != (err = newcat_set_cmd(rig)))
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: Unexpected error with BS command#3=%s\n",
|
|
__func__,
|
|
rigerror(err));
|
|
}
|
|
}
|
|
|
|
// switch back to the starting vfo
|
|
if (rig->state.vfo_list & RIG_VFO_MAIN)
|
|
{
|
|
err = rig_set_vfo(rig, vfotmp == RIG_VFO_MAIN ? RIG_VFO_MAIN : RIG_VFO_SUB);
|
|
}
|
|
else
|
|
{
|
|
err = rig_set_vfo(rig, vfotmp == RIG_VFO_A ? RIG_VFO_A : RIG_VFO_B);
|
|
}
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: rig_set_vfo failed: %s\n", __func__,
|
|
rigerror(err));
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
// after band select re-read things -- may not have to change anything
|
|
freq_t tmp_freqA, tmp_freqB;
|
|
rmode_t tmp_mode;
|
|
pbwidth_t tmp_width;
|
|
|
|
rig_get_freq(rig, RIG_VFO_MAIN, &tmp_freqA);
|
|
rig_get_freq(rig, RIG_VFO_SUB, &tmp_freqB);
|
|
rig_get_mode(rig, RIG_VFO_MAIN, &tmp_mode, &tmp_width);
|
|
rig_get_mode(rig, RIG_VFO_SUB, &tmp_mode, &tmp_width);
|
|
|
|
if ((target_vfo == 0 && tmp_freqA == freq)
|
|
|| (target_vfo == 1 && tmp_freqB == freq))
|
|
{
|
|
rig_debug(RIG_DEBUG_VERBOSE,
|
|
"%s: freq after band select already set to %"PRIfreq"\n", __func__, freq);
|
|
RETURNFUNC(RIG_OK); // we're done then!!
|
|
}
|
|
}
|
|
|
|
#endif
|
|
// after band select re-read things -- may not have to change anything
|
|
// reading both VFOs is really only needed for rigs with just one VFO stack
|
|
// but we read them all to ensure we cover both types
|
|
freq_t tmp_freqA = 0, tmp_freqB = 0;
|
|
rmode_t tmp_mode;
|
|
pbwidth_t tmp_width;
|
|
|
|
// we need to update some info that BS may have caused
|
|
CACHE_RESET;
|
|
|
|
if (vfo == RIG_VFO_A || vfo == RIG_VFO_MAIN)
|
|
{
|
|
rig_get_freq(rig, RIG_VFO_SUB, &tmp_freqA);
|
|
}
|
|
else
|
|
{
|
|
rig_get_freq(rig, RIG_VFO_MAIN, &tmp_freqB);
|
|
}
|
|
|
|
rig_get_mode(rig, RIG_VFO_MAIN, &tmp_mode, &tmp_width);
|
|
rig_get_mode(rig, RIG_VFO_SUB, &tmp_mode, &tmp_width);
|
|
|
|
if ((target_vfo == 0 && tmp_freqA == freq)
|
|
|| (target_vfo == 1 && tmp_freqB == freq))
|
|
{
|
|
rig_debug(RIG_DEBUG_VERBOSE,
|
|
"%s: freq after band select already set to %"PRIfreq"\n", __func__, freq);
|
|
RETURNFUNC(RIG_OK); // we're done then!!
|
|
}
|
|
|
|
// just drop through
|
|
}
|
|
|
|
if (RIG_MODEL_FT450 == caps->rig_model)
|
|
{
|
|
if (c == 'B')
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VS1;F%c%0*"PRIll";VS0;", c,
|
|
priv->width_frequency, (int64_t)freq);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "F%c%0*"PRIll";", c,
|
|
priv->width_frequency, (int64_t)freq);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "F%c%0*"PRIll";", c,
|
|
priv->width_frequency, (int64_t)freq);
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s:%d cmd_str = %s\n", __func__, __LINE__,
|
|
priv->cmd_str);
|
|
|
|
if (RIG_OK != (err = newcat_set_cmd(rig)))
|
|
{
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s:%d command err = %d\n", __func__, __LINE__,
|
|
err);
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: band changing? old=%d, new=%d\n", __func__,
|
|
newcat_band_index(freq), newcat_band_index(rig->state.current_freq));
|
|
|
|
if (RIG_MODEL_FT450 == caps->rig_model && priv->ret_data[2] != target_vfo)
|
|
{
|
|
/* revert current VFO */
|
|
rig_debug(RIG_DEBUG_TRACE, "%s:%d cmd_str = %s\n", __func__, __LINE__,
|
|
priv->ret_data);
|
|
|
|
if (RIG_OK != (err = newcat_set_cmd(rig)))
|
|
{
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s:%d command err = %d\n", __func__, __LINE__,
|
|
err);
|
|
RETURNFUNC(err);
|
|
}
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
/*
|
|
* rig_get_freq
|
|
*
|
|
* Return Freq for a given VFO
|
|
* RIG_TARGETABLE_FREQ
|
|
* Does not SET priv->current_vfo
|
|
*
|
|
*/
|
|
int newcat_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
|
|
{
|
|
char command[3];
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char c;
|
|
int err;
|
|
|
|
ENTERFUNC;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: passed vfo = %s\n", __func__, rig_strvfo(vfo));
|
|
|
|
if (!newcat_valid_command(rig, "FA"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (!newcat_valid_command(rig, "FB"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
switch (vfo)
|
|
{
|
|
case RIG_VFO_A:
|
|
case RIG_VFO_MAIN: // what about MAIN_A/MAIN_B?
|
|
c = 'A';
|
|
break;
|
|
|
|
case RIG_VFO_B:
|
|
case RIG_VFO_SUB: // what about SUB_A/SUB_B?
|
|
c = 'B';
|
|
break;
|
|
|
|
case RIG_VFO_MEM:
|
|
c = 'A';
|
|
break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_ERR, "%s: unsupported vfo=%s\n", __func__, rig_strvfo(vfo));
|
|
RETURNFUNC(-RIG_EINVAL); /* sorry, unsupported VFO */
|
|
}
|
|
|
|
/* Build the command string */
|
|
SNPRINTF(command, sizeof(command), "F%c", c);
|
|
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c", command, cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "cmd_str = %s\n", priv->cmd_str);
|
|
|
|
/* get freq */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/* convert the read frequency string into freq_t and store in *freq */
|
|
sscanf(priv->ret_data + 2, "%"SCNfreq, freq);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE,
|
|
"%s: freq = %"PRIfreq" Hz for vfo %s\n", __func__, *freq, rig_strvfo(vfo));
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
|
|
{
|
|
struct newcat_priv_data *priv;
|
|
int err;
|
|
rmode_t tmode;
|
|
pbwidth_t twidth;
|
|
split_t split_save = rig->state.cache.split;
|
|
|
|
priv = (struct newcat_priv_data *)rig->state.priv;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (newcat_60m_exception(rig,rig->state.cache.freqMainA)) RETURNFUNC(RIG_OK); // we don't set mode in this case
|
|
|
|
if (!newcat_valid_command(rig, "MD"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
// if vfo is current the same don't do anything
|
|
// we don't want to use cache in case the user is twiddling the rig
|
|
if (vfo == RIG_VFO_B || vfo == RIG_VFO_SUB)
|
|
{
|
|
rig_get_mode(rig, vfo, &tmode, &twidth);
|
|
|
|
if (mode == tmode && (twidth == width || twidth == RIG_PASSBAND_NOCHANGE))
|
|
{
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MD0x%c", cat_term);
|
|
|
|
priv->cmd_str[3] = newcat_modechar(mode);
|
|
|
|
if (priv->cmd_str[3] == '0')
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
|
|
/* FT9000 RIG_TARGETABLE_MODE (mode and width) */
|
|
/* FT2000 mode only */
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: generic mode = %s \n",
|
|
__func__, rig_strrmode(mode));
|
|
|
|
|
|
err = newcat_set_cmd(rig);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
if (vfo == RIG_VFO_A || vfo == RIG_VFO_MAIN)
|
|
rig->state.cache.modeMainA = mode;
|
|
else
|
|
rig->state.cache.modeMainB = mode;
|
|
|
|
if (RIG_PASSBAND_NOCHANGE == width) { RETURNFUNC(err); }
|
|
|
|
if (RIG_PASSBAND_NORMAL == width)
|
|
{
|
|
width = rig_passband_normal(rig, mode);
|
|
}
|
|
|
|
/* Set width after mode has been set */
|
|
err = newcat_set_rx_bandwidth(rig, vfo, mode, width);
|
|
|
|
// some rigs if you set mode on VFOB it will turn off split
|
|
// so if we started in split we query split and turn it back on if needed
|
|
if (split_save)
|
|
{
|
|
split_t split;
|
|
vfo_t tx_vfo;
|
|
err = rig_get_split_vfo(rig, RIG_VFO_A, &split, &tx_vfo);
|
|
|
|
// we'll just reset to split to what we want if we need to
|
|
if (!split)
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: turning split back on...buggy rig\n", __func__);
|
|
err = rig_set_split_vfo(rig, RIG_VFO_A, split_save, RIG_VFO_B);
|
|
}
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
int newcat_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char c;
|
|
int err;
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, "MD"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
/* Build the command string */
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MD%c%c", main_sub_vfo,
|
|
cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
/* Get MODE */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/*
|
|
* The current mode value is a digit '0' ... 'C'
|
|
* embedded at ret_data[3] in the read string.
|
|
*/
|
|
c = priv->ret_data[3];
|
|
|
|
/* default, unless set otherwise */
|
|
*width = RIG_PASSBAND_NORMAL;
|
|
|
|
*mode = newcat_rmode_width(rig, vfo, c, width);
|
|
|
|
if (*mode == '0')
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: *mode = '0'??\n", __func__);
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
if (RIG_PASSBAND_NORMAL == *width)
|
|
{
|
|
*width = rig_passband_normal(rig, *mode);
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: returning newcat_get_rx_bandwidth\n", __func__);
|
|
RETURNFUNC(newcat_get_rx_bandwidth(rig, vfo, *mode, width));
|
|
}
|
|
|
|
/*
|
|
* newcat_set_vfo
|
|
*
|
|
* set vfo and store requested vfo for later RIG_VFO_CURR
|
|
* requests.
|
|
*
|
|
*/
|
|
|
|
int newcat_set_vfo(RIG *rig, vfo_t vfo)
|
|
{
|
|
struct newcat_priv_data *priv;
|
|
struct rig_state *state;
|
|
char c;
|
|
int err, mem;
|
|
rmode_t vfo_mode;
|
|
char command[] = "VS";
|
|
|
|
priv = (struct newcat_priv_data *)rig->state.priv;
|
|
state = &rig->state;
|
|
priv->cache_start.tv_sec = 0; // invalidate the cache
|
|
|
|
|
|
ENTERFUNC;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: passed vfo = %s\n", __func__,
|
|
rig_strvfo(vfo));
|
|
|
|
// we can't change VFO while transmitting
|
|
if (rig->state.cache.ptt == RIG_PTT_ON) { RETURNFUNC(RIG_OK); }
|
|
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
err = newcat_set_vfo_from_alias(rig,
|
|
&vfo); /* passes RIG_VFO_MEM, RIG_VFO_A, RIG_VFO_B */
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
switch (vfo)
|
|
{
|
|
case RIG_VFO_A:
|
|
case RIG_VFO_B:
|
|
case RIG_VFO_MAIN:
|
|
case RIG_VFO_SUB:
|
|
if (vfo == RIG_VFO_B || vfo == RIG_VFO_SUB)
|
|
{
|
|
c = '1';
|
|
}
|
|
else
|
|
{
|
|
c = '0';
|
|
}
|
|
|
|
err = newcat_get_vfo_mode(rig, RIG_VFO_A, &vfo_mode);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (vfo_mode == RIG_VFO_MEM)
|
|
{
|
|
priv->current_mem = NC_MEM_CHANNEL_NONE;
|
|
state->current_vfo = RIG_VFO_A;
|
|
err = newcat_vfomem_toggle(rig);
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_VFO_MEM:
|
|
if (priv->current_mem == NC_MEM_CHANNEL_NONE)
|
|
{
|
|
/* Only works correctly for VFO A */
|
|
if (state->current_vfo != RIG_VFO_A && state->current_vfo != RIG_VFO_MAIN)
|
|
{
|
|
RETURNFUNC(-RIG_ENTARGET);
|
|
}
|
|
|
|
/* get current memory channel */
|
|
err = newcat_get_mem(rig, vfo, &mem);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/* turn on memory channel */
|
|
err = newcat_set_mem(rig, vfo, mem);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/* Set current_mem now */
|
|
priv->current_mem = mem;
|
|
}
|
|
|
|
/* Set current_vfo now */
|
|
state->current_vfo = vfo;
|
|
RETURNFUNC(RIG_OK);
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_ENIMPL); /* sorry, VFO not implemented */
|
|
}
|
|
|
|
/* Build the command string */
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c%c", command, c, cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "cmd_str = %s\n", priv->cmd_str);
|
|
|
|
err = newcat_set_cmd(rig);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
state->current_vfo = vfo; /* if set_vfo worked, set current_vfo */
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: rig->state.current_vfo = %s\n", __func__,
|
|
rig_strvfo(vfo));
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
// Either returns a valid RIG_VFO* or if < 0 an error code
|
|
static vfo_t newcat_set_vfo_if_needed(RIG *rig, vfo_t vfo)
|
|
{
|
|
vfo_t oldvfo = rig->state.current_vfo;
|
|
|
|
ENTERFUNC;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s, oldvfo=%s\n", __func__, rig_strvfo(vfo),
|
|
rig_strvfo(oldvfo));
|
|
|
|
if (oldvfo != vfo)
|
|
{
|
|
int ret;
|
|
ret = newcat_set_vfo(rig, vfo);
|
|
|
|
if (ret != RIG_OK)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: error setting vfo=%s\n", __func__,
|
|
rig_strvfo(vfo));
|
|
RETURNFUNC(ret);
|
|
}
|
|
}
|
|
|
|
RETURNFUNC(oldvfo);
|
|
}
|
|
|
|
/*
|
|
* rig_get_vfo
|
|
*
|
|
* get current RX vfo/mem and store requested vfo for
|
|
* later RIG_VFO_CURR requests plus pass the tested vfo/mem
|
|
* back to the frontend.
|
|
*
|
|
*/
|
|
|
|
int newcat_get_vfo(RIG *rig, vfo_t *vfo)
|
|
{
|
|
struct rig_state *state = &rig->state;
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
rmode_t vfo_mode;
|
|
char const *command = "VS";
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!vfo)
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
/* Build the command string */
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s;", command);
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
/* Get VFO */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/*
|
|
* The current VFO value is a digit ('0' or '1' ('A' or 'B'
|
|
* respectively)) embedded at ret_data[2] in the read string.
|
|
*/
|
|
switch (priv->ret_data[2])
|
|
{
|
|
case '0':
|
|
if (rig->state.vfo_list & RIG_VFO_MAIN) { *vfo = RIG_VFO_MAIN; }
|
|
else { *vfo = RIG_VFO_A; }
|
|
|
|
break;
|
|
|
|
case '1':
|
|
if (rig->state.vfo_list & RIG_VFO_SUB) { *vfo = RIG_VFO_SUB; }
|
|
else { *vfo = RIG_VFO_B; }
|
|
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EPROTO); /* sorry, wrong current VFO */
|
|
}
|
|
|
|
/* Check to see if RIG is in MEM mode */
|
|
err = newcat_get_vfo_mode(rig, RIG_VFO_A, &vfo_mode);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (vfo_mode == RIG_VFO_MEM)
|
|
{
|
|
*vfo = RIG_VFO_MEM;
|
|
}
|
|
|
|
state->current_vfo = *vfo; /* set now */
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: rig->state.current_vfo = %s\n", __func__,
|
|
rig_strvfo(state->current_vfo));
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char txon[] = "TX1;";
|
|
char txoff[] = "TX0;";
|
|
|
|
ENTERFUNC;
|
|
|
|
priv->cache_start.tv_sec = 0; // invalidate the cache
|
|
|
|
if (!newcat_valid_command(rig, "TX"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
switch (ptt)
|
|
{
|
|
case RIG_PTT_ON:
|
|
/* Build the command string */
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s", txon);
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
err = newcat_set_cmd(rig);
|
|
break;
|
|
|
|
case RIG_PTT_OFF:
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s", txoff);
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
err = newcat_set_cmd(rig);
|
|
|
|
// some rigs like the FT991 need time before doing anything else like set_freq
|
|
// We won't mess with CW mode -- no freq change expected hopefully
|
|
if (rig->state.current_mode != RIG_MODE_CW
|
|
&& rig->state.current_mode != RIG_MODE_CWR
|
|
&& rig->state.current_mode != RIG_MODE_CWN
|
|
)
|
|
{
|
|
hl_usleep(100 * 1000);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
|
|
int newcat_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char c;
|
|
int err;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, "TX"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c", "TX", cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
/* Get PTT */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
c = priv->ret_data[2];
|
|
|
|
switch (c)
|
|
{
|
|
case '0': /* FT-950 "TX OFF", Original Release Firmware */
|
|
*ptt = RIG_PTT_OFF;
|
|
break;
|
|
|
|
case '1' : /* Just because, what the CAT Manual Shows */
|
|
case '2' : /* FT-950 Radio: Mic, Dataport, CW "TX ON" */
|
|
case '3' : /* FT-950 CAT port: Radio in "TX ON" mode [Not what the CAT Manual Shows] */
|
|
*ptt = RIG_PTT_ON;
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_get_dcd(RIG *rig, vfo_t vfo, dcd_t *dcd)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_set_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t rptr_shift)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char c;
|
|
char command[] = "OS";
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
/* Main or SUB vfo */
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
switch (rptr_shift)
|
|
{
|
|
case RIG_RPT_SHIFT_NONE:
|
|
c = '0';
|
|
break;
|
|
|
|
case RIG_RPT_SHIFT_PLUS:
|
|
c = '1';
|
|
break;
|
|
|
|
case RIG_RPT_SHIFT_MINUS:
|
|
c = '2';
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c%c%c", command,
|
|
main_sub_vfo, c, cat_term);
|
|
RETURNFUNC(newcat_set_cmd(rig));
|
|
}
|
|
|
|
|
|
int newcat_get_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t *rptr_shift)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char c;
|
|
char command[] = "OS";
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
/* Set Main or SUB vfo */
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c%c", command, main_sub_vfo,
|
|
cat_term);
|
|
|
|
/* Get Rptr Shift */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
c = priv->ret_data[3];
|
|
|
|
switch (c)
|
|
{
|
|
case '0':
|
|
*rptr_shift = RIG_RPT_SHIFT_NONE;
|
|
break;
|
|
|
|
case '1':
|
|
*rptr_shift = RIG_RPT_SHIFT_PLUS;
|
|
break;
|
|
|
|
case '2':
|
|
*rptr_shift = RIG_RPT_SHIFT_MINUS;
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t offs)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char command[32];
|
|
freq_t freq = 0;
|
|
|
|
ENTERFUNC;
|
|
|
|
err = newcat_get_freq(rig, vfo, &freq); // Need to get freq to determine band
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (is_ft450)
|
|
{
|
|
strcpy(command, "EX050");
|
|
|
|
// Step size is 100 kHz
|
|
offs /= 100000;
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%03li%c", command, offs,
|
|
cat_term);
|
|
}
|
|
else if (is_ft2000)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
strcpy(command, "EX076");
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
strcpy(command, "EX077");
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
offs /= 1000;
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs,
|
|
cat_term);
|
|
}
|
|
else if (is_ft950)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
strcpy(command, "EX057");
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
strcpy(command, "EX058");
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
offs /= 1000;
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs,
|
|
cat_term);
|
|
}
|
|
else if (is_ft891)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
strcpy(command, "EX0904");
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
strcpy(command, "EX0905");
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
offs /= 1000;
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs,
|
|
cat_term);
|
|
}
|
|
else if (is_ft991)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
strcpy(command, "EX080");
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
strcpy(command, "EX081");
|
|
}
|
|
else if (freq >= 144000000 && freq <= 148000000)
|
|
{
|
|
strcpy(command, "EX082");
|
|
}
|
|
else if (freq >= 430000000 && freq <= 450000000)
|
|
{
|
|
strcpy(command, "EX083");
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m to 70cm bands
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
offs /= 1000;
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx1200)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
strcpy(command, "EX087");
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
strcpy(command, "EX088");
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
offs /= 1000;
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx3000dm)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
strcpy(command, "EX086");
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
strcpy(command, "EX087");
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
offs /= 1000;
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
strcpy(command, "EX081");
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
strcpy(command, "EX082");
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
offs /= 1000;
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
strcpy(command, "EX010315");
|
|
|
|
if (is_ftdx10) { strcpy(command, "EX010317"); }
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
strcpy(command, "EX010316");
|
|
|
|
if (is_ftdx10) { strcpy(command, "EX010318"); }
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
offs /= 1000;
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs,
|
|
cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
RETURNFUNC(newcat_set_cmd(rig));
|
|
}
|
|
|
|
|
|
int newcat_get_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t *offs)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
int ret_data_len;
|
|
char *retoffs;
|
|
freq_t freq = 0;
|
|
int step;
|
|
|
|
ENTERFUNC;
|
|
|
|
err = newcat_get_freq(rig, vfo, &freq); // Need to get freq to determine band
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (is_ft450)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX050%c", cat_term);
|
|
|
|
// Step size is 100 kHz
|
|
step = 100000;
|
|
}
|
|
else if (is_ft2000)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX076%c", cat_term);
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX077%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
*offs = 0;
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
step = 1000;
|
|
}
|
|
else if (is_ft950)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX057%c", cat_term);
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX058%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
*offs = 0;
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
step = 1000;
|
|
}
|
|
else if (is_ft891)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX0904%c", cat_term);
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX0905%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
*offs = 0;
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
step = 1000;
|
|
}
|
|
else if (is_ft991)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX080%c", cat_term);
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX081%c", cat_term);
|
|
}
|
|
else if (freq >= 144000000 && freq <= 148000000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX082%c", cat_term);
|
|
}
|
|
else if (freq >= 430000000 && freq <= 450000000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX083%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m to 70cm bands
|
|
*offs = 0;
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
step = 1000;
|
|
}
|
|
else if (is_ftdx1200)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX087%c", cat_term);
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX088%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
*offs = 0;
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
step = 1000;
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx3000dm)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX086%c", cat_term);
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX087%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
*offs = 0;
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
step = 1000;
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX081%c", cat_term);
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX082%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
*offs = 0;
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
step = 1000;
|
|
}
|
|
else if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
if (freq >= 28000000 && freq <= 29700000)
|
|
{
|
|
char *cmd = "EX010315%c";
|
|
|
|
if (is_ftdx10) { cmd = "EX010317%c"; }
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), cmd, cat_term);
|
|
}
|
|
else if (freq >= 50000000 && freq <= 54000000)
|
|
{
|
|
char *cmd = "EX010316%c";
|
|
|
|
if (is_ftdx10) { cmd = "EX010318%c"; }
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), cmd, cat_term);
|
|
}
|
|
else
|
|
{
|
|
// only valid on 10m and 6m bands
|
|
*offs = 0;
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
// Step size is 1 kHz
|
|
step = 1000;
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
err = newcat_get_cmd(rig);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
ret_data_len = strlen(priv->ret_data);
|
|
|
|
/* skip command */
|
|
retoffs = priv->ret_data + strlen(priv->cmd_str) - 1;
|
|
/* chop term */
|
|
priv->ret_data[ret_data_len - 1] = '\0';
|
|
|
|
*offs = atol(retoffs) * step;
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_set_split_mode(RIG *rig, vfo_t vfo, rmode_t tx_mode,
|
|
pbwidth_t tx_width)
|
|
{
|
|
ENTERFUNC;
|
|
rmode_t tmp_mode;
|
|
pbwidth_t tmp_width;
|
|
int err;
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s, tx_mode=%s, tx_width=%d\n", __func__, rig_strvfo(vfo), rig_strrmode(tx_mode), (int)tx_width);
|
|
err = newcat_get_mode(rig, RIG_VFO_B, &tmp_mode, &tmp_width);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (tmp_mode == tx_mode && (tmp_width == tx_width
|
|
|| tmp_width == RIG_PASSBAND_NOCHANGE))
|
|
{
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
err = rig_set_mode(rig, vfo, tx_mode, tx_width);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
if (vfo == RIG_VFO_A || vfo == RIG_VFO_MAIN)
|
|
rig->state.cache.modeMainA = tx_mode;
|
|
else
|
|
rig->state.cache.modeMainB = tx_mode;
|
|
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_get_split_mode(RIG *rig, vfo_t vfo, rmode_t *tx_mode,
|
|
pbwidth_t *tx_width)
|
|
{
|
|
int err;
|
|
|
|
ENTERFUNC;
|
|
|
|
err = newcat_get_mode(rig, RIG_VFO_B, tx_mode, tx_width);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo)
|
|
{
|
|
int err;
|
|
vfo_t rx_vfo = RIG_VFO_NONE;
|
|
|
|
//ENTERFUNC;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: entered, rxvfo=%s, txvfo=%s, split=%d\n",
|
|
__func__, rig_strvfo(vfo), rig_strvfo(tx_vfo), split);
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (is_ft991)
|
|
{
|
|
vfo = RIG_VFO_A;
|
|
tx_vfo = RIG_SPLIT_ON == split ? RIG_VFO_B : RIG_VFO_A;
|
|
}
|
|
else if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
vfo = RIG_VFO_MAIN;
|
|
tx_vfo = RIG_SPLIT_ON == split ? RIG_VFO_SUB : RIG_VFO_MAIN;
|
|
}
|
|
else
|
|
{
|
|
err = newcat_get_vfo(rig, &rx_vfo); /* sync to rig current vfo */
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
}
|
|
|
|
switch (split)
|
|
{
|
|
case RIG_SPLIT_OFF:
|
|
err = newcat_set_tx_vfo(rig, vfo);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rx_vfo != vfo && newcat_valid_command(rig, "VS"))
|
|
{
|
|
err = rig_set_vfo(rig, vfo);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_SPLIT_ON:
|
|
err = newcat_set_tx_vfo(rig, tx_vfo);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rx_vfo != vfo)
|
|
{
|
|
err = rig_set_vfo(rig, vfo);
|
|
|
|
if (err != RIG_OK && err != -RIG_ENAVAIL)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split, vfo_t *tx_vfo)
|
|
{
|
|
int err;
|
|
|
|
ENTERFUNC;
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
err = newcat_get_tx_vfo(rig, tx_vfo);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
// we assume split is always on VFO_B
|
|
if (*tx_vfo == RIG_VFO_B || *tx_vfo == RIG_VFO_SUB)
|
|
{
|
|
*split = RIG_SPLIT_ON;
|
|
}
|
|
else
|
|
{
|
|
*split = RIG_SPLIT_OFF;
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "SPLIT = %d, vfo = %s, TX_vfo = %s\n", *split,
|
|
rig_strvfo(vfo),
|
|
rig_strvfo(*tx_vfo));
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
int newcat_set_rit(RIG *rig, vfo_t vfo, shortfreq_t rit)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
vfo_t oldvfo;
|
|
int ret;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, "RT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
oldvfo = newcat_set_vfo_if_needed(rig, vfo);
|
|
|
|
if (oldvfo < 0) { RETURNFUNC(oldvfo); }
|
|
|
|
if (rit > rig->caps->max_rit)
|
|
{
|
|
rit = rig->caps->max_rit; /* + */
|
|
}
|
|
else if (labs(rit) > rig->caps->max_rit)
|
|
{
|
|
rit = - rig->caps->max_rit; /* - */
|
|
}
|
|
|
|
if (rit == 0) // don't turn it off just because it is zero
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RC%c",
|
|
cat_term);
|
|
}
|
|
else if (rit < 0)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RC%cRD%04ld%c", cat_term,
|
|
labs(rit), cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RC%cRU%04ld%c", cat_term,
|
|
labs(rit), cat_term);
|
|
}
|
|
|
|
ret = newcat_set_cmd(rig);
|
|
|
|
oldvfo = newcat_set_vfo_if_needed(rig, oldvfo);
|
|
|
|
if (oldvfo < 0) { RETURNFUNC(oldvfo); }
|
|
|
|
RETURNFUNC(ret);
|
|
}
|
|
|
|
|
|
int newcat_get_rit(RIG *rig, vfo_t vfo, shortfreq_t *rit)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char *retval;
|
|
int err;
|
|
int offset = 0;
|
|
char *cmd = "IF";
|
|
|
|
ENTERFUNC;
|
|
|
|
if (vfo == RIG_VFO_B || vfo == RIG_VFO_SUB)
|
|
{
|
|
// OI always returns VFOB and IF always VFOA
|
|
cmd = "OI";
|
|
}
|
|
|
|
if (!newcat_valid_command(rig, cmd))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
*rit = 0;
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c", cmd, cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
/* Get RIT */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
// e.g. FT450 has 27 byte IF response, FT991 has 28 byte if response (one more byte for P2 VFO A Freq)
|
|
// so we now check to ensure we know the length of the response
|
|
|
|
switch (strlen(priv->ret_data))
|
|
{
|
|
case 27: offset = 13; break;
|
|
|
|
case 28: offset = 14; break;
|
|
|
|
default: offset = 0;
|
|
}
|
|
|
|
if (offset == 0)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
"%s: incorrect length of IF response, expected 27 or 28, got %du", __func__,
|
|
(int)strlen(priv->ret_data));
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
retval = priv->ret_data + offset;
|
|
retval[5] = '\0';
|
|
|
|
// return the current offset even if turned off
|
|
*rit = (shortfreq_t) atoi(retval);
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_xit(RIG *rig, vfo_t vfo, shortfreq_t xit)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
vfo_t oldvfo;
|
|
int ret;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, "XT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
oldvfo = newcat_set_vfo_if_needed(rig, vfo);
|
|
|
|
if (oldvfo < 0) { RETURNFUNC(oldvfo); }
|
|
|
|
if (xit > rig->caps->max_xit)
|
|
{
|
|
xit = rig->caps->max_xit; /* + */
|
|
}
|
|
else if (labs(xit) > rig->caps->max_xit)
|
|
{
|
|
xit = - rig->caps->max_xit; /* - */
|
|
}
|
|
|
|
if (xit == 0)
|
|
{
|
|
// don't turn it off just because the offset is zero
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RC%c",
|
|
cat_term);
|
|
}
|
|
else if (xit < 0)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RC%cRD%04ld%c", cat_term,
|
|
labs(xit), cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RC%cRU%04ld%c", cat_term,
|
|
labs(xit), cat_term);
|
|
}
|
|
|
|
ret = newcat_set_cmd(rig);
|
|
|
|
oldvfo = newcat_set_vfo_if_needed(rig, vfo);
|
|
|
|
if (oldvfo < 0) { RETURNFUNC(oldvfo); }
|
|
|
|
RETURNFUNC(ret);
|
|
}
|
|
|
|
|
|
int newcat_get_xit(RIG *rig, vfo_t vfo, shortfreq_t *xit)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char *retval;
|
|
int err;
|
|
int offset = 0;
|
|
char *cmd = "IF";
|
|
|
|
ENTERFUNC;
|
|
|
|
if (vfo == RIG_VFO_B || vfo == RIG_VFO_SUB)
|
|
{
|
|
// OI always returns VFOB and IF always VFOA
|
|
cmd = "OI";
|
|
}
|
|
|
|
if (!newcat_valid_command(rig, cmd))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
*xit = 0;
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c", cmd, cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
/* Get XIT */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
// e.g. FT450 has 27 byte IF response, FT991 has 28 byte if response (one more byte for P2 VFO A Freq)
|
|
// so we now check to ensure we know the length of the response
|
|
|
|
switch (strlen(priv->ret_data))
|
|
{
|
|
case 27: offset = 13; break;
|
|
|
|
case 28: offset = 14; break;
|
|
|
|
default: offset = 0;
|
|
}
|
|
|
|
if (offset == 0)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
"%s: incorrect length of IF response, expected 27 or 28, got %du", __func__,
|
|
(int)strlen(priv->ret_data));
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
retval = priv->ret_data + offset;
|
|
retval[5] = '\0';
|
|
|
|
// return the offset even when turned off
|
|
*xit = (shortfreq_t) atoi(retval);
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_ts(RIG *rig, vfo_t vfo, shortfreq_t ts)
|
|
{
|
|
int err, i;
|
|
pbwidth_t width;
|
|
rmode_t mode;
|
|
ncboolean ts_match;
|
|
|
|
ENTERFUNC;
|
|
|
|
err = newcat_get_mode(rig, vfo, &mode, &width);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/* assume 2 tuning steps per mode */
|
|
for (i = 0, ts_match = FALSE; i < HAMLIB_TSLSTSIZ
|
|
&& rig->caps->tuning_steps[i].ts; i++)
|
|
if (rig->caps->tuning_steps[i].modes & mode)
|
|
{
|
|
if (ts <= rig->caps->tuning_steps[i].ts)
|
|
{
|
|
err = newcat_set_faststep(rig, FALSE);
|
|
}
|
|
else
|
|
{
|
|
err = newcat_set_faststep(rig, TRUE);
|
|
}
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
ts_match = TRUE;
|
|
break;
|
|
} /* if mode */
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "ts_match = %d, i = %d, ts = %d\n", ts_match, i,
|
|
(int)ts);
|
|
|
|
if (ts_match)
|
|
{
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
}
|
|
|
|
|
|
int newcat_get_ts(RIG *rig, vfo_t vfo, shortfreq_t *ts)
|
|
{
|
|
pbwidth_t width;
|
|
rmode_t mode;
|
|
int err, i;
|
|
ncboolean ts_match;
|
|
ncboolean fast_step = FALSE;
|
|
|
|
|
|
ENTERFUNC;
|
|
|
|
err = newcat_get_mode(rig, vfo, &mode, &width);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
err = newcat_get_faststep(rig, &fast_step);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/* assume 2 tuning steps per mode */
|
|
for (i = 0, ts_match = FALSE; i < HAMLIB_TSLSTSIZ
|
|
&& rig->caps->tuning_steps[i].ts; i++)
|
|
if (rig->caps->tuning_steps[i].modes & mode)
|
|
{
|
|
if (fast_step == FALSE)
|
|
{
|
|
*ts = rig->caps->tuning_steps[i].ts;
|
|
}
|
|
else
|
|
{
|
|
*ts = rig->caps->tuning_steps[i + 1].ts;
|
|
}
|
|
|
|
ts_match = TRUE;
|
|
break;
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "ts_match = %d, i = %d, i+1 = %d, *ts = %d\n",
|
|
ts_match, i, i + 1, (int)*ts);
|
|
|
|
if (ts_match)
|
|
{
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
}
|
|
|
|
|
|
int newcat_set_dcs_code(RIG *rig, vfo_t vfo, tone_t code)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_get_dcs_code(RIG *rig, vfo_t vfo, tone_t *code)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_set_tone(RIG *rig, vfo_t vfo, tone_t tone)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_get_tone(RIG *rig, vfo_t vfo, tone_t *tone)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_set_ctcss_tone(RIG *rig, vfo_t vfo, tone_t tone)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
int i;
|
|
ncboolean tone_match;
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, "CN"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (!newcat_valid_command(rig, "CT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
for (i = 0, tone_match = FALSE; rig->caps->ctcss_list[i] != 0; i++)
|
|
if (tone == rig->caps->ctcss_list[i])
|
|
{
|
|
tone_match = TRUE;
|
|
break;
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: tone = %u, tone_match = %d, i = %d", __func__,
|
|
tone, tone_match, i);
|
|
|
|
if (tone_match == FALSE && tone != 0)
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (tone == 0) /* turn off ctcss */
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT%c0%c", main_sub_vfo,
|
|
cat_term);
|
|
}
|
|
else
|
|
{
|
|
if (is_ft891 || is_ft991 || is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN%c0%03d%cCT%c2%c",
|
|
main_sub_vfo, i, cat_term, main_sub_vfo, cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN%c%02d%cCT%c2%c",
|
|
main_sub_vfo, i, cat_term, main_sub_vfo, cat_term);
|
|
}
|
|
}
|
|
|
|
RETURNFUNC(newcat_set_cmd(rig));
|
|
}
|
|
|
|
|
|
int newcat_get_ctcss_tone(RIG *rig, vfo_t vfo, tone_t *tone)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
int t;
|
|
int ret_data_len;
|
|
char *retlvl;
|
|
char cmd[] = "CN";
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, cmd))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
if (is_ft891 || is_ft991 || is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c0%c", cmd, main_sub_vfo,
|
|
cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c%c", cmd, main_sub_vfo,
|
|
cat_term);
|
|
}
|
|
|
|
/* Get CTCSS TONE */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
ret_data_len = strlen(priv->ret_data);
|
|
|
|
/* skip command */
|
|
retlvl = priv->ret_data + strlen(priv->cmd_str) - 1;
|
|
/* chop term */
|
|
priv->ret_data[ret_data_len - 1] = '\0';
|
|
|
|
t = atoi(retlvl); /* tone index */
|
|
|
|
if (t < 0 || t > 49)
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
*tone = rig->caps->ctcss_list[t];
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_dcs_sql(RIG *rig, vfo_t vfo, tone_t code)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_get_dcs_sql(RIG *rig, vfo_t vfo, tone_t *code)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_set_tone_sql(RIG *rig, vfo_t vfo, tone_t tone)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_get_tone_sql(RIG *rig, vfo_t vfo, tone_t *tone)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_set_ctcss_sql(RIG *rig, vfo_t vfo, tone_t tone)
|
|
{
|
|
int err;
|
|
|
|
ENTERFUNC;
|
|
|
|
err = newcat_set_ctcss_tone(rig, vfo, tone);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/* Change to sql */
|
|
if (tone)
|
|
{
|
|
err = newcat_set_func(rig, vfo, RIG_FUNC_TSQL, TRUE);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_get_ctcss_sql(RIG *rig, vfo_t vfo, tone_t *tone)
|
|
{
|
|
int err;
|
|
|
|
ENTERFUNC;
|
|
|
|
err = newcat_get_ctcss_tone(rig, vfo, tone);
|
|
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
|
|
int newcat_power2mW(RIG *rig, unsigned int *mwpower, float power, freq_t freq,
|
|
rmode_t mode)
|
|
{
|
|
int rig_id;
|
|
|
|
ENTERFUNC;
|
|
|
|
rig_id = newcat_get_rigid(rig);
|
|
|
|
switch (rig_id)
|
|
{
|
|
case NC_RIGID_FT450:
|
|
/* 100 Watts */
|
|
*mwpower = power * 100000;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FT450 - rig_id = %d, *mwpower = %u\n", rig_id,
|
|
*mwpower);
|
|
break;
|
|
|
|
case NC_RIGID_FT950:
|
|
/* 100 Watts */
|
|
*mwpower = power * 100000; /* 0..100 Linear scale */
|
|
rig_debug(RIG_DEBUG_TRACE,
|
|
"case FT950 - rig_id = %d, power = %f, *mwpower = %u\n", rig_id, power,
|
|
*mwpower);
|
|
break;
|
|
|
|
case NC_RIGID_FT2000:
|
|
/* 100 Watts */
|
|
*mwpower = power * 100000;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FT2000 - rig_id = %d, *mwpower = %u\n", rig_id,
|
|
*mwpower);
|
|
break;
|
|
|
|
case NC_RIGID_FT2000D:
|
|
/* 200 Watts */
|
|
*mwpower = power * 200000;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FT2000D - rig_id = %d, *mwpower = %u\n",
|
|
rig_id, *mwpower);
|
|
break;
|
|
|
|
case NC_RIGID_FTDX5000:
|
|
/* 200 Watts */
|
|
*mwpower = power * 200000;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FTDX5000 - rig_id = %d, *mwpower = %u\n",
|
|
rig_id, *mwpower);
|
|
break;
|
|
|
|
case NC_RIGID_FTDX9000D:
|
|
/* 200 Watts */
|
|
*mwpower = power * 200000;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FTDX9000D - rig_id = %d, *mwpower = %u\n",
|
|
rig_id, *mwpower);
|
|
break;
|
|
|
|
case NC_RIGID_FTDX9000Contest:
|
|
/* 200 Watts */
|
|
*mwpower = power * 200000;
|
|
rig_debug(RIG_DEBUG_TRACE,
|
|
"case FTDX9000Contest - rig_id = %d, *mwpower = %u\n", rig_id, *mwpower);
|
|
break;
|
|
|
|
case NC_RIGID_FTDX9000MP:
|
|
/* 400 Watts */
|
|
*mwpower = power * 400000;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FTDX9000MP - rig_id = %d, *mwpower = %u\n",
|
|
rig_id, *mwpower);
|
|
break;
|
|
|
|
case NC_RIGID_FTDX1200:
|
|
/* 100 Watts */
|
|
*mwpower = power * 100000;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FTDX1200 - rig_id = %d, *mwpower = %d\n",
|
|
rig_id,
|
|
*mwpower);
|
|
break;
|
|
|
|
default:
|
|
/* 100 Watts */
|
|
*mwpower = power * 100000;
|
|
rig_debug(RIG_DEBUG_TRACE, "default - rig_id = %d, *mwpower = %u\n", rig_id,
|
|
*mwpower);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_mW2power(RIG *rig, float *power, unsigned int mwpower, freq_t freq,
|
|
rmode_t mode)
|
|
{
|
|
int rig_id;
|
|
|
|
ENTERFUNC;
|
|
|
|
rig_id = newcat_get_rigid(rig);
|
|
|
|
switch (rig_id)
|
|
{
|
|
case NC_RIGID_FT450:
|
|
/* 100 Watts */
|
|
*power = mwpower / 100000.0;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FT450 - rig_id = %d, *power = %f\n", rig_id,
|
|
*power);
|
|
break;
|
|
|
|
case NC_RIGID_FT950:
|
|
/* 100 Watts */
|
|
*power = mwpower / 100000.0; /* 0..100 Linear scale */
|
|
rig_debug(RIG_DEBUG_TRACE,
|
|
"case FT950 - rig_id = %d, mwpower = %u, *power = %f\n", rig_id, mwpower,
|
|
*power);
|
|
break;
|
|
|
|
case NC_RIGID_FT2000:
|
|
/* 100 Watts */
|
|
*power = mwpower / 100000.0;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FT2000 - rig_id = %d, *power = %f\n", rig_id,
|
|
*power);
|
|
break;
|
|
|
|
case NC_RIGID_FT2000D:
|
|
/* 200 Watts */
|
|
*power = mwpower / 200000.0;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FT2000D - rig_id = %d, *power = %f\n", rig_id,
|
|
*power);
|
|
break;
|
|
|
|
case NC_RIGID_FTDX5000:
|
|
/* 200 Watts */
|
|
*power = mwpower / 200000.0;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FTDX5000 - rig_id = %d, *power = %f\n", rig_id,
|
|
*power);
|
|
break;
|
|
|
|
case NC_RIGID_FTDX9000D:
|
|
/* 200 Watts */
|
|
*power = mwpower / 200000.0;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FTDX9000D - rig_id = %d, *power = %f\n",
|
|
rig_id, *power);
|
|
break;
|
|
|
|
case NC_RIGID_FTDX9000Contest:
|
|
/* 200 Watts */
|
|
*power = mwpower / 200000.0;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FTDX9000Contest - rig_id = %d, *power = %f\n",
|
|
rig_id, *power);
|
|
break;
|
|
|
|
case NC_RIGID_FTDX9000MP:
|
|
/* 400 Watts */
|
|
*power = mwpower / 400000.0;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FTDX9000MP - rig_id = %d, *power = %f\n",
|
|
rig_id, *power);
|
|
break;
|
|
|
|
case NC_RIGID_FTDX1200:
|
|
/* 100 Watts */
|
|
*power = mwpower / 100000.0;
|
|
rig_debug(RIG_DEBUG_TRACE, "case FTDX1200 - rig_id = %d, *power = %f\n", rig_id,
|
|
*power);
|
|
break;
|
|
|
|
default:
|
|
/* 100 Watts */
|
|
*power = mwpower / 100000.0;
|
|
rig_debug(RIG_DEBUG_TRACE, "default - rig_id = %d, *power = %f\n", rig_id,
|
|
*power);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_powerstat(RIG *rig, powerstat_t status)
|
|
{
|
|
struct rig_state *state = &rig->state;
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int retval;
|
|
int i = 0;
|
|
int retry_save;
|
|
char ps;
|
|
|
|
ENTERFUNC;
|
|
|
|
#if 0 // all Yaeus rigs have PS and calling this here interferes with power on
|
|
|
|
if (!newcat_valid_command(rig, "PS"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
#endif
|
|
|
|
switch (status)
|
|
{
|
|
case RIG_POWER_ON:
|
|
ps = '1';
|
|
// when powering on need a dummy byte to wake it up
|
|
// then sleep from 1 to 2 seconds so we'll do 1.5 secs
|
|
write_block(&state->rigport, (unsigned char *) "PS1;", 4);
|
|
hl_usleep(1200000);
|
|
break;
|
|
|
|
case RIG_POWER_OFF:
|
|
case RIG_POWER_STANDBY:
|
|
ps = '0';
|
|
write_block(&state->rigport, (unsigned char *) "PS0;", 4);
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PS%c%c", ps, cat_term);
|
|
|
|
retval = write_block(&state->rigport, (unsigned char *) priv->cmd_str,
|
|
strlen(priv->cmd_str));
|
|
|
|
retry_save = rig->state.rigport.retry;
|
|
rig->state.rigport.retry = 0;
|
|
|
|
if (status == RIG_POWER_ON) // wait for wakeup only
|
|
{
|
|
for (i = 0; i < 8; ++i) // up to ~10 seconds including the timeouts
|
|
{
|
|
freq_t freq;
|
|
hl_usleep(1000000);
|
|
rig_flush(&state->rigport);
|
|
retval = rig_get_freq(rig, RIG_VFO_A, &freq);
|
|
|
|
if (retval == RIG_OK)
|
|
{
|
|
rig->state.rigport.retry = retry_save;
|
|
RETURNFUNC(retval);
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: Wait #%d for power up\n", __func__, i + 1);
|
|
retval = write_block(&state->rigport, (unsigned char *) priv->cmd_str,
|
|
strlen(priv->cmd_str));
|
|
|
|
if (retval != RIG_OK) { RETURNFUNC(retval); }
|
|
}
|
|
}
|
|
|
|
rig->state.rigport.retry = retry_save;
|
|
|
|
if (i == 9)
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: timeout waiting for powerup, try %d\n",
|
|
__func__,
|
|
i + 1);
|
|
retval = -RIG_ETIMEOUT;
|
|
}
|
|
|
|
RETURNFUNC(retval);
|
|
}
|
|
|
|
|
|
/*
|
|
* This functions returns an error if the rig is off, dah
|
|
*/
|
|
int newcat_get_powerstat(RIG *rig, powerstat_t *status)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char ps;
|
|
char command[] = "PS";
|
|
|
|
ENTERFUNC;
|
|
|
|
*status = RIG_POWER_OFF;
|
|
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c", command, cat_term);
|
|
|
|
/* Get Power status */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
ps = priv->ret_data[2];
|
|
|
|
switch (ps)
|
|
{
|
|
case '1':
|
|
*status = RIG_POWER_ON;
|
|
break;
|
|
|
|
case '0':
|
|
*status = RIG_POWER_OFF;
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_reset(RIG *rig, reset_t reset)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_set_ant(RIG *rig, vfo_t vfo, ant_t ant, value_t option)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char which_ant;
|
|
char command[] = "AN";
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
/* Main or SUB vfo */
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if ((rig->caps->targetable_vfo & RIG_TARGETABLE_ANT))
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
switch (ant)
|
|
{
|
|
case RIG_ANT_1:
|
|
which_ant = '1';
|
|
break;
|
|
|
|
case RIG_ANT_2:
|
|
which_ant = '2';
|
|
break;
|
|
|
|
case RIG_ANT_3:
|
|
if (newcat_is_rig(rig, RIG_MODEL_FT950))
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
if (newcat_is_rig(rig, RIG_MODEL_FTDX1200))
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
which_ant = '3';
|
|
break;
|
|
|
|
case RIG_ANT_4:
|
|
if (newcat_is_rig(rig, RIG_MODEL_FT950))
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
if (newcat_is_rig(rig, RIG_MODEL_FTDX1200))
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
which_ant = '4';
|
|
break;
|
|
|
|
case RIG_ANT_5:
|
|
if (newcat_is_rig(rig, RIG_MODEL_FT950))
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
if (newcat_is_rig(rig, RIG_MODEL_FTDX1200))
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
/* RX only, on FT-2000/FT-5000/FT-9000 */
|
|
which_ant = '5';
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c%c%c", command,
|
|
main_sub_vfo, which_ant, cat_term);
|
|
RETURNFUNC(newcat_set_cmd(rig));
|
|
}
|
|
|
|
|
|
int newcat_get_ant(RIG *rig, vfo_t vfo, ant_t dummy, value_t *option,
|
|
ant_t *ant_curr, ant_t *ant_tx, ant_t *ant_rx)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char c;
|
|
char command[] = "AN";
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
/* Set Main or SUB vfo */
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if ((rig->caps->targetable_vfo & RIG_TARGETABLE_MODE) && !is_ft2000)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c%c", command, main_sub_vfo,
|
|
cat_term);
|
|
|
|
/* Get ANT */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
c = priv->ret_data[3];
|
|
|
|
switch (c)
|
|
{
|
|
case '1':
|
|
*ant_curr = RIG_ANT_1;
|
|
break;
|
|
|
|
case '2' :
|
|
*ant_curr = RIG_ANT_2;
|
|
break;
|
|
|
|
case '3' :
|
|
*ant_curr = RIG_ANT_3;
|
|
break;
|
|
|
|
case '4' :
|
|
*ant_curr = RIG_ANT_4;
|
|
break;
|
|
|
|
case '5' :
|
|
*ant_curr = RIG_ANT_5;
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
*ant_tx = * ant_rx = *ant_curr;
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
static int band2rig(hamlib_band_t band)
|
|
{
|
|
int retval = 0;
|
|
|
|
switch (band)
|
|
{
|
|
case RIG_BAND_160M: retval = 0; break;
|
|
|
|
case RIG_BAND_80M: retval = 1; break;
|
|
|
|
case RIG_BAND_60M: retval = 2; break;
|
|
|
|
case RIG_BAND_40M: retval = 3; break;
|
|
|
|
case RIG_BAND_30M: retval = 4; break;
|
|
|
|
case RIG_BAND_20M: retval = 5; break;
|
|
|
|
case RIG_BAND_17M: retval = 6; break;
|
|
|
|
case RIG_BAND_15M: retval = 7; break;
|
|
|
|
case RIG_BAND_12M: retval = 8; break;
|
|
|
|
case RIG_BAND_10M: retval = 9; break;
|
|
|
|
case RIG_BAND_6M: retval = 10; break;
|
|
|
|
case RIG_BAND_GEN: retval = 11; break;
|
|
|
|
case RIG_BAND_MW: retval = 12; break;
|
|
|
|
case RIG_BAND_AIR: retval = 14; break;
|
|
|
|
case RIG_BAND_144MHZ: retval = 15; break;
|
|
|
|
case RIG_BAND_430MHZ: retval = 16; break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_ERR, "%s: unknown band index=%d\n", __func__, band);
|
|
retval = -RIG_EINVAL;
|
|
break;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
int newcat_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
|
|
{
|
|
struct rig_state *state = &rig->state;
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
int i;
|
|
int scale;
|
|
int fpf;
|
|
char main_sub_vfo = '0';
|
|
char *format;
|
|
|
|
ENTERFUNC;
|
|
|
|
/* Set Main or SUB vfo */
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_LEVEL)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
switch (level)
|
|
{
|
|
case RIG_LEVEL_RFPOWER:
|
|
if (!newcat_valid_command(rig, "PC"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft950 || is_ftdx1200 || is_ftdx3000 || is_ft891 || is_ft991
|
|
|| is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
scale = 100.;
|
|
}
|
|
else if (is_ft450 && newcat_get_rigid(rig) == NC_RIGID_FT450D)
|
|
{
|
|
scale = 100.;
|
|
}
|
|
else if (is_ftdx3000dm)
|
|
{
|
|
scale = 50;
|
|
}
|
|
else
|
|
{
|
|
scale = 255.;
|
|
}
|
|
|
|
fpf = newcat_scale_float(scale, val.f);
|
|
|
|
if (is_ft950 || is_ft891 || is_ft991 || is_ftdx3000 || is_ftdx3000dm
|
|
|| is_ftdx101d
|
|
|| is_ftdx101mp || is_ftdx10)
|
|
{
|
|
// Minimum is 5 watts on these rigs
|
|
if (fpf < 5)
|
|
{
|
|
fpf = 5;
|
|
}
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PC%03d%c", fpf, cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_AF:
|
|
if (!newcat_valid_command(rig, "AG"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (val.f > 1.0) { RETURNFUNC(-RIG_EINVAL); }
|
|
|
|
fpf = newcat_scale_float(255, val.f);
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "AG%c%03d%c", main_sub_vfo, fpf,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_AGC:
|
|
if (!newcat_valid_command(rig, "GT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
switch (val.i)
|
|
{
|
|
case RIG_AGC_OFF:
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "GT00;");
|
|
break;
|
|
|
|
case RIG_AGC_FAST:
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "GT01;");
|
|
break;
|
|
|
|
case RIG_AGC_MEDIUM:
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "GT02;");
|
|
break;
|
|
|
|
case RIG_AGC_SLOW:
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "GT03;");
|
|
break;
|
|
|
|
case RIG_AGC_AUTO:
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "GT04;");
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_IF:
|
|
{
|
|
pbwidth_t width;
|
|
rmode_t mode = 0;
|
|
|
|
if (!newcat_valid_command(rig, "IS"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
newcat_get_mode(rig, vfo, &mode, &width);
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: LEVEL_IF val.i=%d\n", __func__, val.i);
|
|
|
|
if (abs(val.i) > rig->caps->max_ifshift)
|
|
{
|
|
if (val.i > 0)
|
|
{
|
|
val.i = rig->caps->max_ifshift;
|
|
}
|
|
else
|
|
{
|
|
val.i = rig->caps->max_ifshift * -1;
|
|
}
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "IS%c0%+.4d%c", main_sub_vfo,
|
|
val.i, cat_term);
|
|
}
|
|
else if (is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "IS0%d%+.4d%c",
|
|
val.i == 0 ? 0 : 1,
|
|
val.i, cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "IS%c%+.4d%c", main_sub_vfo,
|
|
val.i, cat_term);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE && !is_ft2000)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
// Some Yaesu rigs reject this command in AM/FM modes
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
if (mode & RIG_MODE_AM || mode & RIG_MODE_FM || mode & RIG_MODE_AMN
|
|
|| mode & RIG_MODE_FMN)
|
|
{
|
|
priv->question_mark_response_means_rejected = 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RIG_LEVEL_CWPITCH:
|
|
{
|
|
int kp;
|
|
|
|
if (!newcat_valid_command(rig, "KP"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (val.i < 300)
|
|
{
|
|
i = 300;
|
|
}
|
|
else if (val.i > 1050)
|
|
{
|
|
i = 1050;
|
|
}
|
|
else
|
|
{
|
|
i = val.i;
|
|
}
|
|
|
|
if (is_ft950 || is_ft2000)
|
|
{
|
|
kp = (i - 300) / 50;
|
|
}
|
|
else
|
|
{
|
|
// Most Yaesu rigs seem to use range of 0-75 to represent pitch of 300..1050 Hz in 10 Hz steps
|
|
kp = (i - 300) / 10;
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "KP%02d%c", kp, cat_term);
|
|
break;
|
|
}
|
|
|
|
case RIG_LEVEL_KEYSPD:
|
|
if (!newcat_valid_command(rig, "KS"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "KS%03d%c", val.i, cat_term);
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_MICGAIN:
|
|
{
|
|
pbwidth_t width;
|
|
rmode_t mode = 0;
|
|
|
|
if (!newcat_valid_command(rig, "MG"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
newcat_get_mode(rig, vfo, &mode, &width);
|
|
}
|
|
|
|
if (val.f > 1.0) { RETURNFUNC(-RIG_EINVAL); }
|
|
|
|
if (is_ftdx1200 || is_ftdx3000 || is_ftdx3000dm || is_ft891 || is_ft991
|
|
|| is_ftdx101d
|
|
|| is_ftdx101mp
|
|
|| is_ftdx10)
|
|
{
|
|
fpf = newcat_scale_float(100, val.f);
|
|
}
|
|
else
|
|
{
|
|
fpf = newcat_scale_float(255, val.f);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MG%03d%c", fpf, cat_term);
|
|
|
|
// Some Yaesu rigs reject this command in RTTY modes
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
if (mode & RIG_MODE_RTTY || mode & RIG_MODE_RTTYR)
|
|
{
|
|
priv->question_mark_response_means_rejected = 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RIG_LEVEL_METER:
|
|
if (!newcat_valid_command(rig, "MS"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d
|
|
|| is_ftdx101mp) // new format for the command with VFO selection
|
|
{
|
|
format = "MS0%d;";
|
|
|
|
if (vfo == RIG_VFO_SUB)
|
|
{
|
|
format = "MS1%d;";
|
|
}
|
|
}
|
|
else if (is_ftdx10)
|
|
{
|
|
format = "MS%d0;";
|
|
}
|
|
else
|
|
{
|
|
format = "MS%d;";
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: format=%s\n", __func__, format);
|
|
|
|
switch (val.i)
|
|
{
|
|
case RIG_METER_ALC: SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), format, 1);
|
|
break;
|
|
|
|
case RIG_METER_PO:
|
|
if (newcat_is_rig(rig, RIG_MODEL_FT950))
|
|
{
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), format, 2);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_METER_SWR: SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), format, 3);
|
|
break;
|
|
|
|
case RIG_METER_COMP: SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), format, 0);
|
|
break;
|
|
|
|
case RIG_METER_IC: SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), format, 4);
|
|
break;
|
|
|
|
case RIG_METER_VDD: SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), format, 5);
|
|
break;
|
|
|
|
rig_debug(RIG_DEBUG_ERR, "%s: unknown val.i=%d\n", __func__, val.i);
|
|
|
|
default: RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_PREAMP:
|
|
if (!newcat_valid_command(rig, "PA"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (val.i == 0)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PA00%c", cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE && !is_ft2000)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
priv->cmd_str[0] = '\0';
|
|
|
|
for (i = 0; state->preamp[i] != RIG_DBLST_END; i++)
|
|
{
|
|
if (state->preamp[i] == val.i)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PA0%d%c", i + 1, cat_term);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (strlen(priv->cmd_str) == 0)
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_ATT:
|
|
if (!newcat_valid_command(rig, "RA"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (val.i == 0)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RA00%c", cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE && !is_ft2000)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
priv->cmd_str[0] = '\0';
|
|
|
|
for (i = 0; state->attenuator[i] != RIG_DBLST_END; i++)
|
|
{
|
|
if (state->attenuator[i] == val.i)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RA0%d%c", i + 1, cat_term);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (strlen(priv->cmd_str) == 0)
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_RF:
|
|
if (!newcat_valid_command(rig, "RG"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft891)
|
|
{
|
|
scale = 30;
|
|
}
|
|
else
|
|
{
|
|
scale = 255;
|
|
}
|
|
|
|
fpf = newcat_scale_float(scale, val.f);
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RG%c%03d%c", main_sub_vfo, fpf,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_NR:
|
|
if (!newcat_valid_command(rig, "RL"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (newcat_is_rig(rig, RIG_MODEL_FT450))
|
|
{
|
|
fpf = newcat_scale_float(11, val.f);
|
|
|
|
if (fpf < 1)
|
|
{
|
|
fpf = 1;
|
|
}
|
|
|
|
if (fpf > 11)
|
|
{
|
|
fpf = 11;
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RL0%02d%c", fpf, cat_term);
|
|
}
|
|
else
|
|
{
|
|
fpf = newcat_scale_float(15, val.f);
|
|
|
|
if (fpf < 1)
|
|
{
|
|
fpf = 1;
|
|
}
|
|
|
|
if (fpf > 15)
|
|
{
|
|
fpf = 15;
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RL0%02d%c", fpf, cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE && !is_ft2000)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_COMP:
|
|
if (!newcat_valid_command(rig, "PL"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft2000 || is_ftdx9000 || is_ftdx5000)
|
|
{
|
|
scale = 255;
|
|
}
|
|
else
|
|
{
|
|
scale = 100;
|
|
}
|
|
|
|
fpf = newcat_scale_float(scale, val.f);
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PL%03d%c", fpf, cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_BKINDL:
|
|
{
|
|
int millis;
|
|
value_t keyspd;
|
|
|
|
if (!newcat_valid_command(rig, "SD"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
// Convert 10/ths of dots to milliseconds using the current key speed
|
|
err = newcat_get_level(rig, vfo, RIG_LEVEL_KEYSPD, &keyspd);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
millis = dot10ths_to_millis(val.i, keyspd.i);
|
|
|
|
if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
if (millis <= 30) { SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD00;"); }
|
|
else if (millis <= 50) { SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD01;"); }
|
|
else if (millis <= 100) { SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD02;"); }
|
|
else if (millis <= 150) { SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD03;"); }
|
|
else if (millis <= 200) { SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD04;"); }
|
|
else if (millis <= 250) { SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD05;"); }
|
|
else if (millis > 2900) { SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD33;"); }
|
|
else
|
|
{
|
|
// This covers 300-2900 06-32
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD%02d;",
|
|
6 + ((millis - 300) / 100));
|
|
}
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
if (millis < 20)
|
|
{
|
|
millis = 20;
|
|
}
|
|
|
|
if (millis > 5000)
|
|
{
|
|
millis = 5000;
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", millis, cat_term);
|
|
}
|
|
else if (is_ft950 || is_ft450 || is_ft891 || is_ft991 || is_ftdx1200
|
|
|| is_ftdx3000 || is_ftdx3000dm)
|
|
{
|
|
if (millis < 30)
|
|
{
|
|
millis = 30;
|
|
}
|
|
|
|
if (millis > 3000)
|
|
{
|
|
millis = 3000;
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", millis, cat_term);
|
|
}
|
|
else if (is_ft2000 || is_ftdx9000)
|
|
{
|
|
if (millis < 0)
|
|
{
|
|
millis = 0;
|
|
}
|
|
|
|
if (millis > 5000)
|
|
{
|
|
millis = 5000;
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", millis, cat_term);
|
|
}
|
|
else // default
|
|
{
|
|
if (millis < 1)
|
|
{
|
|
millis = 1;
|
|
}
|
|
|
|
if (millis > 5000)
|
|
{
|
|
millis = 5000;
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", millis, cat_term);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RIG_LEVEL_SQL:
|
|
if (!newcat_valid_command(rig, "SQ"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft891 || is_ft991 || is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
scale = 100;
|
|
}
|
|
else
|
|
{
|
|
scale = 255;
|
|
}
|
|
|
|
fpf = newcat_scale_float(scale, val.f);
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SQ%c%03d%c", main_sub_vfo, fpf,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_VOXDELAY:
|
|
if (!newcat_valid_command(rig, "VD"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
/* VOX delay, api int (tenth of seconds), ms for rig */
|
|
val.i = val.i * 100;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: vali=%d\n", __func__, val.i);
|
|
|
|
if (is_ft950 || is_ft450 || is_ftdx1200)
|
|
{
|
|
if (val.i < 100) /* min is 30ms but spec is 100ms Unit Intervals */
|
|
{
|
|
val.i = 30;
|
|
}
|
|
|
|
if (val.i > 3000)
|
|
{
|
|
val.i = 3000;
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VD%04d%c", val.i, cat_term);
|
|
}
|
|
else if (is_ftdx101d || is_ftdx101mp || is_ftdx10) // new lookup table argument
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: ft101 #1 val.i=%d\n", __func__, val.i);
|
|
|
|
if (val.i == 0) { val.i = 0; }
|
|
else if (val.i <= 100) { val.i = 2; }
|
|
else if (val.i <= 200) { val.i = 4; }
|
|
else if (val.i > 3000) { val.i = 33; }
|
|
else { val.i = (val.i - 300) / 100 + 6; }
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: ftdx101/ftdx10 #1 val.i=%d\n", __func__, val.i);
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VD%02d%c", val.i, cat_term);
|
|
}
|
|
else if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
if (val.i < 0)
|
|
{
|
|
val.i = 0;
|
|
}
|
|
|
|
if (val.i > 5000)
|
|
{
|
|
val.i = 5000;
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VD%04d%c", val.i, cat_term);
|
|
}
|
|
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VD%04d%c", val.i, cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_VOXGAIN:
|
|
if (!newcat_valid_command(rig, "VG"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft2000 || is_ftdx9000 || is_ftdx5000 || is_ft450)
|
|
{
|
|
scale = 255;
|
|
}
|
|
else
|
|
{
|
|
scale = 100;
|
|
}
|
|
|
|
fpf = newcat_scale_float(scale, val.f);
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VG%03d%c", fpf, cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_ANTIVOX:
|
|
if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
fpf = newcat_scale_float(100, val.f);
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "AV%03d%c", fpf, cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
fpf = newcat_scale_float(100, val.f);
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX176%03d%c", fpf, cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx3000dm || is_ftdx1200)
|
|
{
|
|
fpf = newcat_scale_float(100, val.f);
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX183%03d%c", fpf, cat_term);
|
|
}
|
|
else if (is_ft991)
|
|
{
|
|
fpf = newcat_scale_float(100, val.f);
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX147%03d%c", fpf, cat_term);
|
|
}
|
|
else if (is_ft891)
|
|
{
|
|
fpf = newcat_scale_float(100, val.f);
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX1619%03d%c", fpf, cat_term);
|
|
}
|
|
else if (is_ft950)
|
|
{
|
|
fpf = newcat_scale_float(100, val.f);
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX117%03d%c", fpf, cat_term);
|
|
}
|
|
else if (is_ft2000)
|
|
{
|
|
fpf = newcat_scale_float(100, val.f);
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX042%03d%c", fpf, cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_NOTCHF:
|
|
if (!newcat_valid_command(rig, "BP"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
val.i = val.i / 10;
|
|
|
|
if (is_ftdx9000)
|
|
{
|
|
if (val.i < 0)
|
|
{
|
|
val.i = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (val.i < 1)
|
|
{
|
|
val.i = 1;
|
|
}
|
|
}
|
|
|
|
if (is_ft891 || is_ft991 || is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
if (val.i > 320)
|
|
{
|
|
val.i = 320;
|
|
}
|
|
}
|
|
|
|
if (is_ft950 || is_ftdx9000)
|
|
{
|
|
if (val.i > 300)
|
|
{
|
|
val.i = 300;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (val.i > 400)
|
|
{
|
|
val.i = 400;
|
|
}
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BP01%03d%c", val.i, cat_term);
|
|
|
|
if (is_ftdx9000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BP%03d%c", val.i, cat_term);
|
|
}
|
|
else if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_MONITOR_GAIN:
|
|
if (!newcat_valid_command(rig, "ML"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (val.f > 1.0) { RETURNFUNC(-RIG_EINVAL); }
|
|
|
|
if (is_ftdx1200 || is_ftdx3000 || is_ftdx3000dm || is_ft891 || is_ft991
|
|
|| is_ftdx101d
|
|
|| is_ftdx101mp
|
|
|| is_ftdx10)
|
|
{
|
|
fpf = newcat_scale_float(100, val.f);
|
|
}
|
|
else
|
|
{
|
|
fpf = newcat_scale_float(255, val.f);
|
|
}
|
|
|
|
if (is_ftdx9000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "ML%03d%c", fpf, cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "ML1%03d%c", fpf, cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_BAND_SELECT:
|
|
if (newcat_valid_command(rig, "BS"))
|
|
{
|
|
int band = band2rig((hamlib_band_t)val.i);
|
|
|
|
if (band < 0)
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BS%02d%c", band, cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_NB:
|
|
if (!newcat_valid_command(rig, "NL"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
fpf = newcat_scale_float(10, val.f);
|
|
|
|
if (fpf < 0)
|
|
{
|
|
fpf = 0;
|
|
}
|
|
|
|
if (fpf > 10)
|
|
{
|
|
fpf = 10;
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "NL00%02d%c", fpf, cat_term);
|
|
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
err = newcat_set_cmd(rig);
|
|
|
|
// Clear flag after executing command
|
|
priv->question_mark_response_means_rejected = 0;
|
|
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
|
|
int newcat_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
|
|
{
|
|
struct rig_state *state = &rig->state;
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
int ret_data_len;
|
|
char *retlvl;
|
|
int retlvl_len;
|
|
float scale;
|
|
char main_sub_vfo = '0';
|
|
int i;
|
|
|
|
ENTERFUNC;
|
|
|
|
/* Set Main or SUB vfo */
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_LEVEL)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
switch (level)
|
|
{
|
|
case RIG_LEVEL_RFPOWER:
|
|
if (!newcat_valid_command(rig, "PC"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PC%c", cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_PREAMP:
|
|
if (!newcat_valid_command(rig, "PA"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PA0%c", cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_AF:
|
|
if (!newcat_valid_command(rig, "AG"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "AG%c%c", main_sub_vfo,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_AGC:
|
|
if (!newcat_valid_command(rig, "GT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "GT%c%c", main_sub_vfo,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_IF:
|
|
{
|
|
pbwidth_t width;
|
|
rmode_t mode = 0;
|
|
|
|
if (!newcat_valid_command(rig, "IS"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
newcat_get_mode(rig, vfo, &mode, &width);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "IS%c%c", main_sub_vfo,
|
|
cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
// Some Yaesu rigs reject this command in AM/FM modes
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
if (mode & RIG_MODE_AM || mode & RIG_MODE_FM || mode & RIG_MODE_AMN
|
|
|| mode & RIG_MODE_FMN)
|
|
{
|
|
priv->question_mark_response_means_rejected = 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RIG_LEVEL_CWPITCH:
|
|
if (!newcat_valid_command(rig, "KP"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "KP%c", cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_KEYSPD:
|
|
if (!newcat_valid_command(rig, "KS"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "KS%c", cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_MICGAIN:
|
|
{
|
|
pbwidth_t width;
|
|
rmode_t mode = 0;
|
|
|
|
if (!newcat_valid_command(rig, "MG"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
newcat_get_mode(rig, vfo, &mode, &width);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MG%c", cat_term);
|
|
|
|
// Some Yaesu rigs reject this command in RTTY modes
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
if (mode & RIG_MODE_RTTY || mode & RIG_MODE_RTTYR)
|
|
{
|
|
priv->question_mark_response_means_rejected = 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RIG_LEVEL_METER:
|
|
if (!newcat_valid_command(rig, "MS"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MS%c", cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_ATT:
|
|
if (!newcat_valid_command(rig, "RA"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RA0%c", cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_RF:
|
|
if (!newcat_valid_command(rig, "RG"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RG%c%c", main_sub_vfo,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_COMP:
|
|
if (!newcat_valid_command(rig, "PL"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PL%c", cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_NR:
|
|
if (!newcat_valid_command(rig, "RL"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RL0%c", cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_BKINDL:
|
|
if (!newcat_valid_command(rig, "SD"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SD%c", cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_SQL:
|
|
if (!newcat_valid_command(rig, "SQ"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SQ%c%c", main_sub_vfo,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_VOXDELAY:
|
|
|
|
/* VOX delay, arg int (tenth of seconds) */
|
|
if (!newcat_valid_command(rig, "VD"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VD%c", cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_VOXGAIN:
|
|
if (!newcat_valid_command(rig, "VG"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VG%c", cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_NB:
|
|
if (!newcat_valid_command(rig, "NL"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "NL0%c", cat_term);
|
|
break;
|
|
|
|
/*
|
|
* Read only levels
|
|
*/
|
|
case RIG_LEVEL_STRENGTH:
|
|
case RIG_LEVEL_RAWSTR:
|
|
if (!newcat_valid_command(rig, "SM"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SM%c%c", main_sub_vfo,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_LEVEL_SWR:
|
|
if (!newcat_valid_command(rig, "RM"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx9000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM09%c", cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx3000dm || is_ftdx5000)
|
|
{
|
|
// The 3000 has to use the meter read for SWR when the tuner is on
|
|
// We'll assume the 5000 is the same way for now
|
|
// Also need to ensure SWR is selected for the meter
|
|
int tuner;
|
|
value_t meter;
|
|
newcat_get_func(rig, RIG_VFO_A, RIG_FUNC_TUNER, &tuner);
|
|
newcat_get_level(rig, RIG_VFO_A, RIG_LEVEL_METER, &meter);
|
|
|
|
if (tuner && meter.i != RIG_METER_SWR)
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL); // if meter not SWR can't read SWR
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM%c%c", (tuner
|
|
&& meter.i == RIG_METER_SWR) ? '2' : '6',
|
|
cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM6%c", cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_ALC:
|
|
if (!newcat_valid_command(rig, "RM"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx9000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM07%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM4%c", cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_RFPOWER_METER:
|
|
case RIG_LEVEL_RFPOWER_METER_WATTS:
|
|
if (!newcat_valid_command(rig, "RM"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx9000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM08%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM5%c", cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_COMP_METER:
|
|
if (!newcat_valid_command(rig, "RM"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx9000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM06%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM3%c", cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_VD_METER:
|
|
if (!newcat_valid_command(rig, "RM"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx9000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM11%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM8%c", cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_ID_METER:
|
|
if (!newcat_valid_command(rig, "RM"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx9000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM10%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM7%c", cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_ANTIVOX:
|
|
if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "AV%c", cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX176%c", cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx3000dm || is_ftdx1200)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX183%c", cat_term);
|
|
}
|
|
else if (is_ftdx1200)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX183%c", cat_term);
|
|
}
|
|
else if (is_ft991)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX147%c", cat_term);
|
|
}
|
|
else if (is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX1619%c", cat_term);
|
|
}
|
|
else if (is_ft950)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX117%c", cat_term);
|
|
}
|
|
else if (is_ft2000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX042%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_NOTCHF:
|
|
if (!newcat_valid_command(rig, "BP"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BP01%c", cat_term);
|
|
|
|
if (is_ftdx9000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BP%c", cat_term);
|
|
}
|
|
else if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_MONITOR_GAIN:
|
|
if (!newcat_valid_command(rig, "ML"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx9000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "ML%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "ML1%c", cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_TEMP_METER:
|
|
if (!newcat_valid_command(rig, "RM"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx9000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM14%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RM9%c", cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
err = newcat_get_cmd(rig);
|
|
|
|
// Clear flag after executing command
|
|
priv->question_mark_response_means_rejected = 0;
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
ret_data_len = strlen(priv->ret_data);
|
|
|
|
/* skip command */
|
|
retlvl = priv->ret_data + strlen(priv->cmd_str) - 1;
|
|
retlvl_len = strlen(retlvl);
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: retlvl='%s'\n", __func__, retlvl);
|
|
/* chop term */
|
|
priv->ret_data[ret_data_len - 1] = '\0';
|
|
|
|
switch (level)
|
|
{
|
|
case RIG_LEVEL_RFPOWER:
|
|
if (is_ft950 || is_ftdx1200 || is_ftdx3000 || is_ftdx3000dm || is_ft891
|
|
|| is_ft991
|
|
|| is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
scale = 100.;
|
|
}
|
|
else if (is_ft450 && newcat_get_rigid(rig) == NC_RIGID_FT450D)
|
|
{
|
|
scale = 100.;
|
|
}
|
|
else
|
|
{
|
|
scale = 255.;
|
|
}
|
|
|
|
val->f = (float)atoi(retlvl) / scale;
|
|
break;
|
|
|
|
case RIG_LEVEL_VOXGAIN:
|
|
case RIG_LEVEL_COMP:
|
|
if (is_ft2000 || is_ftdx9000 || is_ftdx5000 || is_ft450)
|
|
{
|
|
scale = 255;
|
|
}
|
|
else
|
|
{
|
|
scale = 100;
|
|
}
|
|
|
|
val->f = (float) atoi(retlvl) / scale;
|
|
break;
|
|
|
|
case RIG_LEVEL_ANTIVOX:
|
|
val->f = (float) atoi(retlvl) / 100.;
|
|
break;
|
|
|
|
case RIG_LEVEL_SWR:
|
|
if (retlvl_len > 3)
|
|
{
|
|
// Some rigs like FTDX101 have 6-byte return so we just truncate
|
|
retlvl[3] = 0;
|
|
}
|
|
|
|
if (rig->caps->swr_cal.size == 0)
|
|
{
|
|
val->f = rig_raw2val_float(atoi(retlvl), &yaesu_default_swr_cal);
|
|
}
|
|
else
|
|
{
|
|
val->f = rig_raw2val_float(atoi(retlvl), &rig->caps->swr_cal);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_ALC:
|
|
if (retlvl_len > 3)
|
|
{
|
|
// Some rigs like FTDX101 have 6-byte return so we just truncate
|
|
retlvl[3] = 0;
|
|
}
|
|
|
|
if (rig->caps->alc_cal.size == 0)
|
|
{
|
|
val->f = rig_raw2val_float(atoi(retlvl), &yaesu_default_alc_cal);
|
|
}
|
|
else
|
|
{
|
|
val->f = rig_raw2val_float(atoi(retlvl), &rig->caps->alc_cal);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_RFPOWER_METER:
|
|
case RIG_LEVEL_RFPOWER_METER_WATTS:
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: RFPOWER_METER retlvl=%s\n", __func__, retlvl);
|
|
|
|
if (retlvl_len > 3)
|
|
{
|
|
// Some rigs like FTDX101 have 6-byte return so we just truncate
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: retlvl of %s getting truncated\n", __func__,
|
|
retlvl);
|
|
retlvl[3] = 0;
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: retlvl truncated to %s\n", __func__, retlvl);
|
|
}
|
|
|
|
if (rig->caps->rfpower_meter_cal.size == 0)
|
|
{
|
|
val->f = rig_raw2val_float(atoi(retlvl),
|
|
&yaesu_default_rfpower_meter_cal) / (level == RIG_LEVEL_RFPOWER_METER_WATTS ?
|
|
1.0 : 100.0);
|
|
}
|
|
else
|
|
{
|
|
val->f = rig_raw2val_float(atoi(retlvl),
|
|
&rig->caps->rfpower_meter_cal) / (level == RIG_LEVEL_RFPOWER_METER_WATTS ? 1.0 :
|
|
100.0);
|
|
|
|
if (priv->rig_id == NC_RIGID_FT2000)
|
|
{
|
|
// we reuse the FT2000D table for the FT2000 so need to divide by 2
|
|
// hopefully this works well otherwise we need a separate table
|
|
val->f /= 2;
|
|
}
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: RFPOWER_METER=%s, converted to %f\n",
|
|
__func__, retlvl, val->f);
|
|
|
|
if (level == RIG_LEVEL_RFPOWER_METER && val->f > 1.0)
|
|
{
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: val->f(%f) clipped at 1.0\n", __func__,
|
|
val->f);
|
|
val->f = 1.0;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_COMP_METER:
|
|
if (retlvl_len > 3)
|
|
{
|
|
// Some rigs like FTDX101 have 6-byte return so we just truncate
|
|
retlvl[3] = 0;
|
|
}
|
|
|
|
if (rig->caps->comp_meter_cal.size == 0)
|
|
{
|
|
val->f = rig_raw2val_float(atoi(retlvl), &yaesu_default_comp_meter_cal);
|
|
}
|
|
else
|
|
{
|
|
val->f = rig_raw2val_float(atoi(retlvl), &rig->caps->comp_meter_cal);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_VD_METER:
|
|
if (retlvl_len > 3)
|
|
{
|
|
// Some rigs like FTDX101 have 6-byte return so we just truncate
|
|
retlvl[3] = 0;
|
|
}
|
|
|
|
if (rig->caps->vd_meter_cal.size == 0)
|
|
{
|
|
val->f = rig_raw2val_float(atoi(retlvl), &yaesu_default_vd_meter_cal);
|
|
}
|
|
else
|
|
{
|
|
val->f = rig_raw2val_float(atoi(retlvl), &rig->caps->vd_meter_cal);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_ID_METER:
|
|
if (retlvl_len > 3)
|
|
{
|
|
// Some rigs like FTDX101 have 6-byte return so we just truncate
|
|
retlvl[3] = 0;
|
|
}
|
|
|
|
if (rig->caps->id_meter_cal.size == 0)
|
|
{
|
|
val->f = rig_raw2val_float(atoi(retlvl), &yaesu_default_id_meter_cal);
|
|
}
|
|
else
|
|
{
|
|
val->f = rig_raw2val_float(atoi(retlvl), &rig->caps->id_meter_cal);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_MICGAIN:
|
|
if (is_ftdx1200 || is_ftdx3000 || is_ftdx3000dm || is_ft891 || is_ft991
|
|
|| is_ftdx101d
|
|
|| is_ftdx101mp
|
|
|| is_ftdx10)
|
|
{
|
|
scale = 100.;
|
|
}
|
|
else
|
|
{
|
|
scale = 255.;
|
|
}
|
|
|
|
val->f = (float)atoi(retlvl) / scale;
|
|
break;
|
|
|
|
case RIG_LEVEL_AF:
|
|
val->f = (float)atoi(retlvl) / 255;
|
|
break;
|
|
|
|
case RIG_LEVEL_RF:
|
|
if (is_ft891)
|
|
{
|
|
scale = 30.;
|
|
}
|
|
else
|
|
{
|
|
scale = 255.;
|
|
}
|
|
|
|
val->f = (float)atoi(retlvl) / scale;
|
|
break;
|
|
|
|
case RIG_LEVEL_SQL:
|
|
if (is_ft891 || is_ft991 || is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
scale = 100.;
|
|
}
|
|
else
|
|
{
|
|
scale = 255.;
|
|
}
|
|
|
|
val->f = (float)atoi(retlvl) / scale;
|
|
break;
|
|
|
|
case RIG_LEVEL_BKINDL:
|
|
{
|
|
int raw_value = atoi(retlvl);
|
|
int millis;
|
|
value_t keyspd;
|
|
|
|
if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
switch (raw_value)
|
|
{
|
|
case 0: millis = 30; break;
|
|
|
|
case 1: millis = 50; break;
|
|
|
|
case 2: millis = 100; break;
|
|
|
|
case 3: millis = 150; break;
|
|
|
|
case 4: millis = 200; break;
|
|
|
|
case 5: millis = 250; break;
|
|
|
|
case 6: millis = 300; break;
|
|
|
|
default:
|
|
millis = (raw_value - 6) * 100 + 300;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The rest of Yaesu rigs indicate break-in delay directly as milliseconds
|
|
millis = raw_value;
|
|
}
|
|
|
|
// Convert milliseconds to 10/ths of dots using the current key speed
|
|
err = newcat_get_level(rig, vfo, RIG_LEVEL_KEYSPD, &keyspd);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
val->i = millis_to_dot10ths(millis, keyspd.i);
|
|
break;
|
|
}
|
|
|
|
case RIG_LEVEL_STRENGTH:
|
|
if (rig->caps->str_cal.size > 0)
|
|
{
|
|
val->i = round(rig_raw2val(atoi(retlvl), &rig->caps->str_cal));
|
|
break;
|
|
}
|
|
|
|
if (is_ftdx1200 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ft891
|
|
|| is_ft991
|
|
|| is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
val->i = round(rig_raw2val(atoi(retlvl), &yaesu_default_str_cal));
|
|
}
|
|
else
|
|
{
|
|
// Some Yaesu rigs return straight S-meter answers
|
|
// Return dbS9 -- does >S9 mean 10dB increments? If not, add to rig driver
|
|
if (val->i > 0)
|
|
{
|
|
val->i = (atoi(retlvl) - 9) * 10;
|
|
}
|
|
else
|
|
{
|
|
val->i = (atoi(retlvl) - 9) * 6;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_RAWSTR:
|
|
case RIG_LEVEL_KEYSPD:
|
|
if (rig->caps->rig_model == RIG_MODEL_TS570D
|
|
|| rig->caps->rig_model == RIG_MODEL_TS570S)
|
|
{
|
|
// TS570 uses 010-~060 scale according to manual
|
|
val->i = atoi(retlvl) / 2 + 10;
|
|
}
|
|
else
|
|
{
|
|
val->i = atoi(retlvl);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_IF:
|
|
// IS00+0400
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: ret_data=%s(%d), retlvl=%s\n", __func__,
|
|
priv->ret_data, (int)strlen(priv->ret_data), retlvl);
|
|
|
|
if (strlen(priv->ret_data) == 9)
|
|
{
|
|
int n = sscanf(priv->ret_data, "IS%*c0%d\n", &val->i);
|
|
|
|
if (n != 1)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: unable to parse level from %s\n", __func__,
|
|
priv->ret_data);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
val->i = atoi(retlvl);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_NR:
|
|
if (is_ft450)
|
|
{
|
|
val->f = (float)(atoi(retlvl) / 11.);
|
|
}
|
|
else
|
|
{
|
|
val->f = (float)(atoi(retlvl) / 15.);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_VOXDELAY:
|
|
val->i = atoi(retlvl);
|
|
|
|
if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
switch (val->i)
|
|
{
|
|
case 0: val->i = 0; break; // 30ms=0 we only do tenths
|
|
|
|
case 1: val->i = 0; break; // 50ms=0
|
|
|
|
case 2: val->i = 1; break; // 100ms=1
|
|
|
|
case 3: val->i = 1; break; // 150ms=1
|
|
|
|
case 4: val->i = 2; break; // 200ms=2
|
|
|
|
case 5: val->i = 2; break; // 250ms=2
|
|
|
|
default:
|
|
val->i = (val->i - 6) + 3;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* VOX delay, arg int (tenth of seconds), rig in ms */
|
|
val->i /= 10; // Convert from ms to tenths
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_PREAMP:
|
|
{
|
|
int preamp;
|
|
|
|
if (retlvl[0] < '0' || retlvl[0] > '9')
|
|
{
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
preamp = retlvl[0] - '0';
|
|
|
|
val->i = 0;
|
|
|
|
if (preamp > 0)
|
|
{
|
|
for (i = 0; state->preamp[i] != RIG_DBLST_END; i++)
|
|
{
|
|
if (i == preamp - 1)
|
|
{
|
|
val->i = state->preamp[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RIG_LEVEL_ATT:
|
|
{
|
|
int att;
|
|
|
|
if (retlvl[0] < '0' || retlvl[0] > '9')
|
|
{
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
att = retlvl[0] - '0';
|
|
|
|
val->i = 0;
|
|
|
|
if (att > 0)
|
|
{
|
|
for (i = 0; state->attenuator[i] != RIG_DBLST_END; i++)
|
|
{
|
|
if (i == att - 1)
|
|
{
|
|
val->i = state->attenuator[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RIG_LEVEL_AGC:
|
|
switch (retlvl[0])
|
|
{
|
|
case '0':
|
|
val->i = RIG_AGC_OFF;
|
|
break;
|
|
|
|
case '1':
|
|
val->i = RIG_AGC_FAST;
|
|
break;
|
|
|
|
case '2':
|
|
val->i = RIG_AGC_MEDIUM;
|
|
break;
|
|
|
|
case '3':
|
|
val->i = RIG_AGC_SLOW;
|
|
break;
|
|
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
val->i = RIG_AGC_AUTO; break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_CWPITCH:
|
|
if (is_ft950 || is_ft2000)
|
|
{
|
|
val->i = (atoi(retlvl) * 50) + 300;
|
|
}
|
|
else
|
|
{
|
|
// Most Yaesu rigs seem to use range of 0-75 to represent pitch of 300..1050 Hz in 10 Hz steps
|
|
val->i = (atoi(retlvl) * 10) + 300;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_METER:
|
|
switch (retlvl[0])
|
|
{
|
|
case '0': val->i = RIG_METER_COMP; break;
|
|
|
|
case '1': val->i = RIG_METER_ALC; break;
|
|
|
|
case '2': val->i = RIG_METER_PO; break;
|
|
|
|
case '3': val->i = RIG_METER_SWR; break;
|
|
|
|
case '4': val->i = RIG_METER_IC; break; /* ID CURRENT */
|
|
|
|
case '5': val->i = RIG_METER_VDD; break; /* Final Amp Voltage */
|
|
|
|
default: RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_LEVEL_NOTCHF:
|
|
val->i = atoi(retlvl) * 10;
|
|
break;
|
|
|
|
case RIG_LEVEL_MONITOR_GAIN:
|
|
if (is_ftdx1200 || is_ftdx3000 || is_ftdx3000dm || is_ft891 || is_ft991
|
|
|| is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
scale = 100.;
|
|
}
|
|
else
|
|
{
|
|
scale = 255.;
|
|
}
|
|
|
|
val->f = (float)atoi(retlvl) / scale;
|
|
break;
|
|
|
|
case RIG_LEVEL_NB:
|
|
val->f = (float)(atoi(retlvl) / 10.);
|
|
break;
|
|
|
|
case RIG_LEVEL_TEMP_METER:
|
|
// return value in centigrade -- first 3 digits
|
|
i = 0;
|
|
sscanf(retlvl, "%3d", &i);
|
|
val->f = i / 255. * 100.;
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: retlvl=%s, i=%d, val=%g\n", __func__, retlvl,
|
|
i, val->f);
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
|
|
/* Set Main or SUB vfo */
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & (RIG_TARGETABLE_MODE | RIG_TARGETABLE_TONE))
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
switch (func)
|
|
{
|
|
case RIG_FUNC_ANF:
|
|
{
|
|
pbwidth_t width;
|
|
rmode_t mode = 0;
|
|
|
|
if (!newcat_valid_command(rig, "BC"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
err = newcat_get_mode(rig, vfo, &mode, &width);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BC0%d%c", status ? 1 : 0,
|
|
cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE && !is_ft2000)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
// Some Yaesu rigs reject this command in FM mode
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
if (mode & RIG_MODE_FM || mode & RIG_MODE_FMN)
|
|
{
|
|
priv->question_mark_response_means_rejected = 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RIG_FUNC_MN:
|
|
{
|
|
pbwidth_t width;
|
|
rmode_t mode = 0;
|
|
|
|
if (!newcat_valid_command(rig, "BP"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
newcat_get_mode(rig, vfo, &mode, &width);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BP00%03d%c", status ? 1 : 0,
|
|
cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE && !is_ft2000)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
// Some Yaesu rigs reject this command in FM mode
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
if (mode & RIG_MODE_FM || mode & RIG_MODE_FMN)
|
|
{
|
|
priv->question_mark_response_means_rejected = 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RIG_FUNC_FBKIN:
|
|
if (!newcat_valid_command(rig, "BI"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BI%d%c", status ? 1 : 0,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_TONE:
|
|
if (!newcat_valid_command(rig, "CT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT0%d%c", status ? 2 : 0,
|
|
cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_TONE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_TSQL:
|
|
if (!newcat_valid_command(rig, "CT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT0%d%c", status ? 1 : 0,
|
|
cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_TONE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_CSQL:
|
|
if (!newcat_valid_command(rig, "CT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT0%d%c", status ? 3 : 0,
|
|
cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_TONE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_LOCK:
|
|
if (!newcat_valid_command(rig, "LK"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx1200 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
// These rigs can lock Main/Sub VFO dials individually
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "LK%d%c", status ? 7 : 4,
|
|
cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "LK%d%c", status ? 1 : 0,
|
|
cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_MON:
|
|
if (!newcat_valid_command(rig, "ML"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "ML0%03d%c", status ? 1 : 0,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_NB:
|
|
if (!newcat_valid_command(rig, "NB"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "NB0%d%c", status ? 1 : 0,
|
|
cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_NR:
|
|
{
|
|
pbwidth_t width;
|
|
rmode_t mode = 0;
|
|
|
|
if (!newcat_valid_command(rig, "NR"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
newcat_get_mode(rig, vfo, &mode, &width);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "NR0%d%c", status ? 1 : 0,
|
|
cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
// Some Yaesu rigs reject this command in FM mode
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
if (mode & RIG_MODE_FM || mode & RIG_MODE_FMN)
|
|
{
|
|
priv->question_mark_response_means_rejected = 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RIG_FUNC_COMP:
|
|
{
|
|
pbwidth_t width;
|
|
rmode_t mode = 0;
|
|
|
|
if (!newcat_valid_command(rig, "PR"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
newcat_get_mode(rig, vfo, &mode, &width);
|
|
}
|
|
|
|
if (is_ft891 || is_ft991 || is_ftdx1200 || is_ftdx3000 || is_ftdx3000dm
|
|
|| is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
// There seems to be an error in the manuals for some of these rigs stating that values should be 1 = OFF and 2 = ON, but they are 0 = OFF and 1 = ON instead
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PR0%d%c", status ? 1 : 0,
|
|
cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PR%d%c", status ? 1 : 0,
|
|
cat_term);
|
|
}
|
|
|
|
// Some Yaesu rigs reject this command in AM/FM/RTTY modes
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
if (mode & RIG_MODE_AM || mode & RIG_MODE_FM || mode & RIG_MODE_AMN
|
|
|| mode & RIG_MODE_FMN ||
|
|
mode & RIG_MODE_RTTY || mode & RIG_MODE_RTTYR)
|
|
{
|
|
priv->question_mark_response_means_rejected = 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RIG_FUNC_VOX:
|
|
if (!newcat_valid_command(rig, "VX"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VX%d%c", status ? 1 : 0,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_TUNER:
|
|
if (!newcat_valid_command(rig, "AC"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
priv->question_mark_response_means_rejected = 1;
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "AC00%d%c",
|
|
status == 0 ? 0 : status,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_RIT:
|
|
if (!newcat_valid_command(rig, "RT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RT%d%c", status ? 1 : 0,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_XIT:
|
|
if (!newcat_valid_command(rig, "XT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "XT%d%c", status ? 1 : 0,
|
|
cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_APF:
|
|
if (!newcat_valid_command(rig, "CO"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c2%04d%c", main_sub_vfo,
|
|
status ? 1 : 0, cat_term);
|
|
}
|
|
else if (is_ftdx10 || is_ft991 || is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO02%04d%c", status ? 1 : 0,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c0%02d%c", main_sub_vfo,
|
|
status ? 2 : 0, cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx3000dm || is_ftdx1200 || is_ft2000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO00%02d%c", status ? 2 : 0,
|
|
cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC(-RIG_ENIMPL);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
err = newcat_set_cmd(rig);
|
|
|
|
// Clear flag after executing command
|
|
priv->question_mark_response_means_rejected = 0;
|
|
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
|
|
int newcat_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
int ret_data_len;
|
|
int last_char_index;
|
|
char *retfunc;
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
|
|
if (rig->caps->targetable_vfo & (RIG_TARGETABLE_MODE | RIG_TARGETABLE_TONE))
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
switch (func)
|
|
{
|
|
case RIG_FUNC_ANF:
|
|
{
|
|
pbwidth_t width;
|
|
rmode_t mode = 0;
|
|
|
|
if (!newcat_valid_command(rig, "BC"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
err = newcat_get_mode(rig, vfo, &mode, &width);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BC0%c", cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
// Some Yaesu rigs reject this command in FM mode
|
|
if (is_ft991 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
if (mode & RIG_MODE_FM || mode & RIG_MODE_FMN)
|
|
{
|
|
priv->question_mark_response_means_rejected = 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RIG_FUNC_MN:
|
|
if (!newcat_valid_command(rig, "BP"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BP00%c", cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_FBKIN:
|
|
if (!newcat_valid_command(rig, "BI"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BI%c", cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_TONE:
|
|
if (!newcat_valid_command(rig, "CT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT0%c", cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_TONE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_TSQL:
|
|
if (!newcat_valid_command(rig, "CT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT0%c", cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_TONE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_CSQL:
|
|
if (!newcat_valid_command(rig, "CT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT0%c", cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_TONE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_LOCK:
|
|
if (!newcat_valid_command(rig, "LK"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "LK%c", cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_MON:
|
|
if (!newcat_valid_command(rig, "ML"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "ML0%c", cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_NB:
|
|
if (!newcat_valid_command(rig, "NB"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "NB0%c", cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_NR:
|
|
if (!newcat_valid_command(rig, "NR"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "NR0%c", cat_term);
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
priv->cmd_str[2] = main_sub_vfo;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_COMP:
|
|
if (!newcat_valid_command(rig, "PR"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx1200 || is_ftdx3000 || is_ftdx3000dm || is_ft891 || is_ft991
|
|
|| is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PR0%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PR%c", cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_VOX:
|
|
if (!newcat_valid_command(rig, "VX"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VX%c", cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_TUNER:
|
|
if (!newcat_valid_command(rig, "AC"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "AC%c", cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_RIT:
|
|
if (!newcat_valid_command(rig, "RT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RT%c", cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_XIT:
|
|
if (!newcat_valid_command(rig, "XT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "XT%c", cat_term);
|
|
break;
|
|
|
|
case RIG_FUNC_APF:
|
|
if (!newcat_valid_command(rig, "CO"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c2%c", main_sub_vfo,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx10 || is_ft991 || is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO02%c", cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c0%c", main_sub_vfo,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx3000dm || is_ftdx1200 || is_ft2000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO00%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC(-RIG_ENIMPL);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
err = newcat_get_cmd(rig);
|
|
|
|
// Clear flag after executing command
|
|
priv->question_mark_response_means_rejected = 0;
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
ret_data_len = strlen(priv->ret_data);
|
|
|
|
/* skip command */
|
|
retfunc = priv->ret_data + strlen(priv->cmd_str) - 1;
|
|
/* chop term */
|
|
priv->ret_data[ret_data_len - 1] = '\0';
|
|
|
|
last_char_index = strlen(retfunc) - 1;
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: retfunc='%s'\n", __func__, retfunc);
|
|
|
|
switch (func)
|
|
{
|
|
case RIG_FUNC_MN:
|
|
*status = (retfunc[2] == '0') ? 0 : 1;
|
|
break;
|
|
|
|
case RIG_FUNC_COMP:
|
|
*status = (retfunc[0] == '0') ? 0 : 1;
|
|
break;
|
|
|
|
case RIG_FUNC_MON:
|
|
// The number of digits varies by rig, but the last digit indicates the status always
|
|
*status = (retfunc[last_char_index] == '0') ? 0 : 1;
|
|
break;
|
|
|
|
case RIG_FUNC_LOCK:
|
|
if (is_ftdx1200 || is_ftdx3000 || is_ftdx3000dm || is_ftdx5000 || is_ftdx101d
|
|
|| is_ftdx101mp)
|
|
{
|
|
// These rigs can lock Main/Sub VFO dials individually
|
|
*status = (retfunc[0] == '0' || retfunc[0] == '4') ? 0 : 1;
|
|
}
|
|
else
|
|
{
|
|
*status = (retfunc[0] == '0') ? 0 : 1;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_FUNC_ANF:
|
|
case RIG_FUNC_FBKIN:
|
|
case RIG_FUNC_NB:
|
|
case RIG_FUNC_NR:
|
|
case RIG_FUNC_VOX:
|
|
*status = (retfunc[0] == '0') ? 0 : 1;
|
|
break;
|
|
|
|
case RIG_FUNC_TONE:
|
|
*status = (retfunc[0] == '2') ? 1 : 0;
|
|
break;
|
|
|
|
case RIG_FUNC_TSQL:
|
|
*status = (retfunc[0] == '1') ? 1 : 0;
|
|
break;
|
|
|
|
case RIG_FUNC_CSQL:
|
|
*status = (retfunc[0] == '3') ? 1 : 0;
|
|
break;
|
|
|
|
case RIG_FUNC_TUNER:
|
|
*status = (retfunc[2] == '1') ? 1 : 0;
|
|
break;
|
|
|
|
case RIG_FUNC_RIT:
|
|
*status = (retfunc[0] == '1') ? 1 : 0;
|
|
break;
|
|
|
|
case RIG_FUNC_XIT:
|
|
*status = (retfunc[0] == '1') ? 1 : 0;
|
|
break;
|
|
|
|
case RIG_FUNC_APF:
|
|
if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
*status = (retfunc[last_char_index] == '1') ? 1 : 0;
|
|
}
|
|
else if (is_ftdx10 || is_ft991 || is_ft891)
|
|
{
|
|
*status = (retfunc[last_char_index] == '1') ? 1 : 0;
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
*status = (retfunc[last_char_index] == '2') ? 1 : 0;
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx3000dm || is_ftdx1200 || is_ft2000)
|
|
{
|
|
*status = (retfunc[last_char_index] == '2') ? 1 : 0;
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC(-RIG_ENIMPL);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_parm(RIG *rig, setting_t parm, value_t val)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_get_parm(RIG *rig, setting_t parm, value_t *val)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_set_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t val)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
|
|
ENTERFUNC;
|
|
|
|
switch (token)
|
|
{
|
|
case TOK_ROOFING_FILTER:
|
|
RETURNFUNC(set_roofing_filter(rig, vfo, val.i));
|
|
|
|
case TOK_KEYER:
|
|
if (!newcat_valid_command(rig, "ML"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "KR%d%c", val.i ? 1 : 0,
|
|
cat_term);
|
|
|
|
RETURNFUNC(newcat_set_cmd(rig));
|
|
|
|
case TOK_APF_FREQ:
|
|
RETURNFUNC(newcat_set_apf_frequency(rig, vfo, val.f));
|
|
|
|
case TOK_APF_WIDTH:
|
|
RETURNFUNC(newcat_set_apf_width(rig, vfo, val.i));
|
|
|
|
case TOK_CONTOUR:
|
|
RETURNFUNC(newcat_set_contour(rig, vfo, val.i));
|
|
|
|
case TOK_CONTOUR_FREQ:
|
|
RETURNFUNC(newcat_set_contour_frequency(rig, vfo, val.f));
|
|
|
|
case TOK_CONTOUR_LEVEL:
|
|
RETURNFUNC(newcat_set_contour_level(rig, vfo, val.f));
|
|
|
|
case TOK_CONTOUR_WIDTH:
|
|
RETURNFUNC(newcat_set_contour_width(rig, vfo, val.f));
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_ERR, "%s: Unsupported ext level %s\n", __func__,
|
|
rig_strlevel(token));
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
}
|
|
|
|
int newcat_get_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t *val)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char *result;
|
|
int retval;
|
|
int value;
|
|
|
|
ENTERFUNC;
|
|
|
|
switch (token)
|
|
{
|
|
case TOK_ROOFING_FILTER:
|
|
{
|
|
struct newcat_roofing_filter *roofing_filter;
|
|
retval = get_roofing_filter(rig, vfo, &roofing_filter);
|
|
|
|
if (retval != RIG_OK)
|
|
{
|
|
RETURNFUNC(retval);
|
|
}
|
|
|
|
val->i = roofing_filter->index;
|
|
break;
|
|
}
|
|
|
|
case TOK_KEYER:
|
|
if (!newcat_valid_command(rig, "KR"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "KR%c", cat_term);
|
|
|
|
retval = newcat_get_cmd(rig);
|
|
|
|
if (retval != RIG_OK)
|
|
{
|
|
RETURNFUNC(retval);
|
|
}
|
|
|
|
/* skip command */
|
|
result = priv->ret_data + strlen(priv->cmd_str) - 1;
|
|
/* chop term */
|
|
priv->ret_data[strlen(priv->ret_data) - 1] = '\0';
|
|
|
|
val->i = result[0] == '0' ? 0 : 1;
|
|
break;
|
|
|
|
case TOK_APF_FREQ:
|
|
retval = newcat_get_apf_frequency(rig, vfo, &value);
|
|
|
|
if (retval != RIG_OK)
|
|
{
|
|
RETURNFUNC(retval);
|
|
}
|
|
|
|
val->f = value;
|
|
break;
|
|
|
|
case TOK_APF_WIDTH:
|
|
retval = newcat_get_apf_width(rig, vfo, &value);
|
|
|
|
if (retval != RIG_OK)
|
|
{
|
|
RETURNFUNC(retval);
|
|
}
|
|
|
|
val->i = value;
|
|
break;
|
|
|
|
case TOK_CONTOUR:
|
|
retval = newcat_get_contour(rig, vfo, &value);
|
|
|
|
if (retval != RIG_OK)
|
|
{
|
|
RETURNFUNC(retval);
|
|
}
|
|
|
|
val->i = value;
|
|
break;
|
|
|
|
case TOK_CONTOUR_WIDTH:
|
|
retval = newcat_get_contour_width(rig, vfo, &value);
|
|
|
|
if (retval != RIG_OK)
|
|
{
|
|
RETURNFUNC(retval);
|
|
}
|
|
|
|
val->f = value;
|
|
break;
|
|
|
|
case TOK_CONTOUR_FREQ:
|
|
retval = newcat_get_contour_frequency(rig, vfo, &value);
|
|
|
|
if (retval != RIG_OK)
|
|
{
|
|
RETURNFUNC(retval);
|
|
}
|
|
|
|
val->f = value;
|
|
break;
|
|
|
|
case TOK_CONTOUR_LEVEL:
|
|
retval = newcat_get_contour_level(rig, vfo, &value);
|
|
|
|
if (retval != RIG_OK)
|
|
{
|
|
RETURNFUNC(retval);
|
|
}
|
|
|
|
val->f = value;
|
|
break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_ERR, "%s: Unsupported ext level %s\n", __func__,
|
|
rig_strlevel(token));
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
int newcat_set_ext_parm(RIG *rig, token_t token, value_t val)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_get_ext_parm(RIG *rig, token_t token, value_t *val)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_send_dtmf(RIG *rig, vfo_t vfo, const char *digits)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_recv_dtmf(RIG *rig, vfo_t vfo, char *digits, int *length)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_send_morse(RIG *rig, vfo_t vfo, const char *msg)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int rc;
|
|
char *s = strdup(msg);
|
|
ENTERFUNC;
|
|
|
|
if (newcat_is_rig(rig, RIG_MODEL_FT450))
|
|
{
|
|
// 450 manual says 1/2/3 playback needs P1=6/7/8
|
|
s[0] += 5;
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "KY%c%c", s[0], cat_term);
|
|
}
|
|
|
|
rc = newcat_set_cmd(rig);
|
|
free(s);
|
|
RETURNFUNC(rc);
|
|
}
|
|
|
|
|
|
int newcat_set_bank(RIG *rig, vfo_t vfo, int bank)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_set_mem(RIG *rig, vfo_t vfo, int ch)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err, i;
|
|
ncboolean restore_vfo;
|
|
chan_t *chan_list;
|
|
channel_t valid_chan;
|
|
channel_cap_t *mem_caps = NULL;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, "MC"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
chan_list = rig->caps->chan_list;
|
|
|
|
for (i = 0; i < HAMLIB_CHANLSTSIZ && !RIG_IS_CHAN_END(chan_list[i]); i++)
|
|
{
|
|
if (ch >= chan_list[i].startc &&
|
|
ch <= chan_list[i].endc)
|
|
{
|
|
mem_caps = &chan_list[i].mem_caps;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Test for valid usable channel, skip if empty */
|
|
memset(&valid_chan, 0, sizeof(channel_t));
|
|
valid_chan.channel_num = ch;
|
|
err = newcat_get_channel(rig, vfo, &valid_chan, 1);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (valid_chan.freq <= 1.0)
|
|
{
|
|
mem_caps = NULL;
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: valChan Freq = %f\n", __func__,
|
|
valid_chan.freq);
|
|
|
|
/* Out of Range, or empty */
|
|
if (!mem_caps)
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
/* set to usable vfo if needed */
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/* Restore to VFO mode or leave in Memory Mode */
|
|
switch (vfo)
|
|
{
|
|
case RIG_VFO_A:
|
|
case RIG_VFO_MAIN:
|
|
/* Jump back from memory channel */
|
|
restore_vfo = TRUE;
|
|
break;
|
|
|
|
case RIG_VFO_MEM:
|
|
/* Jump from channel to channel in memory mode */
|
|
restore_vfo = FALSE;
|
|
break;
|
|
|
|
case RIG_VFO_B:
|
|
case RIG_VFO_SUB:
|
|
default:
|
|
/* Only works with VFO A */
|
|
RETURNFUNC(-RIG_ENTARGET);
|
|
}
|
|
|
|
/* Set Memory Channel Number ************** */
|
|
rig_debug(RIG_DEBUG_TRACE, "channel_num = %d, vfo = %s\n", ch, rig_strvfo(vfo));
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC%03d%c", ch, cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
priv->question_mark_response_means_rejected = 1;
|
|
err = newcat_set_cmd(rig);
|
|
priv->question_mark_response_means_rejected = 0;
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/* Restore VFO even if setting to blank memory channel */
|
|
if (restore_vfo)
|
|
{
|
|
err = newcat_vfomem_toggle(rig);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_get_mem(RIG *rig, vfo_t vfo, int *ch)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, "MC"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC%c", cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
/* Get Memory Channel Number */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
*ch = atoi(priv->ret_data + 2);
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
int newcat_vfo_op(RIG *rig, vfo_t vfo, vfo_op_t op)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
|
|
/* Set Main or SUB vfo */
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
switch (op)
|
|
{
|
|
case RIG_OP_TUNE:
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "AC002%c", cat_term);
|
|
break;
|
|
|
|
case RIG_OP_CPY:
|
|
if (newcat_is_rig(rig, RIG_MODEL_FT450))
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VV%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "AB%c", cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_OP_XCHG:
|
|
case RIG_OP_TOGGLE:
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SV%c", cat_term);
|
|
break;
|
|
|
|
case RIG_OP_UP:
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "UP%c", cat_term);
|
|
break;
|
|
|
|
case RIG_OP_DOWN:
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "DN%c", cat_term);
|
|
break;
|
|
|
|
case RIG_OP_BAND_UP:
|
|
if (main_sub_vfo == 1)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BU1%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BU0%c", cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_OP_BAND_DOWN:
|
|
if (main_sub_vfo == 1)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BD1%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BD0%c", cat_term);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_OP_FROM_VFO:
|
|
/* VFOA ! */
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "AM%c", cat_term);
|
|
break;
|
|
|
|
case RIG_OP_TO_VFO:
|
|
/* VFOA ! */
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MA%c", cat_term);
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
RETURNFUNC(newcat_set_cmd(rig));
|
|
}
|
|
|
|
|
|
int newcat_scan(RIG *rig, vfo_t vfo, scan_t scan, int ch)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_set_trn(RIG *rig, int trn)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char c;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, "AI"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (trn == RIG_TRN_OFF)
|
|
{
|
|
c = '0';
|
|
}
|
|
else
|
|
{
|
|
c = '1';
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "AI%c%c", c, cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "cmd_str = %s\n", priv->cmd_str);
|
|
|
|
RETURNFUNC(newcat_set_cmd(rig));
|
|
}
|
|
|
|
|
|
int newcat_get_trn(RIG *rig, int *trn)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char c;
|
|
char command[] = "AI";
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c", command, cat_term);
|
|
|
|
/* Get Auto Information */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
// if we failed to get AI we turn it off and try again
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s0%c", command, cat_term);
|
|
hl_usleep(500 * 1000); // is 500ms enough for the rig to stop sending info?
|
|
newcat_set_cmd(rig); // don't care about any errors here
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c", command, cat_term);
|
|
err = newcat_get_cmd(rig);
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
c = priv->ret_data[2];
|
|
|
|
if (c == '0')
|
|
{
|
|
*trn = RIG_TRN_OFF;
|
|
}
|
|
else
|
|
{
|
|
*trn = RIG_TRN_RIG;
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_decode_event(RIG *rig)
|
|
{
|
|
ENTERFUNC;
|
|
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
|
|
int newcat_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
|
|
{
|
|
struct rig_state *state = &rig->state;
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err, i;
|
|
int rxit;
|
|
char c_rit, c_xit, c_mode, c_vfo, c_tone, c_rptr_shift;
|
|
tone_t tone;
|
|
ncboolean restore_vfo;
|
|
chan_t *chan_list;
|
|
channel_cap_t *mem_caps = NULL;
|
|
|
|
ENTERFUNC;
|
|
|
|
|
|
if (!newcat_valid_command(rig, "MW"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
chan_list = rig->caps->chan_list;
|
|
|
|
for (i = 0; i < HAMLIB_CHANLSTSIZ && !RIG_IS_CHAN_END(chan_list[i]); i++)
|
|
{
|
|
if (chan->channel_num >= chan_list[i].startc &&
|
|
chan->channel_num <= chan_list[i].endc &&
|
|
// writable memory types... NOT 60-METERS or READ-ONLY channels
|
|
(chan_list[i].type == RIG_MTYPE_MEM ||
|
|
chan_list[i].type == RIG_MTYPE_EDGE))
|
|
{
|
|
mem_caps = &chan_list[i].mem_caps;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Out of Range */
|
|
if (!mem_caps)
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
/* Set Restore to VFO or leave in memory mode */
|
|
switch (state->current_vfo)
|
|
{
|
|
case RIG_VFO_A:
|
|
case RIG_VFO_B:
|
|
/* Jump back from memory channel */
|
|
restore_vfo = TRUE;
|
|
break;
|
|
|
|
case RIG_VFO_MEM:
|
|
/* Jump from channel to channel in memory mode */
|
|
restore_vfo = FALSE;
|
|
break;
|
|
|
|
case RIG_VFO_SUB:
|
|
default:
|
|
/* Only works with VFO Main */
|
|
RETURNFUNC(-RIG_ENTARGET);
|
|
}
|
|
|
|
/* Write Memory Channel ************************* */
|
|
/* Clarifier TX, RX */
|
|
if (chan->rit)
|
|
{
|
|
rxit = chan->rit;
|
|
c_rit = '1';
|
|
c_xit = '0';
|
|
}
|
|
else if (chan->xit)
|
|
{
|
|
rxit = chan->xit;
|
|
c_rit = '0';
|
|
c_xit = '1';
|
|
}
|
|
else
|
|
{
|
|
rxit = 0;
|
|
c_rit = '0';
|
|
c_xit = '0';
|
|
}
|
|
|
|
/* MODE */
|
|
c_mode = newcat_modechar(chan->mode);
|
|
|
|
/* VFO Fixed */
|
|
c_vfo = '0';
|
|
|
|
/* CTCSS Tone / Sql */
|
|
if (chan->ctcss_tone)
|
|
{
|
|
c_tone = '2';
|
|
tone = chan->ctcss_tone;
|
|
}
|
|
else if (chan->ctcss_sql)
|
|
{
|
|
c_tone = '1';
|
|
tone = chan->ctcss_sql;
|
|
}
|
|
else
|
|
{
|
|
c_tone = '0';
|
|
tone = 0;
|
|
}
|
|
|
|
for (i = 0; rig->caps->ctcss_list[i] != 0; i++)
|
|
if (tone == rig->caps->ctcss_list[i])
|
|
{
|
|
tone = i;
|
|
|
|
if (tone > 49)
|
|
{
|
|
tone = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
/* Repeater Shift */
|
|
switch (chan->rptr_shift)
|
|
{
|
|
case RIG_RPT_SHIFT_NONE: c_rptr_shift = '0'; break;
|
|
|
|
case RIG_RPT_SHIFT_PLUS: c_rptr_shift = '1'; break;
|
|
|
|
case RIG_RPT_SHIFT_MINUS: c_rptr_shift = '2'; break;
|
|
|
|
default: c_rptr_shift = '0';
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
|
|
"MW%03d%08d%+.4d%c%c%c%c%c%02u%c%c",
|
|
chan->channel_num, (int)chan->freq, rxit, c_rit, c_xit, c_mode, c_vfo,
|
|
c_tone, tone, c_rptr_shift, cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
/* Set Memory Channel */
|
|
priv->question_mark_response_means_rejected = 1;
|
|
err = newcat_set_cmd(rig);
|
|
priv->question_mark_response_means_rejected = 0;
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/* Restore VFO ********************************** */
|
|
if (restore_vfo)
|
|
{
|
|
err = newcat_vfomem_toggle(rig);
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_get_channel(RIG *rig, vfo_t vfo, channel_t *chan, int read_only)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char *retval;
|
|
char c, c2;
|
|
int err, i;
|
|
chan_t *chan_list;
|
|
channel_cap_t *mem_caps = NULL;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, "MR"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
chan_list = rig->caps->chan_list;
|
|
|
|
for (i = 0; i < HAMLIB_CHANLSTSIZ && !RIG_IS_CHAN_END(chan_list[i]); i++)
|
|
{
|
|
if (chan->channel_num >= chan_list[i].startc &&
|
|
chan->channel_num <= chan_list[i].endc)
|
|
{
|
|
mem_caps = &chan_list[i].mem_caps;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Out of Range */
|
|
if (!mem_caps)
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "sizeof(channel_t) = %d\n", (int)sizeof(channel_t));
|
|
rig_debug(RIG_DEBUG_TRACE, "sizeof(priv->cmd_str) = %d\n",
|
|
(int)sizeof(priv->cmd_str));
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MR%03d%c", chan->channel_num,
|
|
cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
|
|
/* Get Memory Channel */
|
|
priv->question_mark_response_means_rejected = 1;
|
|
err = newcat_get_cmd(rig);
|
|
priv->question_mark_response_means_rejected = 0;
|
|
|
|
if (RIG_OK != err)
|
|
{
|
|
if (-RIG_ERJCTED == err)
|
|
{
|
|
/* Invalid channel, has not been set up, make sure freq is
|
|
0 to indicate empty channel */
|
|
chan->freq = 0.;
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/* ret_data string to channel_t struct :: this will destroy ret_data */
|
|
|
|
/* rptr_shift P10 ************************ */
|
|
retval = priv->ret_data + 25;
|
|
|
|
switch (*retval)
|
|
{
|
|
case '0': chan->rptr_shift = RIG_RPT_SHIFT_NONE; break;
|
|
|
|
case '1': chan->rptr_shift = RIG_RPT_SHIFT_PLUS; break;
|
|
|
|
case '2': chan->rptr_shift = RIG_RPT_SHIFT_MINUS; break;
|
|
|
|
default: chan->rptr_shift = RIG_RPT_SHIFT_NONE;
|
|
}
|
|
|
|
*retval = '\0';
|
|
|
|
/* CTCSS Encoding P8 ********************* */
|
|
retval = priv->ret_data + 22;
|
|
c = *retval;
|
|
|
|
/* CTCSS Tone P9 ************************* */
|
|
chan->ctcss_tone = 0;
|
|
chan->ctcss_sql = 0;
|
|
retval = priv->ret_data + 23;
|
|
i = atoi(retval);
|
|
|
|
if (c == '1')
|
|
{
|
|
chan->ctcss_sql = rig->caps->ctcss_list[i];
|
|
}
|
|
else if (c == '2')
|
|
{
|
|
chan->ctcss_tone = rig->caps->ctcss_list[i];
|
|
}
|
|
|
|
/* vfo, mem, P7 ************************** */
|
|
retval = priv->ret_data + 21;
|
|
|
|
if (*retval == '1')
|
|
{
|
|
chan->vfo = RIG_VFO_MEM;
|
|
}
|
|
else
|
|
{
|
|
chan->vfo = RIG_VFO_CURR;
|
|
}
|
|
|
|
/* MODE P6 ******************************* */
|
|
chan->width = 0;
|
|
|
|
retval = priv->ret_data + 20;
|
|
chan->mode = newcat_rmode(*retval);
|
|
|
|
if (chan->mode == RIG_MODE_NONE)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: unknown mode=%c\n", __func__, *retval);
|
|
chan->mode = RIG_MODE_LSB;
|
|
}
|
|
|
|
/* Clarifier TX P5 *********************** */
|
|
retval = priv->ret_data + 19;
|
|
c2 = *retval;
|
|
|
|
/* Clarifier RX P4 *********************** */
|
|
retval = priv->ret_data + 18;
|
|
c = *retval;
|
|
*retval = '\0';
|
|
|
|
/* Clarifier Offset P3 ******************* */
|
|
chan->rit = 0;
|
|
chan->xit = 0;
|
|
retval = priv->ret_data + 13;
|
|
|
|
if (c == '1')
|
|
{
|
|
chan->rit = atoi(retval);
|
|
}
|
|
else if (c2 == '1')
|
|
{
|
|
chan->xit = atoi(retval);
|
|
}
|
|
|
|
*retval = '\0';
|
|
|
|
/* Frequency P2 ************************** */
|
|
retval = priv->ret_data + 5;
|
|
chan->freq = atof(retval);
|
|
|
|
if (!read_only)
|
|
{
|
|
// Set rig to channel values
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
"%s: please contact hamlib mailing list to implement this\n", __func__);
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
"%s: need to know if rig updates when channel read or not\n", __func__);
|
|
RETURNFUNC(-RIG_ENIMPL);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
const char *newcat_get_info(RIG *rig)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
static char idbuf[129]; /* extra large static string array */
|
|
|
|
/* Build the command string */
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "ID;");
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
/* Get Identification Channel */
|
|
if (RIG_OK != newcat_get_cmd(rig))
|
|
{
|
|
return (NULL);
|
|
}
|
|
|
|
priv->ret_data[6] = '\0';
|
|
SNPRINTF(idbuf, sizeof(idbuf), "%s", priv->ret_data);
|
|
|
|
return (idbuf);
|
|
}
|
|
|
|
|
|
/*
|
|
* newcat_valid_command
|
|
*
|
|
* Determine whether or not the command is valid for the specified
|
|
* rig. This function should be called before sending the command
|
|
* to the rig to make it easier to differentiate invalid and illegal
|
|
* commands (for a rig).
|
|
*/
|
|
|
|
ncboolean newcat_valid_command(RIG *rig, char const *const command)
|
|
{
|
|
const struct rig_caps *caps;
|
|
int search_high;
|
|
int search_low;
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s %s\n", __func__, command);
|
|
|
|
caps = rig->caps;
|
|
|
|
if (!caps)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: Rig capabilities not valid\n", __func__);
|
|
RETURNFUNC2(FALSE);
|
|
}
|
|
|
|
/*
|
|
* Determine the type of rig from the model number. Note it is
|
|
* possible for several model variants to exist; i.e., all the
|
|
* FT-9000 variants.
|
|
*/
|
|
|
|
is_ft450 = newcat_is_rig(rig, RIG_MODEL_FT450);
|
|
is_ft891 = newcat_is_rig(rig, RIG_MODEL_FT891);
|
|
is_ft950 = newcat_is_rig(rig, RIG_MODEL_FT950);
|
|
is_ft991 = newcat_is_rig(rig, RIG_MODEL_FT991);
|
|
is_ft2000 = newcat_is_rig(rig, RIG_MODEL_FT2000);
|
|
is_ftdx9000 = newcat_is_rig(rig, RIG_MODEL_FT9000);
|
|
is_ftdx5000 = newcat_is_rig(rig, RIG_MODEL_FTDX5000);
|
|
is_ftdx1200 = newcat_is_rig(rig, RIG_MODEL_FTDX1200);
|
|
is_ftdx3000 = newcat_is_rig(rig, RIG_MODEL_FTDX3000);
|
|
is_ftdx3000dm = newcat_get_rigid(rig) == 462;
|
|
is_ftdx101d = newcat_is_rig(rig, RIG_MODEL_FTDX101D);
|
|
is_ftdx101mp = newcat_is_rig(rig, RIG_MODEL_FTDX101MP);
|
|
is_ftdx10 = newcat_is_rig(rig, RIG_MODEL_FTDX10);
|
|
|
|
if (!is_ft450 && !is_ft950 && !is_ft891 && !is_ft991 && !is_ft2000
|
|
&& !is_ftdx5000 && !is_ftdx9000 && !is_ftdx1200 && !is_ftdx3000 && !is_ftdx101d
|
|
&& !is_ftdx101mp && !is_ftdx10)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: '%s' is unknown\n", __func__, caps->model_name);
|
|
RETURNFUNC2(FALSE);
|
|
}
|
|
|
|
/*
|
|
* Make sure the command is known, and then check to make sure
|
|
* is it valid for the rig.
|
|
*/
|
|
|
|
search_low = 0;
|
|
search_high = valid_commands_count;
|
|
|
|
while (search_low <= search_high)
|
|
{
|
|
int search_test;
|
|
int search_index;
|
|
|
|
search_index = (search_low + search_high) / 2;
|
|
search_test = strcmp(valid_commands[search_index].command, command);
|
|
|
|
if (search_test > 0)
|
|
{
|
|
search_high = search_index - 1;
|
|
}
|
|
else if (search_test < 0)
|
|
{
|
|
search_low = search_index + 1;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The command is valid. Now make sure it is supported by the rig.
|
|
*/
|
|
if (is_ft450 && valid_commands[search_index].ft450)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else if (is_ft891 && valid_commands[search_index].ft891)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else if (is_ft950 && valid_commands[search_index].ft950)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else if (is_ft991 && valid_commands[search_index].ft991)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else if (is_ft2000 && valid_commands[search_index].ft2000)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else if (is_ftdx5000 && valid_commands[search_index].ft5000)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else if (is_ftdx9000 && valid_commands[search_index].ft9000)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else if (is_ftdx1200 && valid_commands[search_index].ft1200)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else if (is_ftdx3000 && valid_commands[search_index].ft3000)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else if (is_ftdx3000dm && valid_commands[search_index].ft3000)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else if (is_ftdx101d && valid_commands[search_index].ft101d)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else if (is_ftdx101mp && valid_commands[search_index].ft101mp)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else if (is_ftdx10 && valid_commands[search_index].ft10)
|
|
{
|
|
RETURNFUNC2(TRUE);
|
|
}
|
|
else
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: '%s' command '%s' not supported\n",
|
|
__func__, caps->model_name, command);
|
|
RETURNFUNC2(FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: '%s' command '%s' not valid\n",
|
|
__func__, caps->model_name, command);
|
|
RETURNFUNC2(FALSE);
|
|
}
|
|
|
|
|
|
ncboolean newcat_is_rig(RIG *rig, rig_model_t model)
|
|
{
|
|
ncboolean is_rig;
|
|
|
|
//a bit too verbose so disable this unless needed
|
|
//rig_debug(RIG_DEBUG_TRACE, "%s(%d):%s called\n", __FILE__, __LINE__, __func__);
|
|
is_rig = (model == rig->caps->rig_model) ? TRUE : FALSE;
|
|
|
|
return (is_rig); // RETURN is too verbose here
|
|
}
|
|
|
|
|
|
/*
|
|
* newcat_set_tx_vfo does not set priv->curr_vfo
|
|
* does set rig->state.tx_vfo
|
|
*/
|
|
int newcat_set_tx_vfo(RIG *rig, vfo_t tx_vfo)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char p1;
|
|
char *command = "FT";
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, "FT"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &tx_vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
switch (tx_vfo)
|
|
{
|
|
case RIG_VFO_A:
|
|
case RIG_VFO_MAIN:
|
|
p1 = '0';
|
|
break;
|
|
|
|
case RIG_VFO_B:
|
|
case RIG_VFO_SUB:
|
|
p1 = '1';
|
|
break;
|
|
|
|
case RIG_VFO_MEM:
|
|
|
|
/* VFO A */
|
|
if (priv->current_mem == NC_MEM_CHANNEL_NONE)
|
|
{
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
else /* Memory Channel mode */
|
|
{
|
|
p1 = '0';
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
/* TODO: G4WJS - FT-450 only has toggle command so not sure how to
|
|
definitively set the TX VFO (VS; doesn't seem to help
|
|
either) */
|
|
if (newcat_is_rig(rig, RIG_MODEL_FT950) ||
|
|
newcat_is_rig(rig, RIG_MODEL_FT2000) ||
|
|
newcat_is_rig(rig, RIG_MODEL_FTDX5000) ||
|
|
newcat_is_rig(rig, RIG_MODEL_FTDX1200) ||
|
|
newcat_is_rig(rig, RIG_MODEL_FT991) ||
|
|
newcat_is_rig(rig, RIG_MODEL_FTDX10) ||
|
|
newcat_is_rig(rig, RIG_MODEL_FTDX3000))
|
|
{
|
|
HAMLIB_TRACE;
|
|
p1 = p1 + 2; /* use non-Toggle commands */
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
// what other Yaeus rigs should be using this?
|
|
// The DX101D returns FT0 when in split and not transmitting
|
|
command = "ST";
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c%c", command, p1, cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "cmd_str = %s, vfo=%s\n", priv->cmd_str,
|
|
rig_strvfo(tx_vfo));
|
|
|
|
rig->state.tx_vfo = tx_vfo;
|
|
|
|
RETURNFUNC(newcat_set_cmd(rig));
|
|
}
|
|
|
|
|
|
/*
|
|
* newcat_get_tx_vfo does not set priv->curr_vfo
|
|
*/
|
|
int newcat_get_tx_vfo(RIG *rig, vfo_t *tx_vfo)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char c;
|
|
rmode_t vfo_mode;
|
|
char const *command = "FT";
|
|
|
|
ENTERFUNC;
|
|
|
|
if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
// what other Yaeus rigs should be using this?
|
|
// The DX101D returns FT0 when in split and not transmitting
|
|
command = "ST";
|
|
}
|
|
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c", command, cat_term);
|
|
|
|
/* Get TX VFO */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
c = priv->ret_data[2];
|
|
|
|
switch (c)
|
|
{
|
|
case '0':
|
|
if (rig->state.vfo_list & RIG_VFO_MAIN) { *tx_vfo = RIG_VFO_MAIN; }
|
|
else { *tx_vfo = RIG_VFO_A; }
|
|
|
|
rig->state.cache.split = 0;
|
|
break;
|
|
|
|
case '1' :
|
|
if (rig->state.vfo_list & RIG_VFO_SUB) { *tx_vfo = RIG_VFO_SUB; }
|
|
else { *tx_vfo = RIG_VFO_B; }
|
|
|
|
rig->state.cache.split = 1;
|
|
break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_ERR, "%s: Unknown tx_vfo=%c from index 2 of %s\n", __func__,
|
|
c, priv->ret_data);
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
/* Check to see if RIG is in MEM mode */
|
|
err = newcat_get_vfo_mode(rig, RIG_VFO_A, &vfo_mode);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (vfo_mode == RIG_VFO_MEM && *tx_vfo == RIG_VFO_A)
|
|
{
|
|
*tx_vfo = RIG_VFO_MEM;
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: tx_vfo = %s\n", __func__, rig_strvfo(*tx_vfo));
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_vfo_from_alias(RIG *rig, vfo_t *vfo)
|
|
{
|
|
|
|
ENTERFUNC;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: alias vfo = %s\n", __func__, rig_strvfo(*vfo));
|
|
|
|
if (*vfo == RIG_VFO_NONE)
|
|
{
|
|
int rc = rig_get_vfo(rig, vfo);
|
|
|
|
if (rc != RIG_OK)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: rig_get_vfo failed: %s\n", __func__,
|
|
rig_strvfo(*vfo));
|
|
RETURNFUNC(rc);
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: vfo==None so get vfo=%s\n", __func__,
|
|
rig_strvfo(*vfo));
|
|
}
|
|
|
|
switch (*vfo)
|
|
{
|
|
case RIG_VFO_A:
|
|
case RIG_VFO_B:
|
|
case RIG_VFO_MEM:
|
|
/* passes through */
|
|
break;
|
|
|
|
case RIG_VFO_CURR: /* RIG_VFO_RX == RIG_VFO_CURR */
|
|
case RIG_VFO_VFO:
|
|
*vfo = rig->state.current_vfo;
|
|
break;
|
|
|
|
case RIG_VFO_TX:
|
|
|
|
/* set to another vfo for split or uplink */
|
|
if (rig->state.vfo_list & RIG_VFO_MAIN)
|
|
{
|
|
*vfo = (rig->state.current_vfo == RIG_VFO_SUB) ? RIG_VFO_MAIN : RIG_VFO_SUB;
|
|
}
|
|
else
|
|
{
|
|
*vfo = (rig->state.current_vfo == RIG_VFO_B) ? RIG_VFO_A : RIG_VFO_B;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_VFO_MAIN:
|
|
*vfo = RIG_VFO_MAIN;
|
|
break;
|
|
|
|
case RIG_VFO_SUB:
|
|
*vfo = RIG_VFO_SUB;
|
|
break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_TRACE, "Unrecognized. vfo= %s\n", rig_strvfo(*vfo));
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
/*
|
|
* Found newcat_set_level() floating point math problem
|
|
* Using rigctl on FT950 I was trying to set RIG_LEVEL_COMP to 12
|
|
* I kept setting it to 11. I wrote some test software and
|
|
* found out that 0.12 * 100 = 11 with my setup.
|
|
* Compiler is gcc 4.2.4, CPU is AMD X2
|
|
* This works somewhat but Find a better way.
|
|
* The newcat_get_level() seems to work correctly.
|
|
* Terry KJ4EED
|
|
*
|
|
*/
|
|
int newcat_scale_float(int scale, float fval)
|
|
{
|
|
float f;
|
|
float fudge = 0.003;
|
|
|
|
if ((fval + fudge) > 1.0)
|
|
{
|
|
f = scale * fval;
|
|
}
|
|
else
|
|
{
|
|
f = scale * (fval + fudge);
|
|
}
|
|
|
|
return (int) f; // RETURN is too verbose here
|
|
}
|
|
|
|
|
|
int newcat_set_narrow(RIG *rig, vfo_t vfo, ncboolean narrow)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char c;
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, "NA"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
if (narrow == TRUE)
|
|
{
|
|
c = '1';
|
|
}
|
|
else
|
|
{
|
|
c = '0';
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "NA%c%c%c", main_sub_vfo, c,
|
|
cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "cmd_str = %s\n", priv->cmd_str);
|
|
|
|
RETURNFUNC(newcat_set_cmd(rig));
|
|
}
|
|
|
|
|
|
int newcat_get_narrow(RIG *rig, vfo_t vfo, ncboolean *narrow)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char c;
|
|
char command[] = "NA";
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c%c", command, main_sub_vfo,
|
|
cat_term);
|
|
|
|
/* Get NAR */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
c = priv->ret_data[3];
|
|
|
|
if (c == '1')
|
|
{
|
|
*narrow = TRUE;
|
|
}
|
|
else
|
|
{
|
|
*narrow = FALSE;
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
// returns 1 if in narrow mode 0 if not, < 0 if error
|
|
// if vfo != RIG_VFO_NONE then will use NA0 or NA1 depending on vfo Main or Sub
|
|
static int get_narrow(RIG *rig, vfo_t vfo)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int narrow = 0;
|
|
int err;
|
|
|
|
ENTERFUNC;
|
|
// find out if we're in narrow or wide mode
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "NA%c%c",
|
|
vfo == RIG_VFO_SUB ? '1' : '0', cat_term);
|
|
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (sscanf(priv->ret_data, "NA%*1d%3d", &narrow) != 1)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: unable to parse width from '%s'\n", __func__,
|
|
priv->ret_data);
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
RETURNFUNC(narrow);
|
|
}
|
|
|
|
int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
int w = 0;
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s vfo=%s, mode=%s, width=%d\n", __func__,
|
|
rig_strvfo(vfo), rig_strrmode(mode), (int)width);
|
|
|
|
if (!newcat_valid_command(rig, "SH"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
// NOTE: RIG_PASSBAND_NORMAL (0) should select the default filter width (SH00)
|
|
|
|
if (is_ft950)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
// Narrow mode must be chosen correctly before filter width
|
|
err = newcat_set_narrow(rig, vfo, width <= 500 ? TRUE : FALSE);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 0; }
|
|
else if (width <= 100) { w = 3; }
|
|
else if (width <= 200) { w = 4; }
|
|
else if (width <= 300) { w = 5; }
|
|
else if (width <= 400) { w = 6; }
|
|
else if (width <= 500) { w = 7; }
|
|
else if (width <= 800) { w = 8; }
|
|
else if (width <= 1200) { w = 9; }
|
|
else if (width <= 1400) { w = 10; }
|
|
else if (width <= 1700) { w = 11; }
|
|
else if (width <= 2000) { w = 12; }
|
|
else { w = 13; } // 2400 Hz
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
// Narrow mode must be chosen correctly before filter width
|
|
err = newcat_set_narrow(rig, vfo, width <= 1800 ? TRUE : FALSE);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 0; }
|
|
else if (width <= 200) { w = 1; }
|
|
else if (width <= 400) { w = 2; }
|
|
else if (width <= 600) { w = 3; }
|
|
else if (width <= 850) { w = 4; }
|
|
else if (width <= 1100) { w = 5; }
|
|
else if (width <= 1350) { w = 6; }
|
|
else if (width <= 1500) { w = 7; }
|
|
else if (width <= 1650) { w = 8; }
|
|
else if (width <= 1800) { w = 9; }
|
|
else if (width <= 1950) { w = 10; }
|
|
else if (width <= 2100) { w = 11; }
|
|
else if (width <= 2250) { w = 12; }
|
|
else if (width <= 2400) { w = 13; }
|
|
else if (width <= 2450) { w = 14; }
|
|
else if (width <= 2500) { w = 15; }
|
|
else if (width <= 2600) { w = 16; }
|
|
else if (width <= 2700) { w = 17; }
|
|
else if (width <= 2800) { w = 18; }
|
|
else if (width <= 2900) { w = 19; }
|
|
else { w = 20; } // 3000 Hz
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_FMN:
|
|
// Set roofing filter and narrow mode
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} // end switch(mode)
|
|
|
|
if ((err = set_roofing_filter_for_width(rig, vfo, width)) != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
if (width > 0 && width < rig_passband_normal(rig, mode))
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, TRUE);
|
|
}
|
|
else
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, FALSE);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
|
|
case RIG_MODE_FMN:
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
} // end is_ft950 */
|
|
else if (is_ft891)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
// Narrow mode must be chosen correctly before filter width
|
|
err = newcat_set_narrow(rig, vfo, width <= 500 ? TRUE : FALSE);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 0; }
|
|
else if (width <= 50) { w = 1; }
|
|
else if (width <= 100) { w = 2; }
|
|
else if (width <= 150) { w = 3; }
|
|
else if (width <= 200) { w = 4; }
|
|
else if (width <= 250) { w = 5; }
|
|
else if (width <= 300) { w = 6; }
|
|
else if (width <= 350) { w = 7; }
|
|
else if (width <= 400) { w = 8; }
|
|
else if (width <= 450) { w = 9; }
|
|
else if (width <= 500) { w = 10; }
|
|
else if (width <= 800) { w = 11; }
|
|
else if (width <= 1200) { w = 12; }
|
|
else if (width <= 1400) { w = 13; }
|
|
else if (width <= 1700) { w = 14; }
|
|
else if (width <= 2000) { w = 15; }
|
|
else if (width <= 2400) { w = 16; }
|
|
else { w = 17; } // 3000 Hz
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
// Narrow mode must be chosen correctly before filter width
|
|
err = newcat_set_narrow(rig, vfo, width <= 1800 ? TRUE : FALSE);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 0; }
|
|
else if (width <= 200) { w = 1; }
|
|
else if (width <= 400) { w = 2; }
|
|
else if (width <= 600) { w = 3; }
|
|
else if (width <= 850) { w = 4; }
|
|
else if (width <= 1100) { w = 5; }
|
|
else if (width <= 1350) { w = 6; }
|
|
else if (width <= 1500) { w = 7; }
|
|
else if (width <= 1650) { w = 8; }
|
|
else if (width <= 1800) { w = 9; }
|
|
else if (width <= 1950) { w = 10; }
|
|
else if (width <= 2100) { w = 11; }
|
|
else if (width <= 2200) { w = 12; }
|
|
else if (width <= 2300) { w = 13; }
|
|
else if (width <= 2400) { w = 14; }
|
|
else if (width <= 2500) { w = 15; }
|
|
else if (width <= 2600) { w = 16; }
|
|
else if (width <= 2700) { w = 17; }
|
|
else if (width <= 2800) { w = 18; }
|
|
else if (width <= 2900) { w = 19; }
|
|
else if (width <= 3000) { w = 20; }
|
|
else { w = 21; } // 3000 Hz
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
if (width > 0 && width < rig_passband_normal(rig, mode))
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, TRUE);
|
|
}
|
|
else
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, FALSE);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
|
|
case RIG_MODE_FMN:
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} // end switch(mode)
|
|
} // end is_ft891
|
|
else if (is_ft991)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
// Narrow mode must be chosen correctly before filter width
|
|
err = newcat_set_narrow(rig, vfo, width <= 500 ? TRUE : FALSE);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 0; }
|
|
else if (width <= 50) { w = 1; }
|
|
else if (width <= 100) { w = 2; }
|
|
else if (width <= 150) { w = 3; }
|
|
else if (width <= 200) { w = 4; }
|
|
else if (width <= 250) { w = 5; }
|
|
else if (width <= 300) { w = 6; }
|
|
else if (width <= 350) { w = 7; }
|
|
else if (width <= 400) { w = 8; }
|
|
else if (width <= 450) { w = 9; }
|
|
else if (width <= 500) { w = 10; }
|
|
else if (width <= 800) { w = 11; }
|
|
else if (width <= 1200) { w = 12; }
|
|
else if (width <= 1400) { w = 13; }
|
|
else if (width <= 1700) { w = 14; }
|
|
else if (width <= 2000) { w = 15; }
|
|
else if (width <= 2400) { w = 16; }
|
|
else { w = 17; } // 3000 Hz
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
// Narrow mode must be chosen correctly before filter width
|
|
err = newcat_set_narrow(rig, vfo, width <= 1800 ? TRUE : FALSE);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 0; }
|
|
else if (width <= 200) { w = 1; }
|
|
else if (width <= 400) { w = 2; }
|
|
else if (width <= 600) { w = 3; }
|
|
else if (width <= 850) { w = 4; }
|
|
else if (width <= 1100) { w = 5; }
|
|
else if (width <= 1350) { w = 6; }
|
|
else if (width <= 1500) { w = 7; }
|
|
else if (width <= 1650) { w = 8; }
|
|
else if (width <= 1800) { w = 9; }
|
|
else if (width <= 1950) { w = 10; }
|
|
else if (width <= 2100) { w = 11; }
|
|
else if (width <= 2200) { w = 12; }
|
|
else if (width <= 2300) { w = 13; }
|
|
else if (width <= 2400) { w = 14; }
|
|
else if (width <= 2500) { w = 15; }
|
|
else if (width <= 2600) { w = 16; }
|
|
else if (width <= 2700) { w = 17; }
|
|
else if (width <= 2800) { w = 18; }
|
|
else if (width <= 2900) { w = 19; }
|
|
else if (width <= 3000) { w = 20; }
|
|
else { w = 21; } // 3200 Hz
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM: // Only 1 passband each for AM or AMN
|
|
if (width == RIG_PASSBAND_NORMAL || width == 9000)
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, FALSE);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
|
|
case RIG_MODE_AMN:
|
|
if (width == RIG_PASSBAND_NORMAL || width == 6000)
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, TRUE);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
|
|
case RIG_MODE_FM: // Only 1 passband each for FM or FMN
|
|
if (width == RIG_PASSBAND_NORMAL || width == 16000)
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, FALSE);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
|
|
case RIG_MODE_FMN:
|
|
if (width == RIG_PASSBAND_NORMAL || width == 9000)
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, TRUE);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
|
|
case RIG_MODE_C4FM:
|
|
if (width == RIG_PASSBAND_NORMAL || width == 16000)
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, TRUE);
|
|
}
|
|
else if (width == 9000)
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, FALSE);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
|
|
case RIG_MODE_PKTFM:
|
|
if (width > 0 && width < rig_passband_normal(rig, mode))
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, TRUE);
|
|
}
|
|
else
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, FALSE);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} // end switch(mode)
|
|
} // end is_ft991
|
|
else if (is_ftdx1200 || is_ftdx3000)
|
|
{
|
|
// FTDX 1200 and FTDX 3000 have the same set of filter choices
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
// Narrow mode must be chosen correctly before filter width
|
|
err = newcat_set_narrow(rig, vfo, width <= 500 ? TRUE : FALSE);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 0; }
|
|
else if (width <= 50) { w = 1; }
|
|
else if (width <= 100) { w = 2; }
|
|
else if (width <= 150) { w = 3; }
|
|
else if (width <= 200) { w = 4; }
|
|
else if (width <= 250) { w = 5; }
|
|
else if (width <= 300) { w = 6; }
|
|
else if (width <= 350) { w = 7; }
|
|
else if (width <= 400) { w = 8; }
|
|
else if (width <= 450) { w = 9; }
|
|
else if (width <= 500) { w = 10; }
|
|
else if (width <= 800) { w = 11; }
|
|
else if (width <= 1200) { w = 12; }
|
|
else if (width <= 1400) { w = 13; }
|
|
else if (width <= 1700) { w = 14; }
|
|
else if (width <= 2000) { w = 15; }
|
|
else { w = 16; } // 2400 Hz
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
// Narrow mode must be chosen correctly before filter width
|
|
err = newcat_set_narrow(rig, vfo, width <= 1800 ? TRUE : FALSE);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 0; }
|
|
else if (width <= 200) { w = 1; }
|
|
else if (width <= 400) { w = 2; }
|
|
else if (width <= 600) { w = 3; }
|
|
else if (width <= 850) { w = 4; }
|
|
else if (width <= 1100) { w = 5; }
|
|
else if (width <= 1350) { w = 6; }
|
|
else if (width <= 1500) { w = 7; }
|
|
else if (width <= 1650) { w = 8; }
|
|
else if (width <= 1800) { w = 9; }
|
|
else if (width <= 1950) { w = 10; }
|
|
else if (width <= 2100) { w = 11; }
|
|
else if (width <= 2200) { w = 12; }
|
|
else if (width <= 2300) { w = 13; }
|
|
else if (width <= 2400) { w = 14; }
|
|
else if (width <= 2500) { w = 15; }
|
|
else if (width <= 2600) { w = 16; }
|
|
else if (width <= 2700) { w = 17; }
|
|
else if (width <= 2800) { w = 18; }
|
|
else if (width <= 2900) { w = 19; }
|
|
else if (width <= 3000) { w = 20; }
|
|
else if (width <= 3200) { w = 21; }
|
|
else if (width <= 3400) { w = 22; }
|
|
else if (width <= 3600) { w = 23; }
|
|
else if (width <= 3800) { w = 24; }
|
|
else { w = 25; } // 4000 Hz
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_AMN:
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_FMN:
|
|
// Set roofing filter and narrow mode
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} // end switch(mode)
|
|
|
|
if ((err = set_roofing_filter_for_width(rig, vfo, width)) != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_AMN:
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_FMN:
|
|
if (width > 0 && width < rig_passband_normal(rig, mode))
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, TRUE);
|
|
}
|
|
else
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, FALSE);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
}
|
|
} // end is_ftdx1200 and is_ftdx3000
|
|
else if (is_ftdx5000)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
// Narrow mode must be chosen correctly before filter width
|
|
err = newcat_set_narrow(rig, vfo, width <= 500 ? TRUE : FALSE);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 0; }
|
|
else if (width <= 50) { w = 1; }
|
|
else if (width <= 100) { w = 2; }
|
|
else if (width <= 150) { w = 3; }
|
|
else if (width <= 200) { w = 4; }
|
|
else if (width <= 250) { w = 5; }
|
|
else if (width <= 300) { w = 6; }
|
|
else if (width <= 350) { w = 7; }
|
|
else if (width <= 400) { w = 8; }
|
|
else if (width <= 450) { w = 9; }
|
|
else if (width <= 500) { w = 10; }
|
|
else if (width <= 800) { w = 11; }
|
|
else if (width <= 1200) { w = 12; }
|
|
else if (width <= 1400) { w = 13; }
|
|
else if (width <= 1700) { w = 14; }
|
|
else if (width <= 2000) { w = 15; }
|
|
else { w = 16; } // 2400 Hz
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
// Narrow mode must be chosen correctly before filter width
|
|
err = newcat_set_narrow(rig, vfo, width <= 1800 ? TRUE : FALSE);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 0; }
|
|
else if (width <= 200) { w = 1; }
|
|
else if (width <= 400) { w = 2; }
|
|
else if (width <= 600) { w = 3; }
|
|
else if (width <= 850) { w = 4; }
|
|
else if (width <= 1100) { w = 5; }
|
|
else if (width <= 1350) { w = 6; }
|
|
else if (width <= 1500) { w = 7; }
|
|
else if (width <= 1650) { w = 8; }
|
|
else if (width <= 1800) { w = 9; }
|
|
else if (width <= 1950) { w = 10; }
|
|
else if (width <= 2100) { w = 11; }
|
|
else if (width <= 2250) { w = 12; }
|
|
else if (width <= 2400) { w = 13; }
|
|
else if (width <= 2500) { w = 15; }
|
|
else if (width <= 2600) { w = 16; }
|
|
else if (width <= 2700) { w = 17; }
|
|
else if (width <= 2800) { w = 18; }
|
|
else if (width <= 2900) { w = 19; }
|
|
else if (width <= 3000) { w = 20; }
|
|
else if (width <= 3200) { w = 21; }
|
|
else if (width <= 3400) { w = 22; }
|
|
else if (width <= 3600) { w = 23; }
|
|
else if (width <= 3800) { w = 24; }
|
|
else { w = 25; } // 4000 Hz
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_AMN:
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_FMN:
|
|
// Set roofing filter and narrow mode
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} // end switch(mode)
|
|
|
|
if ((err = set_roofing_filter_for_width(rig, vfo, width)) != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_AMN:
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_FMN:
|
|
if (width > 0 && width < rig_passband_normal(rig, mode))
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, TRUE);
|
|
}
|
|
else
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, FALSE);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
}
|
|
} // end is_ftdx5000
|
|
else if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 0; }
|
|
else if (width <= 50) { w = 1; }
|
|
else if (width <= 100) { w = 2; }
|
|
else if (width <= 150) { w = 3; }
|
|
else if (width <= 200) { w = 4; }
|
|
else if (width <= 250) { w = 5; }
|
|
else if (width <= 300) { w = 6; }
|
|
else if (width <= 350) { w = 7; }
|
|
else if (width <= 400) { w = 8; }
|
|
else if (width <= 450) { w = 9; }
|
|
else if (width <= 500) { w = 10; }
|
|
else if (width <= 600) { w = 11; }
|
|
else if (width <= 800) { w = 12; }
|
|
else if (width <= 1200) { w = 13; }
|
|
else if (width <= 1400) { w = 14; }
|
|
else if (width <= 1700) { w = 15; }
|
|
else if (width <= 2000) { w = 16; }
|
|
else if (width <= 2400) { w = 17; }
|
|
else { w = 18; }
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 0; }
|
|
else if (width <= 300) { w = 1; }
|
|
else if (width <= 400) { w = 2; }
|
|
else if (width <= 600) { w = 3; }
|
|
else if (width <= 850) { w = 4; }
|
|
else if (width <= 1100) { w = 5; }
|
|
else if (width <= 1200) { w = 6; }
|
|
else if (width <= 1500) { w = 7; }
|
|
else if (width <= 1650) { w = 8; }
|
|
else if (width <= 1800) { w = 9; }
|
|
else if (width <= 1950) { w = 10; }
|
|
else if (width <= 2100) { w = 11; }
|
|
else if (width <= 2200) { w = 12; }
|
|
else if (width <= 2300) { w = 13; }
|
|
else if (width <= 2400) { w = 14; }
|
|
else if (width <= 2500) { w = 15; }
|
|
else if (width <= 2600) { w = 16; }
|
|
else if (width <= 2700) { w = 17; }
|
|
else if (width <= 2800) { w = 18; }
|
|
else if (width <= 2900) { w = 19; }
|
|
else if (width <= 3000) { w = 20; }
|
|
else if (width <= 3200) { w = 21; }
|
|
else if (width <= 3500) { w = 22; }
|
|
else { w = 23; } // 4000Hz
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_AMN:
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_FMN:
|
|
// Set roofing filter and narrow mode
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} // end switch(mode)
|
|
|
|
if ((err = set_roofing_filter_for_width(rig, vfo, width)) != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
if (width > 0 && width < rig_passband_normal(rig, mode))
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, TRUE);
|
|
}
|
|
else
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, FALSE);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
|
|
case RIG_MODE_AMN:
|
|
case RIG_MODE_FMN:
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
} // end is_ftdx101
|
|
else if (is_ft2000)
|
|
{
|
|
// We need details on the widths here, manuals lack information.
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
// Narrow mode overrides DSP filter width on FT-2000
|
|
newcat_set_narrow(rig, vfo, FALSE);
|
|
|
|
// CW bandwidth is 2400 Hz at value 16
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 16; }
|
|
else if (width <= 200) { w = 4; }
|
|
else if (width <= 500) { w = 6; }
|
|
else if (width <= 2400) { w = 16; }
|
|
else { w = 31; } // No effect?
|
|
|
|
break;
|
|
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
// Narrow mode overrides DSP filter width on FT-2000
|
|
newcat_set_narrow(rig, vfo, FALSE);
|
|
|
|
// Packet SSB bandwidth is 2400 Hz at value 31
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 31; }
|
|
else if (width <= 200) { w = 8; }
|
|
else if (width <= 500) { w = 16; }
|
|
else { w = 31; } // 2400
|
|
|
|
break;
|
|
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
// Narrow mode overrides DSP filter width on FT-2000
|
|
newcat_set_narrow(rig, vfo, FALSE);
|
|
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 16; }
|
|
else if (width <= 300) { w = 8; }
|
|
else if (width <= 500) { w = 16; }
|
|
else { w = 31; } // 2400
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
// Narrow mode overrides DSP filter width on FT-2000
|
|
newcat_set_narrow(rig, vfo, FALSE);
|
|
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 16; }
|
|
else if (width <= 1800) { w = 8; }
|
|
else if (width <= 2400) { w = 16; }
|
|
else if (width <= 3000) { w = 25; }
|
|
else { w = 31; } // 4000
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_AMN:
|
|
case RIG_MODE_FMN:
|
|
RETURNFUNC(RIG_OK);
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
if ((err = set_roofing_filter_for_width(rig, vfo, width)) != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_AMN:
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_FMN:
|
|
if (width > 0 && width < rig_passband_normal(rig, mode))
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, TRUE);
|
|
}
|
|
else
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, FALSE);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// FT-450, FTDX 9000
|
|
// We need details on the widths here, manuals lack information.
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 16; }
|
|
else if (width <= 500) { w = 6; }
|
|
else if (width <= 1800) { w = 16; }
|
|
else { w = 24; }
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
if (width == RIG_PASSBAND_NORMAL) { w = 16; }
|
|
else if (width <= 1800) { w = 8; }
|
|
else if (width <= 2400) { w = 16; }
|
|
else { w = 25; } // 3000
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
if (width > 0 && width < rig_passband_normal(rig, mode))
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, TRUE);
|
|
}
|
|
else
|
|
{
|
|
err = newcat_set_narrow(rig, vfo, FALSE);
|
|
}
|
|
|
|
RETURNFUNC(err);
|
|
|
|
case RIG_MODE_FMN:
|
|
RETURNFUNC(RIG_OK);
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} /* end switch(mode) */
|
|
|
|
} /* end else */
|
|
|
|
if (is_ftdx101d || is_ftdx101mp || is_ft891)
|
|
{
|
|
// some rigs now require the bandwidth be turned "on"
|
|
int on = is_ft891;
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SH%c%d%02d;", main_sub_vfo, on,
|
|
w);
|
|
}
|
|
else if (is_ft2000 || is_ftdx3000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SH0%02d;", w);
|
|
}
|
|
else if (is_ftdx10)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SH00%02d;", w);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SH%c%02d;", main_sub_vfo, w);
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
/* Set RX Bandwidth */
|
|
RETURNFUNC(newcat_set_cmd(rig));
|
|
}
|
|
|
|
static int set_roofing_filter(RIG *rig, vfo_t vfo, int index)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
struct newcat_priv_caps *priv_caps = (struct newcat_priv_caps *)rig->caps->priv;
|
|
struct newcat_roofing_filter *roofing_filters;
|
|
char main_sub_vfo = '0';
|
|
char roofing_filter_choice = 0;
|
|
int err;
|
|
int i;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (priv_caps == NULL)
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
roofing_filters = priv_caps->roofing_filters;
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_ROOFING)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
if (!newcat_valid_command(rig, "RF"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
for (i = 0; roofing_filters[i].index >= 0; i++)
|
|
{
|
|
struct newcat_roofing_filter *current_filter = &roofing_filters[i];
|
|
char set_value = current_filter->set_value;
|
|
|
|
if (set_value == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
roofing_filter_choice = set_value;
|
|
|
|
if (current_filter->index == index)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (roofing_filter_choice == 0)
|
|
{
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RF%c%c%c", main_sub_vfo,
|
|
roofing_filter_choice, cat_term);
|
|
|
|
priv->question_mark_response_means_rejected = 1;
|
|
err = newcat_set_cmd(rig);
|
|
priv->question_mark_response_means_rejected = 0;
|
|
|
|
if (RIG_OK != err)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
static int set_roofing_filter_for_width(RIG *rig, vfo_t vfo, int width)
|
|
{
|
|
struct newcat_priv_caps *priv_caps = (struct newcat_priv_caps *)rig->caps->priv;
|
|
int index = 0;
|
|
int i;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (priv_caps == NULL)
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
for (i = 0; i < priv_caps->roofing_filter_count; i++)
|
|
{
|
|
struct newcat_roofing_filter *current_filter = &priv_caps->roofing_filters[i];
|
|
char set_value = current_filter->set_value;
|
|
|
|
// Skip get-only values and optional filters
|
|
if (set_value == 0 || current_filter->optional)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// The last filter is always the narrowest
|
|
if (current_filter->width < width)
|
|
{
|
|
break;
|
|
}
|
|
|
|
index = current_filter->index;
|
|
}
|
|
|
|
RETURNFUNC(set_roofing_filter(rig, vfo, index));
|
|
}
|
|
|
|
static int get_roofing_filter(RIG *rig, vfo_t vfo,
|
|
struct newcat_roofing_filter **roofing_filter)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
struct newcat_priv_caps *priv_caps = (struct newcat_priv_caps *)rig->caps->priv;
|
|
struct newcat_roofing_filter *roofing_filters;
|
|
char roofing_filter_choice;
|
|
char main_sub_vfo = '0';
|
|
char rf_vfo = 'X';
|
|
int err;
|
|
int n;
|
|
int i;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (priv_caps == NULL)
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
roofing_filters = priv_caps->roofing_filters;
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_ROOFING)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RF%c%c", main_sub_vfo,
|
|
cat_term);
|
|
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
n = sscanf(priv->ret_data, "RF%c%c", &rf_vfo, &roofing_filter_choice);
|
|
|
|
if (n != 2)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
"%s: error parsing '%s' for vfo and roofing filter, got %d parsed\n", __func__,
|
|
priv->ret_data, n);
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
for (i = 0; i < priv_caps->roofing_filter_count; i++)
|
|
{
|
|
struct newcat_roofing_filter *current_filter = &roofing_filters[i];
|
|
|
|
if (current_filter->get_value == roofing_filter_choice)
|
|
{
|
|
*roofing_filter = current_filter;
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
"%s: Expected a valid roofing filter but got %c from '%s'\n", __func__,
|
|
roofing_filter_choice, priv->ret_data);
|
|
|
|
RETURNFUNC(RIG_EPROTO);
|
|
}
|
|
|
|
int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
int w;
|
|
int sh_command_valid = 1;
|
|
int narrow = 0;
|
|
char cmd[] = "SH";
|
|
char main_sub_vfo = '0';
|
|
|
|
ENTERFUNC;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s vfo=%s, mode=%s\n", __func__,
|
|
rig_strvfo(vfo), rig_strrmode(mode));
|
|
|
|
if (!newcat_valid_command(rig, cmd))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
err = newcat_set_vfo_from_alias(rig, &vfo);
|
|
|
|
if (err < 0)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
if (is_ft950 || is_ftdx5000 || is_ftdx3000)
|
|
{
|
|
// Some Yaesu rigs cannot query SH in modes such as AM/FM
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_FMN:
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_AMN:
|
|
case RIG_MODE_PKTAM:
|
|
sh_command_valid = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
|
|
{
|
|
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
}
|
|
|
|
if (sh_command_valid)
|
|
{
|
|
if (is_ft2000 || is_ftdx10 || is_ftdx3000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s0%c", cmd, cat_term);
|
|
}
|
|
else
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c%c", cmd, main_sub_vfo,
|
|
cat_term);
|
|
}
|
|
|
|
err = newcat_get_cmd(rig);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
|
|
w = 0; // use default in case of error
|
|
|
|
if (strlen(priv->ret_data) == 7)
|
|
{
|
|
int on;
|
|
// do we need to pay attention to the Main/Sub here?
|
|
int n = sscanf(priv->ret_data, "SH%*1d%1d%3d", &on, &w);
|
|
|
|
if (n != 2)
|
|
{
|
|
err = -RIG_EPROTO;
|
|
}
|
|
|
|
#if 0 // this may apply to another Yaesu rig
|
|
|
|
if (n == 2)
|
|
{
|
|
if (!on) { w = 0; }
|
|
}
|
|
else
|
|
{
|
|
err = -RIG_EPROTO;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
else if (strlen(priv->ret_data) == 6)
|
|
{
|
|
int n = sscanf(priv->ret_data, "SH%3d", &w);
|
|
|
|
if (n != 1) { err = -RIG_EPROTO; }
|
|
}
|
|
else
|
|
{
|
|
err = -RIG_EPROTO;
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: w=%d\n", __func__, w);
|
|
|
|
if (err != RIG_OK)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: unable to parse width from '%s'\n", __func__,
|
|
priv->ret_data);
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Some Yaesu rigs cannot query filter width using SH command in modes such as AM/FM
|
|
w = 0;
|
|
}
|
|
|
|
if (is_ft950)
|
|
{
|
|
if ((narrow = get_narrow(rig, RIG_VFO_MAIN)) < 0)
|
|
{
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
switch (w)
|
|
{
|
|
case 0:
|
|
*width = narrow ? 300 : 500;
|
|
break;
|
|
|
|
case 3: *width = 100; break;
|
|
|
|
case 4: *width = 200; break;
|
|
|
|
case 5: *width = 300; break;
|
|
|
|
case 6: *width = 400; break;
|
|
|
|
case 7: *width = 5000; break;
|
|
|
|
case 8: *width = 800; break;
|
|
|
|
case 9: *width = 1200; break;
|
|
|
|
case 10: *width = 1400; break;
|
|
|
|
case 11: *width = 1700; break;
|
|
|
|
case 12: *width = 2000; break;
|
|
|
|
case 13: *width = 2400; break;
|
|
|
|
default: RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
switch (w)
|
|
{
|
|
case 0:
|
|
*width = narrow ? 1800 : 2400;
|
|
break;
|
|
|
|
case 1: *width = 200; break;
|
|
|
|
case 2: *width = 400; break;
|
|
|
|
case 3: *width = 600; break;
|
|
|
|
case 4: *width = 850; break;
|
|
|
|
case 5: *width = 1100; break;
|
|
|
|
case 6: *width = 1350; break;
|
|
|
|
case 7: *width = 1500; break;
|
|
|
|
case 8: *width = 1650; break;
|
|
|
|
case 9: *width = 1800; break;
|
|
|
|
case 10: *width = 1950; break;
|
|
|
|
case 11: *width = 2100; break;
|
|
|
|
case 12: *width = 2250; break;
|
|
|
|
case 13: *width = 2400; break;
|
|
|
|
case 14: *width = 2450; break;
|
|
|
|
case 15: *width = 2500; break;
|
|
|
|
case 16: *width = 2600; break;
|
|
|
|
case 17: *width = 2700; break;
|
|
|
|
case 18: *width = 2800; break;
|
|
|
|
case 19: *width = 2900; break;
|
|
|
|
case 20: *width = 3000; break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
*width = narrow ? 6000 : 9000;
|
|
break;
|
|
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_FM:
|
|
*width = narrow ? 9000 : 16000;
|
|
break;
|
|
|
|
case RIG_MODE_FMN:
|
|
*width = 9000;
|
|
break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_ERR, "%s: unknown mode=%s\n", __func__, rig_strrmode(mode));
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} /* end switch(mode) */
|
|
|
|
} /* end if is_ft950 */
|
|
else if (is_ft891)
|
|
{
|
|
if ((narrow = get_narrow(rig, vfo)) < 0)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: error narrow < 0, narrow=%d\n", __func__, narrow);
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
switch (w)
|
|
{
|
|
case 0:
|
|
if (mode == RIG_MODE_CW || mode == RIG_MODE_CWR)
|
|
{
|
|
*width = narrow ? 500 : 2400;
|
|
}
|
|
else
|
|
{
|
|
*width = narrow ? 300 : 500;
|
|
}
|
|
|
|
break;
|
|
|
|
case 1: *width = 50; break;
|
|
|
|
case 2: *width = 100; break;
|
|
|
|
case 3: *width = 150; break;
|
|
|
|
case 4: *width = 200; break;
|
|
|
|
case 5: *width = 250; break;
|
|
|
|
case 6: *width = 300; break;
|
|
|
|
case 7: *width = 350; break;
|
|
|
|
case 8: *width = 400; break;
|
|
|
|
case 9: *width = 450; break;
|
|
|
|
case 10: *width = 500; break;
|
|
|
|
case 11: *width = 800; break;
|
|
|
|
case 12: *width = 1200; break;
|
|
|
|
case 13: *width = 1400; break;
|
|
|
|
case 14: *width = 1700; break;
|
|
|
|
case 15: *width = 2000; break;
|
|
|
|
case 16: *width = 2400; break;
|
|
|
|
case 17: *width = 3000; break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_ERR, "%s: unknown w=%d\n", __func__, w);
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
switch (w)
|
|
{
|
|
case 0: *width = narrow ? 1500 : 2400; break;
|
|
|
|
case 1: *width = 200; break;
|
|
|
|
case 2: *width = 400; break;
|
|
|
|
case 3: *width = 600; break;
|
|
|
|
case 4: *width = 850; break;
|
|
|
|
case 5: *width = 1100; break;
|
|
|
|
case 6: *width = 1350; break;
|
|
|
|
case 7: *width = 1500; break;
|
|
|
|
case 8: *width = 1650; break;
|
|
|
|
case 9: *width = 1800; break;
|
|
|
|
case 10: *width = 1950; break;
|
|
|
|
case 11: *width = 2100; break;
|
|
|
|
case 12: *width = 2200; break;
|
|
|
|
case 13: *width = 2300; break;
|
|
|
|
case 14: *width = 2400; break;
|
|
|
|
case 15: *width = 2500; break;
|
|
|
|
case 16: *width = 2600; break;
|
|
|
|
case 17: *width = 2700; break;
|
|
|
|
case 18: *width = 2800; break;
|
|
|
|
case 19: *width = 2900; break;
|
|
|
|
case 20: *width = 3000; break;
|
|
|
|
case 21: *width = 3200; break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_ERR, "%s: unknown mode=%s\n", __func__, rig_strrmode(mode));
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_FMN:
|
|
*width = 9000;
|
|
break;
|
|
|
|
case RIG_MODE_AMN:
|
|
*width = 6000;
|
|
break;
|
|
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
*width = 16000;
|
|
break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_ERR, "%s: unknown mode=%s\n", __func__, rig_strrmode(mode));
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} /* end switch(mode) */
|
|
|
|
} /* end if is_ft891 */
|
|
else if (is_ft991)
|
|
{
|
|
// some modes are fixed and can't be queried with "NA0"
|
|
if (mode != RIG_MODE_C4FM && mode != RIG_MODE_PKTFM && mode != RIG_MODE_PKTFMN
|
|
&& (narrow = get_narrow(rig, vfo)) < 0)
|
|
{
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
narrow = 0;
|
|
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
switch (w)
|
|
{
|
|
case 0:
|
|
if (mode == RIG_MODE_CW || mode == RIG_MODE_CWR)
|
|
{
|
|
*width = narrow ? 500 : 2400;
|
|
}
|
|
else
|
|
{
|
|
*width = narrow ? 300 : 500;
|
|
}
|
|
|
|
break;
|
|
|
|
case 1: *width = 50; break;
|
|
|
|
case 2: *width = 100; break;
|
|
|
|
case 3: *width = 150; break;
|
|
|
|
case 4: *width = 200; break;
|
|
|
|
case 5: *width = 250; break;
|
|
|
|
case 6: *width = 300; break;
|
|
|
|
case 7: *width = 350; break;
|
|
|
|
case 8: *width = 400; break;
|
|
|
|
case 9: *width = 450; break;
|
|
|
|
case 10: *width = 500; break;
|
|
|
|
case 11: *width = 800; break;
|
|
|
|
case 12: *width = 1200; break;
|
|
|
|
case 13: *width = 1400; break;
|
|
|
|
case 14: *width = 1700; break;
|
|
|
|
case 15: *width = 2000; break;
|
|
|
|
case 16: *width = 2400; break;
|
|
|
|
case 17: *width = 3000; break;
|
|
|
|
default: RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
switch (w)
|
|
{
|
|
case 0: *width = narrow ? 1500 : 2400; break;
|
|
|
|
case 1: *width = 200; break;
|
|
|
|
case 2: *width = 400; break;
|
|
|
|
case 3: *width = 600; break;
|
|
|
|
case 4: *width = 850; break;
|
|
|
|
case 5: *width = 1100; break;
|
|
|
|
case 6: *width = 1350; break;
|
|
|
|
case 7: *width = 1500; break;
|
|
|
|
case 8: *width = 1650; break;
|
|
|
|
case 9: *width = 1800; break;
|
|
|
|
case 10: *width = 1950; break;
|
|
|
|
case 11: *width = 2100; break;
|
|
|
|
case 12: *width = 2200; break;
|
|
|
|
case 13: *width = 2300; break;
|
|
|
|
case 14: *width = 2400; break;
|
|
|
|
case 15: *width = 2500; break;
|
|
|
|
case 16: *width = 2600; break;
|
|
|
|
case 17: *width = 2700; break;
|
|
|
|
case 18: *width = 2800; break;
|
|
|
|
case 19: *width = 2900; break;
|
|
|
|
case 20: *width = 3000; break;
|
|
|
|
case 21: *width = 3200; break;
|
|
|
|
default: RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_FMN:
|
|
*width = 9000;
|
|
break;
|
|
|
|
case RIG_MODE_AMN:
|
|
*width = 6000;
|
|
break;
|
|
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_C4FM:
|
|
case RIG_MODE_PKTFM:
|
|
*width = 16000;
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} /* end switch(mode) */
|
|
|
|
} /* end if is_ft991 */
|
|
else if (is_ftdx1200 || is_ftdx3000)
|
|
{
|
|
if ((narrow = get_narrow(rig, RIG_VFO_MAIN)) < 0)
|
|
{
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
switch (w)
|
|
{
|
|
case 0:
|
|
*width = narrow ? 500 : 2400;
|
|
break;
|
|
|
|
case 1: *width = 50; break;
|
|
|
|
case 2: *width = 100; break;
|
|
|
|
case 3: *width = 150; break;
|
|
|
|
case 4: *width = 200; break;
|
|
|
|
case 5: *width = 250; break;
|
|
|
|
case 6: *width = 300; break;
|
|
|
|
case 7: *width = 350; break;
|
|
|
|
case 8: *width = 400; break;
|
|
|
|
case 9: *width = 450; break;
|
|
|
|
case 10: *width = 500; break;
|
|
|
|
case 11: *width = 800; break;
|
|
|
|
case 12: *width = 1200; break;
|
|
|
|
case 13: *width = 1400; break;
|
|
|
|
case 14: *width = 1700; break;
|
|
|
|
case 15: *width = 2000; break;
|
|
|
|
case 16: *width = 2400; break;
|
|
|
|
default: RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
switch (w)
|
|
{
|
|
case 0:
|
|
*width = narrow ? 1500 : 2400;
|
|
break;
|
|
|
|
case 1: *width = 200; break;
|
|
|
|
case 2: *width = 400; break;
|
|
|
|
case 3: *width = 600; break;
|
|
|
|
case 4: *width = 850; break;
|
|
|
|
case 5: *width = 1100; break;
|
|
|
|
case 6: *width = 1350; break;
|
|
|
|
case 7: *width = 1500; break;
|
|
|
|
case 8: *width = 1650; break;
|
|
|
|
case 9: *width = 1800; break;
|
|
|
|
case 10: *width = 1950; break;
|
|
|
|
case 11: *width = 2100; break;
|
|
|
|
case 12: *width = 2250; break;
|
|
|
|
case 13: *width = 2400; break;
|
|
|
|
case 14: *width = 2450; break;
|
|
|
|
case 15: *width = 2500; break;
|
|
|
|
case 16: *width = 2600; break;
|
|
|
|
case 17: *width = 2700; break;
|
|
|
|
case 18: *width = 2800; break;
|
|
|
|
case 19: *width = 2900; break;
|
|
|
|
case 20: *width = 3000; break;
|
|
|
|
case 21: *width = 3200; break;
|
|
|
|
case 22: *width = 3400; break;
|
|
|
|
case 23: *width = 3600; break;
|
|
|
|
case 24: *width = 3800; break;
|
|
|
|
case 25: *width = 4000; break;
|
|
|
|
default: RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
*width = narrow ? 6000 : 9000;
|
|
break;
|
|
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_FM:
|
|
*width = narrow ? 9000 : 16000;
|
|
break;
|
|
|
|
case RIG_MODE_FMN:
|
|
*width = 9000;
|
|
break;
|
|
|
|
case RIG_MODE_AMN:
|
|
*width = 6000;
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} /* end switch(mode) */
|
|
|
|
} /* end if is_ftdx1200 or is_ftdx3000 */
|
|
else if (is_ftdx5000)
|
|
{
|
|
if ((narrow = get_narrow(rig, RIG_VFO_MAIN)) < 0)
|
|
{
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
switch (w)
|
|
{
|
|
case 0:
|
|
*width = narrow ? 500 : 2400;
|
|
break;
|
|
|
|
case 1: *width = 50; break;
|
|
|
|
case 2: *width = 100; break;
|
|
|
|
case 3: *width = 150; break;
|
|
|
|
case 4: *width = 200; break;
|
|
|
|
case 5: *width = 250; break;
|
|
|
|
case 6: *width = 300; break;
|
|
|
|
case 7: *width = 350; break;
|
|
|
|
case 8: *width = 400; break;
|
|
|
|
case 9: *width = 450; break;
|
|
|
|
case 10: *width = 500; break;
|
|
|
|
case 11: *width = 800; break;
|
|
|
|
case 12: *width = 1200; break;
|
|
|
|
case 13: *width = 1400; break;
|
|
|
|
case 14: *width = 1700; break;
|
|
|
|
case 15: *width = 2000; break;
|
|
|
|
case 16: *width = 2400; break;
|
|
|
|
default: RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
switch (w)
|
|
{
|
|
case 0:
|
|
*width = narrow ? 1500 : 2400;
|
|
break;
|
|
|
|
case 1: *width = 200; break;
|
|
|
|
case 2: *width = 400; break;
|
|
|
|
case 3: *width = 600; break;
|
|
|
|
case 4: *width = 850; break;
|
|
|
|
case 5: *width = 1100; break;
|
|
|
|
case 6: *width = 1350; break;
|
|
|
|
case 7: *width = 1500; break;
|
|
|
|
case 8: *width = 1650; break;
|
|
|
|
case 9: *width = 1800; break;
|
|
|
|
case 10: *width = 1950; break;
|
|
|
|
case 11: *width = 2100; break;
|
|
|
|
case 12: *width = 2250; break;
|
|
|
|
case 13: *width = 2400; break;
|
|
|
|
// 14 is not defined for FTDX 5000, but leaving here for completeness
|
|
case 14: *width = 2400; break;
|
|
|
|
case 15: *width = 2500; break;
|
|
|
|
case 16: *width = 2600; break;
|
|
|
|
case 17: *width = 2700; break;
|
|
|
|
case 18: *width = 2800; break;
|
|
|
|
case 19: *width = 2900; break;
|
|
|
|
case 20: *width = 3000; break;
|
|
|
|
case 21: *width = 3200; break;
|
|
|
|
case 22: *width = 3400; break;
|
|
|
|
case 23: *width = 3600; break;
|
|
|
|
case 24: *width = 3800; break;
|
|
|
|
case 25: *width = 4000; break;
|
|
|
|
default: RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
*width = narrow ? 6000 : 9000;
|
|
break;
|
|
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_FM:
|
|
*width = narrow ? 9000 : 16000;
|
|
break;
|
|
|
|
case RIG_MODE_FMN:
|
|
*width = 9000;
|
|
break;
|
|
|
|
case RIG_MODE_AMN:
|
|
*width = 6000;
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} /* end switch(mode) */
|
|
|
|
} /* end if is_ftdx5000 */
|
|
else if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: is_ftdx101 w=%d, mode=%s\n", __func__, w,
|
|
rig_strrmode(mode));
|
|
|
|
if (w == 0) // then we need to know the roofing filter
|
|
{
|
|
struct newcat_roofing_filter *roofing_filter;
|
|
int err = get_roofing_filter(rig, vfo, &roofing_filter);
|
|
|
|
if (err == RIG_OK)
|
|
{
|
|
*width = roofing_filter->width;
|
|
}
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
switch (w)
|
|
{
|
|
case 0: break; /* use roofing filter width */
|
|
|
|
case 1: *width = 50; break;
|
|
|
|
case 2: *width = 100; break;
|
|
|
|
case 3: *width = 150; break;
|
|
|
|
case 4: *width = 200; break;
|
|
|
|
case 5: *width = 250; break;
|
|
|
|
case 6: *width = 300; break;
|
|
|
|
case 7: *width = 350; break;
|
|
|
|
case 8: *width = 400; break;
|
|
|
|
case 9: *width = 450; break;
|
|
|
|
case 10: *width = 500; break;
|
|
|
|
case 11: *width = 600; break;
|
|
|
|
case 12: *width = 800; break;
|
|
|
|
case 13: *width = 1200; break;
|
|
|
|
case 14: *width = 1400; break;
|
|
|
|
case 15: *width = 1700; break;
|
|
|
|
case 16: *width = 2000; break;
|
|
|
|
case 17: *width = 2400; break;
|
|
|
|
case 18: *width = 3000; break;
|
|
|
|
default: RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
switch (w)
|
|
{
|
|
case 0: break; /* use roofing filter width */
|
|
|
|
case 1: *width = 300; break;
|
|
|
|
case 2: *width = 400; break;
|
|
|
|
case 3: *width = 600; break;
|
|
|
|
case 4: *width = 850; break;
|
|
|
|
case 5: *width = 1100; break;
|
|
|
|
case 6: *width = 1200; break;
|
|
|
|
case 7: *width = 1500; break;
|
|
|
|
case 8: *width = 1650; break;
|
|
|
|
case 9: *width = 1800; break;
|
|
|
|
case 10: *width = 1950; break;
|
|
|
|
case 11: *width = 2100; break;
|
|
|
|
case 12: *width = 2200; break;
|
|
|
|
case 13: *width = 2300; break;
|
|
|
|
case 14: *width = 2400; break;
|
|
|
|
case 15: *width = 2500; break;
|
|
|
|
case 16: *width = 2600; break;
|
|
|
|
case 17: *width = 2700; break;
|
|
|
|
case 18: *width = 2800; break;
|
|
|
|
case 19: *width = 2900; break;
|
|
|
|
case 20: *width = 3000; break;
|
|
|
|
case 21: *width = 3200; break;
|
|
|
|
case 22: *width = 3500; break;
|
|
|
|
case 23: *width = 4000; break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_ERR, "%s: unknown width=%d\n", __func__, w);
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
case RIG_MODE_FMN:
|
|
case RIG_MODE_PKTFMN:
|
|
*width = 9000;
|
|
break;
|
|
|
|
case RIG_MODE_AMN:
|
|
*width = 6000;
|
|
break;
|
|
|
|
case RIG_MODE_FM:
|
|
case RIG_MODE_PKTFM:
|
|
*width = 16000;
|
|
break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: bad mode\n", __func__);
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} /* end switch(mode) */
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: end if FTDX101D\n", __func__);
|
|
} /* end if is_ftdx101 */
|
|
else if (is_ft2000)
|
|
{
|
|
if ((narrow = get_narrow(rig, RIG_VFO_MAIN)) < 0)
|
|
{
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
if (w <= 4)
|
|
{
|
|
*width = 200;
|
|
}
|
|
else if (w <= 6)
|
|
{
|
|
*width = 500;
|
|
}
|
|
else if (w <= 16)
|
|
{
|
|
*width = 2400;
|
|
}
|
|
else
|
|
{
|
|
*width = 3000;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
if (w <= 8)
|
|
{
|
|
*width = 200;
|
|
}
|
|
else if (w <= 16)
|
|
{
|
|
*width = 500;
|
|
}
|
|
else
|
|
{
|
|
*width = 2400;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
if (w <= 8)
|
|
{
|
|
*width = 300;
|
|
}
|
|
else if (w <= 16)
|
|
{
|
|
*width = 500;
|
|
}
|
|
else
|
|
{
|
|
*width = 2400;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
if (w <= 8)
|
|
{
|
|
*width = 1800;
|
|
}
|
|
else if (w <= 16)
|
|
{
|
|
*width = 2400;
|
|
}
|
|
else if (w <= 25)
|
|
{
|
|
*width = 3000;
|
|
}
|
|
else
|
|
{
|
|
*width = 4000;
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
*width = narrow ? 6000 : 9000;
|
|
break;
|
|
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_FM:
|
|
*width = narrow ? 9000 : 16000;
|
|
break;
|
|
|
|
case RIG_MODE_FMN:
|
|
*width = 9000;
|
|
break;
|
|
|
|
case RIG_MODE_AMN:
|
|
*width = 6000;
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} /* end switch (mode) */
|
|
} /* end if is_ft2000 */
|
|
else
|
|
{
|
|
/* FT450, FT9000 */
|
|
switch (mode)
|
|
{
|
|
case RIG_MODE_PKTUSB:
|
|
case RIG_MODE_PKTLSB:
|
|
case RIG_MODE_RTTY:
|
|
case RIG_MODE_RTTYR:
|
|
case RIG_MODE_CW:
|
|
case RIG_MODE_CWR:
|
|
case RIG_MODE_LSB:
|
|
case RIG_MODE_USB:
|
|
if (w < 16)
|
|
{
|
|
*width = rig_passband_narrow(rig, mode);
|
|
}
|
|
else if (w > 16)
|
|
{
|
|
*width = rig_passband_wide(rig, mode);
|
|
}
|
|
else
|
|
{
|
|
*width = rig_passband_normal(rig, mode);
|
|
}
|
|
|
|
break;
|
|
|
|
case RIG_MODE_AM:
|
|
*width = narrow ? 6000 : 9000;
|
|
break;
|
|
|
|
case RIG_MODE_PKTFM:
|
|
case RIG_MODE_FM:
|
|
*width = narrow ? 9000 : 16000;
|
|
break;
|
|
|
|
case RIG_MODE_FMN:
|
|
*width = 9000;
|
|
break;
|
|
|
|
case RIG_MODE_AMN:
|
|
*width = 6000;
|
|
break;
|
|
|
|
default:
|
|
RETURNFUNC(-RIG_EINVAL);
|
|
} /* end switch (mode) */
|
|
} /* end else */
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: RETURNFUNC(RIG_OK)\n", __func__);
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_set_faststep(RIG *rig, ncboolean fast_step)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char c;
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, "FS"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (fast_step == TRUE)
|
|
{
|
|
c = '1';
|
|
}
|
|
else
|
|
{
|
|
c = '0';
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "FS%c%c", c, cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
RETURNFUNC(newcat_set_cmd(rig));
|
|
}
|
|
|
|
|
|
int newcat_get_faststep(RIG *rig, ncboolean *fast_step)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
char c;
|
|
char command[] = "FS";
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c", command, cat_term);
|
|
|
|
/* Get Fast Step */
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
c = priv->ret_data[2];
|
|
|
|
if (c == '1')
|
|
{
|
|
*fast_step = TRUE;
|
|
}
|
|
else
|
|
{
|
|
*fast_step = FALSE;
|
|
}
|
|
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
int newcat_get_rigid(RIG *rig)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
const char *s = NULL;
|
|
|
|
ENTERFUNC;
|
|
|
|
/* if first valid get */
|
|
if (priv->rig_id == NC_RIGID_NONE)
|
|
{
|
|
s = newcat_get_info(rig);
|
|
|
|
if (s != NULL)
|
|
{
|
|
s += 2; /* ID0310, jump past ID */
|
|
priv->rig_id = atoi(s);
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "rig_id = %d, idstr = %s\n", priv->rig_id,
|
|
s == NULL ? "NULL" : s);
|
|
}
|
|
else
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "rig_id = %d\n", priv->rig_id);
|
|
}
|
|
|
|
RETURNFUNC(priv->rig_id);
|
|
}
|
|
|
|
|
|
/*
|
|
* input: RIG *, vfo_t *
|
|
* output: VFO mode: RIG_VFO_VFO for VFO A or B
|
|
* RIG_VFO_MEM for VFO MEM
|
|
* return: RIG_OK or error
|
|
*/
|
|
int newcat_get_vfo_mode(RIG *rig, vfo_t vfo, rmode_t *vfo_mode)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
int offset = 0;
|
|
char *cmd = "IF";
|
|
|
|
ENTERFUNC;
|
|
|
|
if (vfo == RIG_VFO_B || vfo == RIG_VFO_SUB)
|
|
{
|
|
// OI always returns VFOB and IF always VFOA
|
|
cmd = "OI";
|
|
}
|
|
|
|
if (!newcat_valid_command(rig, cmd))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
/* Get VFO Information ****************** */
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c", cmd, cat_term);
|
|
|
|
if (RIG_OK != (err = newcat_get_cmd(rig)))
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
/* vfo, mem, P7 ************************** */
|
|
// e.g. FT450 has 27 byte IF response, FT991 has 28 byte if response (one more byte for P2 VFO A Freq)
|
|
// so we now check to ensure we know the length of the response
|
|
switch (strlen(priv->ret_data))
|
|
{
|
|
case 27: offset = 21; priv->width_frequency = 8; break;
|
|
|
|
case 28: offset = 22; priv->width_frequency = 9; break;
|
|
|
|
default:
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
"%s: incorrect length of IF response, expected 27 or 28, got %d", __func__,
|
|
(int)strlen(priv->ret_data));
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: offset=%d, width_frequency=%d\n", __func__,
|
|
offset, priv->width_frequency);
|
|
|
|
switch (priv->ret_data[offset])
|
|
{
|
|
case '0': *vfo_mode = RIG_VFO_VFO; break;
|
|
|
|
case '1': /* Memory */
|
|
case '2': /* Memory Tune */
|
|
case '3': /* Quick Memory Bank */
|
|
case '4': /* Quick Memory Bank Tune */
|
|
default:
|
|
*vfo_mode = RIG_VFO_MEM;
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: vfo mode = %s\n", __func__,
|
|
rig_strvfo(*vfo_mode));
|
|
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
|
|
/*
|
|
* Writes data and waits for response
|
|
* input: complete CAT command string including termination in cmd_str
|
|
* output: complete CAT command answer string in ret_data
|
|
* return: RIG_OK or error
|
|
*/
|
|
|
|
|
|
int newcat_vfomem_toggle(RIG *rig)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char command[] = "VM";
|
|
|
|
ENTERFUNC;
|
|
|
|
if (!newcat_valid_command(rig, command))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
/* copy set command */
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s%c", command, cat_term);
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_str = %s\n", __func__, priv->cmd_str);
|
|
|
|
RETURNFUNC(newcat_set_cmd(rig));
|
|
}
|
|
|
|
/*
|
|
* Writes a null terminated command string from priv->cmd_str to the
|
|
* CAT port and returns a response from the rig in priv->ret_data
|
|
* which is also null terminated.
|
|
*
|
|
* Honors the 'retry' capabilities field by resending the command up
|
|
* to 'retry' times until a valid response is received. In the special
|
|
* cases of receiving a valid response to a different command or the
|
|
* "?;" busy please wait response; the command is not resent but up to
|
|
* 'retry' retries to receive a valid response are made.
|
|
*/
|
|
int newcat_get_cmd(RIG *rig)
|
|
{
|
|
struct rig_state *state = &rig->state;
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int retry_count = 0;
|
|
int rc = -RIG_EPROTO;
|
|
int is_read_cmd = 0;
|
|
|
|
ENTERFUNC;
|
|
|
|
// try to cache rapid repeats of the IF command
|
|
// this is for WSJT-X/JTDX sequence of v/f/m/t
|
|
// should allow rapid repeat of any call using the IF; cmd
|
|
// Any call that changes something in the IF response should invalidate the cache
|
|
if (strcmp(priv->cmd_str, "IF;") == 0 && priv->cache_start.tv_sec != 0)
|
|
{
|
|
int cache_age_ms;
|
|
|
|
cache_age_ms = elapsed_ms(&priv->cache_start, 0);
|
|
|
|
if (cache_age_ms < 500) // 500ms cache time
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cache hit, age=%dms\n", __func__, cache_age_ms);
|
|
strcpy(priv->ret_data, priv->last_if_response);
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
// we drop through and do the real IF command
|
|
}
|
|
|
|
// any command that is read only should not expire cache
|
|
is_read_cmd =
|
|
strcmp(priv->cmd_str, "AG0;") == 0
|
|
|| strcmp(priv->cmd_str, "AG1;") == 0
|
|
|| strcmp(priv->cmd_str, "AN0;") == 0
|
|
|| strcmp(priv->cmd_str, "AN1;") == 0
|
|
|| strcmp(priv->cmd_str, "BP00;") == 0
|
|
|| strcmp(priv->cmd_str, "BP01;") == 0
|
|
|| strcmp(priv->cmd_str, "BP10;") == 0
|
|
|| strcmp(priv->cmd_str, "BP11;") == 0
|
|
|| strcmp(priv->cmd_str, "CN00;") == 0
|
|
|| strcmp(priv->cmd_str, "CN10;") == 0
|
|
|| strcmp(priv->cmd_str, "CO00;") == 0
|
|
|| strcmp(priv->cmd_str, "CO01;") == 0
|
|
|| strcmp(priv->cmd_str, "CO02;") == 0
|
|
|| strcmp(priv->cmd_str, "CO03;") == 0
|
|
|| strcmp(priv->cmd_str, "CO10;") == 0
|
|
|| strcmp(priv->cmd_str, "CO11;") == 0
|
|
|| strcmp(priv->cmd_str, "CO12;") == 0
|
|
|| strcmp(priv->cmd_str, "CO13;") == 0
|
|
|| strcmp(priv->cmd_str, "IS1;") == 0
|
|
|| strcmp(priv->cmd_str, "IS0;") == 0
|
|
|| strcmp(priv->cmd_str, "IS1;") == 0
|
|
|| strcmp(priv->cmd_str, "MD0;") == 0
|
|
|| strcmp(priv->cmd_str, "MD1;") == 0
|
|
|| strcmp(priv->cmd_str, "NA0;") == 0
|
|
|| strcmp(priv->cmd_str, "NA1;") == 0
|
|
|| strcmp(priv->cmd_str, "NB0;") == 0
|
|
|| strcmp(priv->cmd_str, "NB1;") == 0
|
|
|| strcmp(priv->cmd_str, "NL0;") == 0
|
|
|| strcmp(priv->cmd_str, "NL1;") == 0
|
|
|| strcmp(priv->cmd_str, "NR0;") == 0
|
|
|| strcmp(priv->cmd_str, "NR1;") == 0
|
|
|| strcmp(priv->cmd_str, "NR0;") == 0
|
|
|| strcmp(priv->cmd_str, "NR1;") == 0
|
|
|| strcmp(priv->cmd_str, "OI;") == 0
|
|
|| strcmp(priv->cmd_str, "OS0;") == 0
|
|
|| strcmp(priv->cmd_str, "OS0;") == 0
|
|
|| strcmp(priv->cmd_str, "OS1;") == 0
|
|
|| strcmp(priv->cmd_str, "PA0;") == 0
|
|
|| strcmp(priv->cmd_str, "PA1;") == 0
|
|
|| strcmp(priv->cmd_str, "RA0;") == 0
|
|
|| strcmp(priv->cmd_str, "RA1;") == 0
|
|
|| strcmp(priv->cmd_str, "RF0;") == 0
|
|
|| strcmp(priv->cmd_str, "RF1;") == 0
|
|
|| strcmp(priv->cmd_str, "RL0;") == 0
|
|
|| strcmp(priv->cmd_str, "RL1;") == 0
|
|
|| strncmp(priv->cmd_str, "RM", 2) == 0
|
|
|| strcmp(priv->cmd_str, "SM0;") == 0
|
|
|| strcmp(priv->cmd_str, "SM1;") == 0
|
|
|| strcmp(priv->cmd_str, "SQ0;") == 0
|
|
|| strcmp(priv->cmd_str, "SQ1;") == 0
|
|
|| strcmp(priv->cmd_str, "VT0;") == 0
|
|
|| strcmp(priv->cmd_str, "VT1;") == 0;
|
|
|
|
if (priv->cmd_str[2] !=
|
|
';' && !is_read_cmd) // then we must be setting something so we'll invalidate the cache
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cache invalidated\n", __func__);
|
|
priv->cache_start.tv_sec = 0;
|
|
}
|
|
|
|
|
|
while (rc != RIG_OK && retry_count++ <= state->rigport.retry)
|
|
{
|
|
rig_flush(&state->rigport); /* discard any unsolicited data */
|
|
|
|
if (rc != -RIG_BUSBUSY)
|
|
{
|
|
/* send the command */
|
|
rig_debug(RIG_DEBUG_TRACE, "cmd_str = %s\n", priv->cmd_str);
|
|
|
|
if (RIG_OK != (rc = write_block(&state->rigport,
|
|
(unsigned char *) priv->cmd_str,
|
|
strlen(priv->cmd_str))))
|
|
{
|
|
RETURNFUNC(rc);
|
|
}
|
|
}
|
|
|
|
/* read the reply */
|
|
if ((rc = read_string(&state->rigport, (unsigned char *) priv->ret_data,
|
|
sizeof(priv->ret_data),
|
|
&cat_term, sizeof(cat_term), 0, 1)) <= 0)
|
|
{
|
|
continue; /* usually a timeout - retry */
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: read count = %d, ret_data = %s\n",
|
|
__func__, rc, priv->ret_data);
|
|
rc = RIG_OK; /* received something */
|
|
|
|
/* Check that command termination is correct - alternative is
|
|
response is longer than the buffer */
|
|
if (cat_term != priv->ret_data[strlen(priv->ret_data) - 1])
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: Command is not correctly terminated '%s'\n",
|
|
__func__, priv->ret_data);
|
|
rc = -RIG_EPROTO; /* retry */
|
|
/* we could decrement retry_count
|
|
here but there is a danger of
|
|
infinite looping so we just use up
|
|
a retry for safety's sake */
|
|
continue;
|
|
}
|
|
|
|
/* check for error codes */
|
|
if (2 == strlen(priv->ret_data))
|
|
{
|
|
/* The following error responses are documented for Kenwood
|
|
but not for Yaesu, but at least one of them is known to
|
|
occur in that the FT-450 certainly responds to "IF;"
|
|
occasionally with "?;". The others are harmless even of
|
|
they do not occur as they are unambiguous. */
|
|
switch (priv->ret_data[0])
|
|
{
|
|
case 'N':
|
|
/* Command recognized by rig but invalid data entered. */
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: NegAck for '%s'\n", __func__, priv->cmd_str);
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
|
|
case 'O':
|
|
/* Too many characters sent without a carriage return */
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: Overflow for '%s'\n", __func__,
|
|
priv->cmd_str);
|
|
rc = -RIG_EPROTO;
|
|
break; /* retry */
|
|
|
|
case 'E':
|
|
/* Communication error */
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: Communication error for '%s'\n", __func__,
|
|
priv->cmd_str);
|
|
rc = -RIG_EIO;
|
|
break; /* retry */
|
|
|
|
case '?':
|
|
|
|
/* The ? response is ambiguous and undocumented by Yaesu, but for get commands it seems to
|
|
* indicate that the rig rejected the command because the state of the rig is not valid for the command
|
|
* or that the command parameter is invalid. Retrying the command does not fix the issue,
|
|
* as the error is caused by the an invalid combination of rig state.
|
|
*
|
|
* For example, the following cases have been observed:
|
|
* - MR and MC commands are rejected when referring to an _empty_ memory channel even
|
|
* if the channel number is in a valid range
|
|
* - BC (ANF) and RL (NR) commands fail in AM/FM modes, because they are
|
|
* supported only in SSB/CW/RTTY modes
|
|
* - MG (MICGAIN) command fails in RTTY mode, as it's a digital mode
|
|
*
|
|
* There are many more cases like these and they vary by rig model.
|
|
*
|
|
* So far, "rig busy" type situations with the ? response have not been observed for get commands.
|
|
* Followup 20201213 FTDX3000 FB; command returning ?; so do NOT abort
|
|
* see https://github.com/Hamlib/Hamlib/issues/464
|
|
*/
|
|
if (priv->question_mark_response_means_rejected)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: Command rejected by the rig (get): '%s'\n",
|
|
__func__,
|
|
priv->cmd_str);
|
|
RETURNFUNC(-RIG_ERJCTED);
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_WARN, "%s: Rig busy - retrying %d of %d: '%s'\n", __func__,
|
|
retry_count, state->rigport.retry, priv->cmd_str);
|
|
|
|
rc = -RIG_ERJCTED; /* retry */
|
|
break;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
/* verify that reply was to the command we sent */
|
|
if ((priv->ret_data[0] != priv->cmd_str[0]
|
|
|| priv->ret_data[1] != priv->cmd_str[1]))
|
|
{
|
|
/*
|
|
* TODO: When RIG_TRN is enabled, we can pass the string
|
|
* to the decoder for callback. That way we don't ignore
|
|
* any commands.
|
|
*/
|
|
rig_debug(RIG_DEBUG_ERR, "%s: wrong reply %.2s for command %.2s\n",
|
|
__func__, priv->ret_data, priv->cmd_str);
|
|
// we were using BUSBUSY but microham devices need retries
|
|
// this should be OK under all other circumstances too
|
|
//rc = -RIG_BUSBUSY; /* retry read only */
|
|
rc = -RIG_EPROTO;
|
|
}
|
|
}
|
|
|
|
// update the cache
|
|
if (strncmp(priv->cmd_str, "IF;", 3) == 0)
|
|
{
|
|
elapsed_ms(&priv->cache_start, 1);
|
|
strcpy(priv->last_if_response, priv->ret_data);
|
|
}
|
|
|
|
RETURNFUNC(rc);
|
|
}
|
|
|
|
/*
|
|
* This tries to set and read to validate the set command actually worked
|
|
* returns RIG_OK if set, -RIG_EIMPL if not implemented yet, or -RIG_EPROTO if unsuccessful
|
|
*/
|
|
int newcat_set_cmd_validate(RIG *rig)
|
|
{
|
|
struct rig_state *state = &rig->state;
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char valcmd[16];
|
|
int retries = 8;
|
|
int retry = 0;
|
|
int sleepms = 50;
|
|
int rc = -RIG_EPROTO;
|
|
|
|
ENTERFUNC;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: priv->cmd_str=%s\n", __func__, priv->cmd_str);
|
|
|
|
// For FA and FB rig.c now tries to verify the set_freq actually works
|
|
// For example the FT-2000 can't do a FA set followed by an immediate read
|
|
// We were using "ID" to verify the command but rig.c now does
|
|
// a verifcation of frequency and retries if it doesn't match
|
|
if ((strncmp(priv->cmd_str, "FA", 2) == 0) && (strlen(priv->cmd_str) > 3))
|
|
{
|
|
strcpy(valcmd, "FA;");
|
|
|
|
if (priv->rig_id == NC_RIGID_FTDX3000)
|
|
{
|
|
strcpy(valcmd, "");
|
|
}
|
|
}
|
|
else if ((strncmp(priv->cmd_str, "FB", 2) == 0) && (strlen(priv->cmd_str) > 3))
|
|
{
|
|
strcpy(valcmd, "FB;");
|
|
|
|
if (priv->rig_id == NC_RIGID_FTDX3000)
|
|
{
|
|
strcpy(valcmd, "");
|
|
}
|
|
}
|
|
else if ((strncmp(priv->cmd_str, "MD", 2) == 0) && (strlen(priv->cmd_str) > 3))
|
|
{
|
|
strcpy(valcmd, priv->cmd_str); // pull the needed part of the cmd
|
|
valcmd[3] = ';';
|
|
valcmd[4] = 0;
|
|
}
|
|
else if ((strncmp(priv->cmd_str, "TX", 2) == 0) && (strlen(priv->cmd_str) > 3))
|
|
{
|
|
strcpy(valcmd, "TX;");
|
|
}
|
|
else if ((strncmp(priv->cmd_str, "FT", 2) == 0) && (strlen(priv->cmd_str) > 3))
|
|
{
|
|
strcpy(valcmd, "FT;");
|
|
}
|
|
else if ((strncmp(priv->cmd_str, "AI", 2) == 0) && (strlen(priv->cmd_str) > 3))
|
|
{
|
|
strcpy(valcmd, "AI;");
|
|
}
|
|
else if ((strncmp(priv->cmd_str, "VS", 2) == 0) && (strlen(priv->cmd_str) > 3))
|
|
{
|
|
strcpy(valcmd, "VS;");
|
|
|
|
// Some models treat the 2nd VS as a mute request
|
|
if (is_ftdx3000 || is_ftdx9000)
|
|
{
|
|
strcpy(valcmd, "");
|
|
}
|
|
}
|
|
else if (strncmp(priv->cmd_str, "SV", 2) == 0)
|
|
{
|
|
strcpy(valcmd, ""); // nothing to validate
|
|
}
|
|
else if (strncmp(priv->cmd_str, "BA", 2) == 0)
|
|
{
|
|
strcpy(valcmd, ""); // nothing to validate
|
|
}
|
|
else if (strncmp(priv->cmd_str, "AB", 2) == 0)
|
|
{
|
|
strcpy(valcmd, ""); // nothing to validate
|
|
}
|
|
else if (strncmp(priv->cmd_str, "BS", 2) == 0)
|
|
{
|
|
strcpy(valcmd, ""); // nothing to validate
|
|
}
|
|
else if (strncmp(priv->cmd_str, "MS", 2) == 0)
|
|
{
|
|
strcpy(valcmd, ""); // nothing to validate
|
|
}
|
|
else if (strncmp(priv->cmd_str, "SH", 2) == 0)
|
|
{
|
|
// could validate with SH but different formats need to be handled
|
|
strcpy(valcmd, ""); // nothing to validate
|
|
}
|
|
else if (strncmp(priv->cmd_str, "RF", 2) == 0)
|
|
{
|
|
// could validate with RF but different formats need to be handled
|
|
strcpy(valcmd, ""); // nothing to validate
|
|
}
|
|
else if (strncmp(priv->cmd_str, "BU", 2) == 0)
|
|
{
|
|
strcpy(valcmd, "FA;"); // nothing to validate
|
|
}
|
|
else if (strncmp(priv->cmd_str, "BD", 2) == 0)
|
|
{
|
|
strcpy(valcmd, "FA;"); // nothing to validate
|
|
}
|
|
else
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: %s not implemented\n", __func__, priv->cmd_str);
|
|
RETURNFUNC(-RIG_ENIMPL);
|
|
}
|
|
|
|
while (rc != RIG_OK && retry++ < retries)
|
|
{
|
|
int bytes;
|
|
char cmd[256]; // big enough
|
|
rig_flush(&state->rigport); /* discard any unsolicited data */
|
|
SNPRINTF(cmd, sizeof(cmd), "%s%s", priv->cmd_str, valcmd);
|
|
rc = write_block(&state->rigport, (unsigned char *) cmd, strlen(cmd));
|
|
|
|
if (rc != RIG_OK) { RETURNFUNC(-RIG_EIO); }
|
|
|
|
if (strlen(valcmd) == 0) { RETURNFUNC(RIG_OK); }
|
|
|
|
bytes = read_string(&state->rigport, (unsigned char *) priv->ret_data,
|
|
sizeof(priv->ret_data),
|
|
&cat_term, sizeof(cat_term), 0, 1);
|
|
|
|
// FA and FB success is now verified in rig.c with a followup query
|
|
// so no validation is needed
|
|
if (strncmp(priv->cmd_str, "FA", 2) == 0 || strncmp(priv->cmd_str, "FB", 2))
|
|
{
|
|
return RIG_OK;
|
|
}
|
|
|
|
if (strncmp(priv->cmd_str, "FT", 2) == 0
|
|
&& strncmp(priv->ret_data, "FT", 2) == 0)
|
|
{
|
|
// FT command does not echo what's sent so we just check the basic command
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
if (strncmp(priv->cmd_str, "TX", 2) == 0
|
|
&& strncmp(priv->ret_data, "TX", 2) == 0)
|
|
{
|
|
// TX command does not echo what's sent so we just check the basic command
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
if (bytes > 0)
|
|
{
|
|
// for the BS command we can only run it once
|
|
// so we'll assume it worked
|
|
// maybe Yaeus will make this command more intelligent
|
|
if (strstr(priv->cmd_str, "BS")) { RETURNFUNC(RIG_OK); }
|
|
|
|
// if the first two chars match we are validated
|
|
if (strncmp(priv->cmd_str, "VS", 2) == 0
|
|
&& strncmp(priv->cmd_str, priv->ret_data, 2) == 0) { RETURNFUNC(RIG_OK); }
|
|
else if (strcmp(priv->cmd_str, priv->ret_data) == 0) { RETURNFUNC(RIG_OK); }
|
|
else { rc = -RIG_EPROTO; }
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_WARN, "%s: cmd validation failed, '%s'!='%s', try#%d\n",
|
|
__func__, priv->cmd_str, priv->ret_data, retry);
|
|
hl_usleep(sleepms * 1000);
|
|
}
|
|
|
|
RETURNFUNC(-RIG_EPROTO);
|
|
}
|
|
/*
|
|
* Writes a null terminated command string from priv->cmd_str to the
|
|
* CAT port that is not expected to have a response.
|
|
*
|
|
* Honors the 'retry' capabilities field by resending the command up
|
|
* to 'retry' times until a valid response is received. In the special
|
|
* cases of receiving a valid response to a different command or the
|
|
* "?;" busy please wait response; the command is not resent but up to
|
|
* 'retry' retries to receive a valid response are made.
|
|
*/
|
|
int newcat_set_cmd(RIG *rig)
|
|
{
|
|
struct rig_state *state = &rig->state;
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int retry_count = 0;
|
|
int rc = -RIG_EPROTO;
|
|
|
|
ENTERFUNC;
|
|
/* pick a basic quick query command for verification */
|
|
char const *const verify_cmd = RIG_MODEL_FT9000 == rig->caps->rig_model ?
|
|
"AI;" : "ID;";
|
|
|
|
while (rc != RIG_OK && retry_count++ <= state->rigport.retry)
|
|
{
|
|
rig_flush(&state->rigport); /* discard any unsolicited data */
|
|
/* send the command */
|
|
rig_debug(RIG_DEBUG_TRACE, "cmd_str = %s\n", priv->cmd_str);
|
|
|
|
rc = newcat_set_cmd_validate(rig);
|
|
|
|
if (rc == RIG_OK)
|
|
{
|
|
// if we were able to set and and validate we're done
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cmd_validate OK\n", __func__);
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
else if (rc == -RIG_EPROTO)
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: set_cmd_validate failed\n", __func__);
|
|
RETURNFUNC(rc);
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE,
|
|
"%s: newcat_set_cmd_validate not implemented...continuing\n", __func__);
|
|
|
|
if (RIG_OK != (rc = write_block(&state->rigport,
|
|
(unsigned char *) priv->cmd_str,
|
|
strlen(priv->cmd_str))))
|
|
{
|
|
RETURNFUNC(rc);
|
|
}
|
|
|
|
/* skip validation if high throughput is needed */
|
|
if (priv->fast_set_commands == TRUE)
|
|
{
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
// freq set and ptt are now verified in rig.c
|
|
if (strncmp(priv->cmd_str, "FA", 2) == 0
|
|
|| strncmp(priv->cmd_str, "FB", 2) == 0
|
|
|| strncmp(priv->cmd_str, "TX", 2) == 0)
|
|
{
|
|
RETURNFUNC(RIG_OK);
|
|
}
|
|
|
|
|
|
if (strncmp(priv->cmd_str, "BS", 2) == 0)
|
|
{
|
|
// the BS command needs time to do it's thing
|
|
hl_usleep(500 * 1000);
|
|
priv->cache_start.tv_sec = 0; // invalidate the cache
|
|
}
|
|
|
|
/* send the verification command */
|
|
rig_debug(RIG_DEBUG_TRACE, "cmd_str = %s\n", verify_cmd);
|
|
|
|
if (RIG_OK != (rc = write_block(&state->rigport, (unsigned char *) verify_cmd,
|
|
strlen(verify_cmd))))
|
|
{
|
|
RETURNFUNC(rc);
|
|
}
|
|
|
|
/* read the reply */
|
|
if ((rc = read_string(&state->rigport, (unsigned char *) priv->ret_data,
|
|
sizeof(priv->ret_data),
|
|
&cat_term, sizeof(cat_term), 0, 1)) <= 0)
|
|
{
|
|
continue; /* usually a timeout - retry */
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s(%d): read count = %d, ret_data = %s\n",
|
|
__func__, __LINE__, rc, priv->ret_data);
|
|
rc = RIG_OK; /* received something */
|
|
|
|
/* check for error codes */
|
|
if (2 == strlen(priv->ret_data))
|
|
{
|
|
/* The following error responses are documented for Kenwood
|
|
but not for Yaesu, but at least one of them is known to
|
|
occur in that the FT-450 certainly responds to "IF;"
|
|
occasionally with "?;". The others are harmless even of
|
|
they do not occur as they are unambiguous. */
|
|
switch (priv->ret_data[0])
|
|
{
|
|
case 'N':
|
|
/* Command recognized by rig but invalid data entered. */
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: NegAck for '%s'\n", __func__, priv->cmd_str);
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
|
|
case 'O':
|
|
/* Too many characters sent without a carriage return */
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: Overflow for '%s'\n", __func__,
|
|
priv->cmd_str);
|
|
rc = -RIG_EPROTO;
|
|
break; /* retry */
|
|
|
|
case 'E':
|
|
/* Communication error */
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: Communication error for '%s'\n", __func__,
|
|
priv->cmd_str);
|
|
rc = -RIG_EIO;
|
|
break; /* retry */
|
|
|
|
case '?':
|
|
|
|
/* The ? response is ambiguous and undocumented by Yaesu. For set commands it seems to indicate:
|
|
* 1) either that the rig is busy and the command needs to be retried
|
|
* 2) or that the rig rejected the command because the state of the rig is not valid for the command
|
|
* or that the command parameter is invalid. Retrying the command does not fix the issue
|
|
* in this case, as the error is caused by the an invalid combination of rig state.
|
|
* The latter case is consistent with behaviour of get commands.
|
|
*
|
|
* For example, the following cases have been observed:
|
|
* - MR and MC commands are rejected when referring to an _empty_ memory channel even
|
|
* if the channel number is in a valid range
|
|
* - BC (ANF) and RL (NR) commands fail in AM/FM modes, because they are
|
|
* supported only in SSB/CW/RTTY modes
|
|
* - MG (MICGAIN) command fails in RTTY mode, as it's a digital mode
|
|
*
|
|
* There are many more cases like these and they vary by rig model.
|
|
*/
|
|
if (priv->question_mark_response_means_rejected)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: Command rejected by the rig (set): '%s'\n",
|
|
__func__,
|
|
priv->cmd_str);
|
|
RETURNFUNC(-RIG_ERJCTED);
|
|
}
|
|
|
|
/* Rig busy wait please */
|
|
rig_debug(RIG_DEBUG_WARN, "%s: Rig busy - retrying: '%s'\n", __func__,
|
|
priv->cmd_str);
|
|
|
|
/* read/flush the verify command reply which should still be there */
|
|
if ((rc = read_string(&state->rigport, (unsigned char *) priv->ret_data,
|
|
sizeof(priv->ret_data),
|
|
&cat_term, sizeof(cat_term), 0, 1)) > 0)
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s(%d): read count = %d, ret_data = %s\n",
|
|
__func__, __LINE__, rc, priv->ret_data);
|
|
rc = -RIG_BUSBUSY; /* retry */
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (RIG_OK == rc)
|
|
{
|
|
/* Check that response prefix and response termination is
|
|
correct - alternative is response is longer that the
|
|
buffer */
|
|
if (strncmp(verify_cmd, priv->ret_data, strlen(verify_cmd) - 1)
|
|
|| (cat_term != priv->ret_data[strlen(priv->ret_data) - 1]))
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: Unexpected verify command response '%s'\n",
|
|
__func__, priv->ret_data);
|
|
rc = -RIG_BUSBUSY;
|
|
continue; /* retry */
|
|
}
|
|
}
|
|
}
|
|
|
|
RETURNFUNC(rc);
|
|
}
|
|
|
|
struct
|
|
{
|
|
rmode_t mode;
|
|
char modechar;
|
|
ncboolean chk_width;
|
|
} static const newcat_mode_conv[] =
|
|
{
|
|
{ RIG_MODE_LSB, '1', FALSE },
|
|
{ RIG_MODE_USB, '2', FALSE },
|
|
{ RIG_MODE_CW, '3', FALSE },
|
|
{ RIG_MODE_FM, '4', TRUE},
|
|
{ RIG_MODE_AM, '5', TRUE},
|
|
{ RIG_MODE_RTTY, '6', FALSE },
|
|
{ RIG_MODE_CWR, '7', FALSE },
|
|
{ RIG_MODE_PKTLSB, '8', FALSE },
|
|
{ RIG_MODE_RTTYR, '9', FALSE },
|
|
{ RIG_MODE_PKTFM, 'A', TRUE},
|
|
{ RIG_MODE_FMN, 'B', TRUE},
|
|
{ RIG_MODE_PKTUSB, 'C', FALSE },
|
|
{ RIG_MODE_AMN, 'D', TRUE},
|
|
{ RIG_MODE_C4FM, 'E', TRUE},
|
|
{ RIG_MODE_PKTFMN, 'F', TRUE}
|
|
};
|
|
|
|
rmode_t newcat_rmode(char mode)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof(newcat_mode_conv) / sizeof(newcat_mode_conv[0]); i++)
|
|
{
|
|
if (newcat_mode_conv[i].modechar == mode)
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: %s for %c\n", __func__,
|
|
rig_strrmode(newcat_mode_conv[i].mode), mode);
|
|
return (newcat_mode_conv[i].mode);
|
|
}
|
|
}
|
|
|
|
return (RIG_MODE_NONE);
|
|
}
|
|
|
|
char newcat_modechar(rmode_t rmode)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof(newcat_mode_conv) / sizeof(newcat_mode_conv[0]); i++)
|
|
{
|
|
if (newcat_mode_conv[i].mode == rmode)
|
|
{
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: return %c for %s\n", __func__,
|
|
newcat_mode_conv[i].modechar, rig_strrmode(rmode));
|
|
return (newcat_mode_conv[i].modechar);
|
|
}
|
|
}
|
|
|
|
return ('0');
|
|
}
|
|
|
|
rmode_t newcat_rmode_width(RIG *rig, vfo_t vfo, char mode, pbwidth_t *width)
|
|
{
|
|
ncboolean narrow;
|
|
int i;
|
|
|
|
ENTERFUNC;
|
|
|
|
*width = RIG_PASSBAND_NORMAL;
|
|
|
|
for (i = 0; i < sizeof(newcat_mode_conv) / sizeof(newcat_mode_conv[0]); i++)
|
|
{
|
|
if (newcat_mode_conv[i].modechar == mode)
|
|
{
|
|
if (newcat_mode_conv[i].chk_width == TRUE)
|
|
{
|
|
// crude fix because 991 hangs on NA0; command while in C4FM
|
|
if (newcat_is_rig(rig, RIG_MODEL_FT991))
|
|
{
|
|
if (mode == 'E')
|
|
{
|
|
*width = 16000;
|
|
}
|
|
else if (mode == 'F')
|
|
{
|
|
*width = 9000;
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_TRACE, "991A & C4FM Skip newcat_get_narrow in %s\n",
|
|
__func__);
|
|
}
|
|
else
|
|
{
|
|
if (newcat_get_narrow(rig, vfo, &narrow) != RIG_OK)
|
|
{
|
|
RETURNFUNC(newcat_mode_conv[i].mode);
|
|
}
|
|
|
|
if (narrow == TRUE)
|
|
{
|
|
*width = rig_passband_narrow(rig, mode);
|
|
}
|
|
else
|
|
{
|
|
*width = rig_passband_normal(rig, mode);
|
|
}
|
|
}
|
|
}
|
|
|
|
// don't use RETURNFUNC here as that macros expects an int for the return code
|
|
return (newcat_mode_conv[i].mode);
|
|
}
|
|
}
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s fell out the bottom %c %s\n", __func__,
|
|
mode, rig_strrmode(mode));
|
|
|
|
RETURNFUNC('0');
|
|
}
|
|
|
|
int newcat_send_voice_mem(RIG *rig, vfo_t vfo, int ch)
|
|
{
|
|
char *p1 = "0"; // newer rigs have 2 bytes where is fixed at zero e.g. FT991
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
|
|
if (!newcat_valid_command(rig, "PB"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
// we don't do any channel checking -- varies by rig -- could do it but not critical
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PB%s%d%c", p1, ch, cat_term);
|
|
RETURNFUNC2(newcat_set_cmd(rig));
|
|
}
|
|
|
|
static int newcat_set_apf_frequency(RIG *rig, vfo_t vfo, int freq)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
|
|
if (!newcat_valid_command(rig, "CO"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
// Range seems to be -250..250 Hz in 10 Hz steps
|
|
if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c3%04d%c", main_sub_vfo,
|
|
(freq + 250) / 10, cat_term);
|
|
}
|
|
else if (is_ftdx10 || is_ft991 || is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO03%04d%c", (freq + 250) / 10,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx1200)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO02%02d%c", (freq + 250) / 10,
|
|
cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC2(-RIG_ENIMPL);
|
|
}
|
|
|
|
RETURNFUNC2(newcat_set_cmd(rig));
|
|
}
|
|
|
|
static int newcat_get_apf_frequency(RIG *rig, vfo_t vfo, int *freq)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
int err;
|
|
int ret_data_len;
|
|
char *ret_data;
|
|
|
|
if (!newcat_valid_command(rig, "CO"))
|
|
{
|
|
RETURNFUNC(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c3%c", main_sub_vfo,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx10 || is_ft991 || is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO03%c", cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx1200)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO02%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC(-RIG_ENIMPL);
|
|
}
|
|
|
|
if ((err = newcat_get_cmd(rig)) != RIG_OK)
|
|
{
|
|
RETURNFUNC(err);
|
|
}
|
|
|
|
ret_data_len = strlen(priv->ret_data);
|
|
|
|
/* skip command */
|
|
ret_data = priv->ret_data + strlen(priv->cmd_str) - 1;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: ret_data='%s'\n", __func__, ret_data);
|
|
/* chop term */
|
|
priv->ret_data[ret_data_len - 1] = '\0';
|
|
|
|
int raw_value = atoi(ret_data);
|
|
|
|
// Range seems to be -250..250 Hz in 10 Hz steps
|
|
*freq = raw_value * 10 - 250;
|
|
|
|
RETURNFUNC2(RIG_OK);
|
|
}
|
|
|
|
static int newcat_set_apf_width(RIG *rig, vfo_t vfo, int choice)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
|
|
if (!newcat_valid_command(rig, "EX"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX030201%d%c", choice,
|
|
cat_term);
|
|
}
|
|
else if (is_ft991)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX111%d%c", choice, cat_term);
|
|
}
|
|
else if (is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX1201%d%c", choice, cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX112%d%c", choice, cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx1200)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX107%d%c", choice, cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC2(-RIG_ENIMPL);
|
|
}
|
|
|
|
RETURNFUNC2(newcat_set_cmd(rig));
|
|
}
|
|
|
|
static int newcat_get_apf_width(RIG *rig, vfo_t vfo, int *choice)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
int ret_data_len;
|
|
char *ret_data;
|
|
|
|
if (!newcat_valid_command(rig, "EX"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX030201%c", cat_term);
|
|
}
|
|
else if (is_ft991)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX111%c", cat_term);
|
|
}
|
|
else if (is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX1201%c", cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX112%c", cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx1200)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX107%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC2(-RIG_ENIMPL);
|
|
}
|
|
|
|
if ((err = newcat_get_cmd(rig)) != RIG_OK)
|
|
{
|
|
RETURNFUNC2(err);
|
|
}
|
|
|
|
ret_data_len = strlen(priv->ret_data);
|
|
|
|
/* skip command */
|
|
ret_data = priv->ret_data + strlen(priv->cmd_str) - 1;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: ret_data='%s'\n", __func__, ret_data);
|
|
/* chop term */
|
|
priv->ret_data[ret_data_len - 1] = '\0';
|
|
|
|
*choice = atoi(ret_data);
|
|
|
|
RETURNFUNC2(RIG_OK);
|
|
}
|
|
|
|
static int newcat_set_contour(RIG *rig, vfo_t vfo, int status)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
|
|
if (!newcat_valid_command(rig, "CO"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c0%04d%c", main_sub_vfo,
|
|
status ? 1 : 0, cat_term);
|
|
}
|
|
else if (is_ftdx10 || is_ft991 || is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO00%04d%c", status ? 1 : 0,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c0%02d%c", main_sub_vfo,
|
|
status ? 1 : 0, cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx1200 || is_ft2000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO00%02d%c", status ? 1 : 0,
|
|
cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC2(-RIG_ENIMPL);
|
|
}
|
|
|
|
RETURNFUNC2(newcat_set_cmd(rig));
|
|
}
|
|
|
|
static int newcat_get_contour(RIG *rig, vfo_t vfo, int *status)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
int err;
|
|
int ret_data_len;
|
|
char *ret_data;
|
|
int last_char_index;
|
|
|
|
if (!newcat_valid_command(rig, "CO"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c0%c", main_sub_vfo,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx10 || is_ft991 || is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO00%c", cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c0%c", main_sub_vfo,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx1200 || is_ft2000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO00%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC2(-RIG_ENIMPL);
|
|
}
|
|
|
|
if ((err = newcat_get_cmd(rig)) != RIG_OK)
|
|
{
|
|
RETURNFUNC2(err);
|
|
}
|
|
|
|
ret_data_len = strlen(priv->ret_data);
|
|
|
|
/* skip command */
|
|
ret_data = priv->ret_data + strlen(priv->cmd_str) - 1;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: ret_data='%s'\n", __func__, ret_data);
|
|
/* chop term */
|
|
priv->ret_data[ret_data_len - 1] = '\0';
|
|
|
|
last_char_index = strlen(ret_data) - 1;
|
|
|
|
*status = (ret_data[last_char_index] == '1') ? 1 : 0;
|
|
|
|
RETURNFUNC2(RIG_OK);
|
|
}
|
|
|
|
static int newcat_set_contour_frequency(RIG *rig, vfo_t vfo, int freq)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
|
|
if (!newcat_valid_command(rig, "CO"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
// Range is 10..3200 Hz
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c1%04d%c", main_sub_vfo,
|
|
freq, cat_term);
|
|
}
|
|
else if (is_ftdx10 || is_ft991 || is_ft891)
|
|
{
|
|
// Range is 10..3200 Hz
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO01%04d%c", freq, cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
// Range is 100..4000 Hz in 100 Hz steps
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c1%01d%c", main_sub_vfo,
|
|
freq / 100, cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx1200 || is_ft2000)
|
|
{
|
|
// Range is 100..4000 Hz in 100 Hz steps
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO01%02d%c", freq / 100,
|
|
cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC2(-RIG_ENIMPL);
|
|
}
|
|
|
|
RETURNFUNC2(newcat_set_cmd(rig));
|
|
}
|
|
|
|
static int newcat_get_contour_frequency(RIG *rig, vfo_t vfo, int *freq)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
char main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
|
|
int err;
|
|
int ret_data_len;
|
|
char *ret_data;
|
|
|
|
if (!newcat_valid_command(rig, "CO"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c1%c", main_sub_vfo,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx10 || is_ft991 || is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO01%c", cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO%c1%c", main_sub_vfo,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx1200 || is_ft2000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CO01%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC2(-RIG_ENIMPL);
|
|
}
|
|
|
|
if ((err = newcat_get_cmd(rig)) != RIG_OK)
|
|
{
|
|
RETURNFUNC2(err);
|
|
}
|
|
|
|
ret_data_len = strlen(priv->ret_data);
|
|
|
|
/* skip command */
|
|
ret_data = priv->ret_data + strlen(priv->cmd_str) - 1;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: ret_data='%s'\n", __func__, ret_data);
|
|
/* chop term */
|
|
priv->ret_data[ret_data_len - 1] = '\0';
|
|
|
|
int raw_value = atoi(ret_data);
|
|
|
|
if (is_ftdx101d || is_ftdx101mp || is_ftdx10 || is_ft991 || is_ft891)
|
|
{
|
|
*freq = raw_value;
|
|
}
|
|
else if (is_ftdx5000 || is_ftdx3000 || is_ftdx1200 || is_ft2000)
|
|
{
|
|
*freq = raw_value * 100;
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC2(-RIG_ENIMPL);
|
|
}
|
|
|
|
RETURNFUNC2(RIG_OK);
|
|
}
|
|
|
|
static int newcat_set_contour_level(RIG *rig, vfo_t vfo, int level)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
|
|
if (!newcat_valid_command(rig, "EX"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX030202%+03d%c", level,
|
|
cat_term);
|
|
}
|
|
else if (is_ft991)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX112%+03d%c", level, cat_term);
|
|
}
|
|
else if (is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX1202%+03d%c", level,
|
|
cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX113%+03d%c", level, cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx1200)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX108%+03d%c", level, cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC2(-RIG_ENIMPL);
|
|
}
|
|
|
|
RETURNFUNC2(newcat_set_cmd(rig));
|
|
}
|
|
|
|
static int newcat_get_contour_level(RIG *rig, vfo_t vfo, int *level)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
int ret_data_len;
|
|
char *ret_data;
|
|
|
|
if (!newcat_valid_command(rig, "EX"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX030202%c", cat_term);
|
|
}
|
|
else if (is_ft991)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX112%c", cat_term);
|
|
}
|
|
else if (is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX1202%c", cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX113%c", cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx1200)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX108%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC2(-RIG_ENIMPL);
|
|
}
|
|
|
|
if ((err = newcat_get_cmd(rig)) != RIG_OK)
|
|
{
|
|
RETURNFUNC2(err);
|
|
}
|
|
|
|
ret_data_len = strlen(priv->ret_data);
|
|
|
|
/* skip command */
|
|
ret_data = priv->ret_data + strlen(priv->cmd_str) - 1;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: ret_data='%s'\n", __func__, ret_data);
|
|
/* chop term */
|
|
priv->ret_data[ret_data_len - 1] = '\0';
|
|
|
|
*level = atoi(ret_data);
|
|
|
|
RETURNFUNC2(RIG_OK);
|
|
}
|
|
|
|
static int newcat_set_contour_width(RIG *rig, vfo_t vfo, int width)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
|
|
if (!newcat_valid_command(rig, "EX"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX030203%02d%c", width,
|
|
cat_term);
|
|
}
|
|
else if (is_ft991)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX113%02d%c", width, cat_term);
|
|
}
|
|
else if (is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX1203%02d%c", width, cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX114%02d%c", width, cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx1200)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX109%02d%c", width, cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC2(-RIG_ENIMPL);
|
|
}
|
|
|
|
RETURNFUNC2(newcat_set_cmd(rig));
|
|
}
|
|
|
|
static int newcat_get_contour_width(RIG *rig, vfo_t vfo, int *width)
|
|
{
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
int err;
|
|
int ret_data_len;
|
|
char *ret_data;
|
|
|
|
if (!newcat_valid_command(rig, "EX"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX030203%c", cat_term);
|
|
}
|
|
else if (is_ft991)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX113%c", cat_term);
|
|
}
|
|
else if (is_ft891)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX1203%c", cat_term);
|
|
}
|
|
else if (is_ftdx5000)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX114%c", cat_term);
|
|
}
|
|
else if (is_ftdx3000 || is_ftdx1200)
|
|
{
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX109%c", cat_term);
|
|
}
|
|
else
|
|
{
|
|
RETURNFUNC2(-RIG_ENIMPL);
|
|
}
|
|
|
|
if ((err = newcat_get_cmd(rig)) != RIG_OK)
|
|
{
|
|
RETURNFUNC2(err);
|
|
}
|
|
|
|
ret_data_len = strlen(priv->ret_data);
|
|
|
|
/* skip command */
|
|
ret_data = priv->ret_data + strlen(priv->cmd_str) - 1;
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: ret_data='%s'\n", __func__, ret_data);
|
|
/* chop term */
|
|
priv->ret_data[ret_data_len - 1] = '\0';
|
|
|
|
*width = atoi(ret_data);
|
|
|
|
RETURNFUNC2(RIG_OK);
|
|
}
|
|
|
|
int newcat_set_clock(RIG *rig, int year, int month, int day, int hour, int min,
|
|
int sec, double msec, int utc_offset)
|
|
{
|
|
int retval = RIG_OK;
|
|
int err;
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
|
|
if (!newcat_valid_command(rig, "DT"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "DT0%04d%02d%02d%c", year, month,
|
|
day, cat_term);
|
|
|
|
if (RIG_OK != (err = newcat_set_cmd(rig)))
|
|
{
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s:%d command err = %d\n", __func__, __LINE__,
|
|
err);
|
|
RETURNFUNC2(err);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "DT1%02d%02d%02d%c", hour, min,
|
|
sec, cat_term);
|
|
|
|
if (RIG_OK != (err = newcat_set_cmd(rig)))
|
|
{
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s:%d command err = %d\n", __func__, __LINE__,
|
|
err);
|
|
RETURNFUNC2(err);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "DT2%c%04d%c",
|
|
utc_offset >= 0 ? '+' : '-', utc_offset, cat_term);
|
|
|
|
if (RIG_OK != (err = newcat_set_cmd(rig)))
|
|
{
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s:%d command err = %d\n", __func__, __LINE__,
|
|
err);
|
|
RETURNFUNC2(err);
|
|
}
|
|
|
|
RETURNFUNC2(retval);
|
|
}
|
|
|
|
int newcat_get_clock(RIG *rig, int *year, int *month, int *day, int *hour,
|
|
int *min, int *sec, double *msec, int *utc_offset)
|
|
{
|
|
int retval = RIG_OK;
|
|
int err;
|
|
int n;
|
|
struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv;
|
|
|
|
if (!newcat_valid_command(rig, "DT"))
|
|
{
|
|
RETURNFUNC2(-RIG_ENAVAIL);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "DT0%c", cat_term);
|
|
|
|
if ((err = newcat_get_cmd(rig)) != RIG_OK)
|
|
{
|
|
RETURNFUNC2(err);
|
|
}
|
|
|
|
n = sscanf(priv->ret_data, "DT0%04d%02d%02d", year, month, day);
|
|
|
|
if (n != 3)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: DT0 unable to parse '%s'\n", __func__,
|
|
priv->ret_data);
|
|
RETURNFUNC2(-RIG_EPROTO);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "DT1%c", cat_term);
|
|
|
|
if ((err = newcat_get_cmd(rig)) != RIG_OK)
|
|
{
|
|
RETURNFUNC2(err);
|
|
}
|
|
|
|
n = sscanf(priv->ret_data, "DT1%02d%02d%02d", hour, min, sec);
|
|
|
|
if (n != 3)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: DT1 unable to parse '%s'\n", __func__,
|
|
priv->ret_data);
|
|
RETURNFUNC2(-RIG_EPROTO);
|
|
}
|
|
|
|
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "DT2%c", cat_term);
|
|
|
|
if ((err = newcat_get_cmd(rig)) != RIG_OK)
|
|
{
|
|
RETURNFUNC2(err);
|
|
}
|
|
|
|
// we keep utc_offset in HHMM format rather than converting
|
|
n = sscanf(priv->ret_data, "DT2%d", utc_offset);
|
|
|
|
if (n != 1)
|
|
{
|
|
rig_debug(RIG_DEBUG_ERR, "%s: DT2 unable to parse '%s'\n", __func__,
|
|
priv->ret_data);
|
|
RETURNFUNC2(-RIG_EPROTO);
|
|
}
|
|
|
|
RETURNFUNC2(retval);
|
|
}
|
|
|