From 31837025f2e0513d156272ba180d08702435ccaf Mon Sep 17 00:00:00 2001 From: KaComet Date: Sun, 27 Nov 2022 09:33:36 -0600 Subject: [PATCH] Add support for VFO mode in Rigctrl. Gpredict will now try to enable and use VFO mode, usally set via the --vfo command line flag in Rigctrl, when connecting to a radio. If VFO mode could not be enabled, the old style of commanding the radio is used. --- src/gtk-rig-ctrl.c | 217 +++++++++++++++++++++++++++----------- src/gtk-rig-ctrl.h | 1 + src/radio-conf.c | 12 ++- src/sat-pref-rig-editor.c | 40 ++++--- 4 files changed, 186 insertions(+), 84 deletions(-) diff --git a/src/gtk-rig-ctrl.c b/src/gtk-rig-ctrl.c index 4c14ad09..d57c8bd3 100644 --- a/src/gtk-rig-ctrl.c +++ b/src/gtk-rig-ctrl.c @@ -79,7 +79,6 @@ static gboolean check_aos_los(GtkRigCtrl * ctrl); static gboolean set_freq_simplex(GtkRigCtrl * ctrl, gint sock, gdouble freq); static gboolean get_freq_simplex(GtkRigCtrl * ctrl, gint sock, gdouble * freq); static gboolean set_freq_toggle(GtkRigCtrl * ctrl, gint sock, gdouble freq); -static gboolean set_toggle(GtkRigCtrl * ctrl, gint sock); static gboolean unset_toggle(GtkRigCtrl * ctrl, gint sock); static gboolean get_freq_toggle(GtkRigCtrl * ctrl, gint sock, gdouble * freq); static gboolean get_ptt(GtkRigCtrl * ctrl, gint sock); @@ -178,6 +177,7 @@ static void gtk_rig_ctrl_init(GtkRigCtrl * ctrl, ctrl->lastrxf = 0.0; ctrl->lasttxf = 0.0; ctrl->last_toggle_tx = -1; + ctrl->vfo_opt_supported = FALSE; } GType gtk_rig_ctrl_get_type() @@ -1489,37 +1489,94 @@ static inline gboolean check_get_response(gchar * buffback, gboolean retcode, return retcode; } -/* Setup VFOs for split operation (simplex or duplex) */ -static gboolean setup_split(GtkRigCtrl * ctrl) +/* + * Return the string for the supplied VFO. + * + * Returns a VFO string (VFOA, VFOB, Main, Sub) for the specified VFO enum if VFO mode is enabled. + * If VFO mode is not enabled, checked via the isVfoSupported argument, an empty string is returned. + */ +static gchar* vfo_str(vfo_t vfo, gboolean isVfoSupported) { + // If --VFO mode is not enabled, no need to specify a VFO. Return an empty string. + if (!isVfoSupported) + return ""; + + // If --VFO mode is enabled, return the VFO string for the provided vfo enum. + switch (vfo) { + case VFO_A: + return "VFOA"; + case VFO_B: + return "VFOB"; + case VFO_MAIN: + return "Main"; + case VFO_SUB: + return "Sub"; + default: + return "currVFO"; + } +} + +/* + * Check if the radio has the --vfo option enabled. + * + * Returns TRUE if the --vfo option is enabled, FALSE otherwise. + */ +static gboolean check_vfo_option(GtkRigCtrl * ctrl, gint sock) { gchar *buff; - gchar buffback[256]; + gchar buffback[128]; gboolean retcode; + gboolean retval = FALSE; - switch (ctrl->conf->vfoUp) - { - case VFO_A: - buff = g_strdup("S 1 VFOA\x0a"); - break; + // Send command to check if --vfo mode is enabled. + buff = g_strdup_printf("\\chk_vfo\x0a"); + retcode = send_rigctld_command(ctrl, sock, buff, buffback, 128); + retcode = check_get_response(buffback, retcode, __func__); - case VFO_B: - buff = g_strdup("S 1 VFOB\x0a"); - break; + // Check if '1' was sent back (indicating --vfo mode is enabled.) + if (retcode && (buffback[0]=='1')) + retval = TRUE; - case VFO_MAIN: - buff = g_strdup("S 1 Main\x0a"); - break; + g_free(buff); + return retval; +} - case VFO_SUB: - buff = g_strdup("S 1 Sub\x0a"); - break; +/* + * Try to enable the --vfo option for a radio if it is supported. + * + * Returns TRUE if the --vfo option has been enabled, FALSE otherwise. + */ +static gboolean enable_vfo_option(GtkRigCtrl * ctrl, gint sock) +{ + gchar *buff; + gchar buffback[128]; + gboolean retval = FALSE; - default: - sat_log_log(SAT_LOG_LEVEL_ERROR, - _("%s called but TX VFO is %d."), __func__, - ctrl->conf->vfoUp); - return FALSE; - } + buff = g_strdup_printf("\\set_vfo_opt 1\x0a"); + send_rigctld_command(ctrl, sock, buff, buffback, 128); + + // Check if --vfo mode was successfully enabled. + retval = check_vfo_option(ctrl, sock); + + g_free(buff); + return retval; +} + +/* Setup VFOs for split operation (simplex or duplex) */ +static gboolean setup_split(GtkRigCtrl * ctrl) +{ + gchar *buff; + gchar buffback[256]; + gboolean retcode; + + /* send command to enable split mode + * Example: S VFOA 1 VFOB\x0a + * S: Rigctrl set split VFO + * VFOA: Downlink vfo. Omitted if --VFO mode is not enabled in Rigctrl + * 1: Enable split (0 would disable split.) + * VFOB: Uplink vfo. + * /x0a: End of command + */ + buff = g_strdup_printf("S %s 1 %s\x0a", vfo_str(ctrl->conf->vfoDown, ctrl->vfo_opt_supported), vfo_str(ctrl->conf->vfoUp, TRUE)); retcode = send_rigctld_command(ctrl, ctrl->sock, buff, buffback, 128); g_free(buff); @@ -2252,8 +2309,13 @@ static gboolean get_ptt(GtkRigCtrl * ctrl, gint sock) if (ctrl->conf->ptt == PTT_TYPE_CAT) { - /* send command get_ptt (t) */ - buff = g_strdup_printf("t\x0a"); + /* send command to enable or disable the PTT + * Example: t VFOA 1 \x0a + * t: Rigctrl get PTT command + * VFOA: VFO to get PTT of. In this case the uplink VFO. Omitted if --VFO mode is not enabled in Rigctrl + * /x0a: End of command + */ + buff = g_strdup_printf("t %s\x0a", vfo_str(ctrl->conf->vfoUp, ctrl->vfo_opt_supported)); } else { @@ -2281,11 +2343,15 @@ static gboolean set_ptt(GtkRigCtrl * ctrl, gint sock, gboolean ptt) gchar buffback[128]; gboolean retcode; - /* send command */ - if (ptt == TRUE) - buff = g_strdup_printf("T 1\x0aq\x0a"); - else - buff = g_strdup_printf("T 0\x0aq\x0a"); + /* send command to enable or disable the PTT + * Example: T VFOA 1 \x0a + * T: Rigctrl set PTT command + * VFOA: VFO to set PTT on. In this case the uplink VFO. Omitted if --VFO mode is not enabled in Rigctrl + * 1: 1 or 0, corresponding to enable PTT and disable PTT respectively + * /x0a: End of command + */ + gchar pttChar = (ptt) ? '1' : '0'; + buff = g_strdup_printf("T %s %c\x0a", vfo_str(ctrl->conf->vfoUp, ctrl->vfo_opt_supported), pttChar); retcode = send_rigctld_command(ctrl, sock, buff, buffback, 128); g_free(buff); @@ -2363,7 +2429,14 @@ static gboolean set_freq_simplex(GtkRigCtrl * ctrl, gint sock, gdouble freq) gchar buffback[128]; gboolean retcode; - buff = g_strdup_printf("F %10.0f\x0a", freq); + /* send command to set downlink frequency + * Example: F VFOA 10000000 \x0a + * F: Rigctrl set frequency command + * VFOA: VFO to set the frequency of. In this case the downlink VFO. Omitted if --VFO mode is not enabled in Rigctrl + * 10000000: Frequency in Hz + * /x0a: End of command + */ + buff = g_strdup_printf("F %s %10.0f\x0a", vfo_str(ctrl->conf->vfoDown, ctrl->vfo_opt_supported), freq); retcode = send_rigctld_command(ctrl, sock, buff, buffback, 128); g_free(buff); @@ -2376,33 +2449,24 @@ static gboolean set_freq_simplex(GtkRigCtrl * ctrl, gint sock, gdouble freq) * * Returns TRUE if the operation was successful, FALSE otherwise */ -static gboolean set_freq_toggle(GtkRigCtrl * ctrl, gint sock, gdouble freq) -{ - gchar *buff; - gchar buffback[128]; - gboolean retcode; - - /* send command */ - buff = g_strdup_printf("I %10.0f\x0a", freq); - retcode = send_rigctld_command(ctrl, sock, buff, buffback, 128); - g_free(buff); - - return (check_set_response(buffback, retcode, __func__)); - -} - -/* - * Turn on the radios toggle mode - * - * Returns TRUE if the operation was successful - */ -static gboolean set_toggle(GtkRigCtrl * ctrl, gint sock) -{ - gchar *buff; - gchar buffback[128]; - gboolean retcode; - - buff = g_strdup_printf("S 1 %d\x0a", ctrl->conf->vfoDown); +static gboolean set_freq_toggle(GtkRigCtrl * ctrl, gint sock, gdouble freq) { + gchar * buff; + gchar buffback[128]; + gboolean retcode; + + /* send command to set uplink frequency + * Example: F VFOA 10000000 \x0a + * F: Rigctrl set frequency command. If --VFO mode is not enabled, the "I" command is used instead. + * The "I" command has to be used to set the TX frequency when not in --VFO mode. + * VFOA: VFO to set the frequency of. In this case the uplink VFO. Not used with "I" command. + * 10000000: Frequency in Hz + * /x0a: End of command + */ + if (ctrl->vfo_opt_supported) { + buff = g_strdup_printf("F %s %10.0f\x0a", vfo_str(ctrl->conf->vfoUp, TRUE), freq); + } else { + buff = g_strdup_printf("I %10.0f\x0a", freq); + } retcode = send_rigctld_command(ctrl, sock, buff, buffback, 128); g_free(buff); @@ -2421,7 +2485,15 @@ static gboolean unset_toggle(GtkRigCtrl * ctrl, gint sock) gboolean retcode; /* send command */ - buff = g_strdup_printf("S 0 %d\x0a", ctrl->conf->vfoDown); + /* send command to disable split mode + * Example: S VFOA 1 VFOB\x0a + * S: Rigctrl set split VFO + * VFOA: Downlink vfo. Omitted if --VFO mode is not enabled in Rigctrl + * 0: Disable split (1 would enable split.) + * VFOB: Uplink vfo. + * /x0a: End of command + */ + buff = g_strdup_printf("S %s 0 %s\x0a", vfo_str(ctrl->conf->vfoDown, ctrl->vfo_opt_supported), vfo_str(ctrl->conf->vfoUp, TRUE)); retcode = send_rigctld_command(ctrl, sock, buff, buffback, 128); g_free(buff); @@ -2440,7 +2512,13 @@ static gboolean get_freq_simplex(GtkRigCtrl * ctrl, gint sock, gdouble * freq) gboolean retcode; gboolean retval = TRUE; - buff = g_strdup_printf("f\x0a"); + /* send command to get downlink frequency + * Example: f VFOA \x0a + * f: Rigctrl get frequency command + * VFOA: VFO to get the frequency of. In this case the downlink VFO. Omitted if --VFO mode is not enabled in Rigctrl + * /x0a: End of command + */ + buff = g_strdup_printf("f %s\x0a", vfo_str(ctrl->conf->vfoDown, ctrl->vfo_opt_supported)); retcode = send_rigctld_command(ctrl, sock, buff, buffback, 128); retcode = check_get_response(buffback, retcode, __func__); if (retcode) @@ -2480,8 +2558,18 @@ static gboolean get_freq_toggle(GtkRigCtrl * ctrl, gint sock, gdouble * freq) return FALSE; } - /* send command */ - buff = g_strdup_printf("i\x0a"); + /* send command to set uplink frequency + * Example: f VFOA \x0a + * f: Rigctrl set frequency command. If --VFO mode is not enabled, the "i" command is used instead. + * The "I" command has to be used to get the TX frequency when not in --VFO mode. + * VFOA: VFO to get the frequency of. In this case the uplink VFO. Not used with "i" command. + * /x0a: End of command + */ + if (ctrl->vfo_opt_supported) { + buff = g_strdup_printf("f %s\x0a", vfo_str(ctrl->conf->vfoUp, TRUE)); + } else { + buff = g_strdup_printf("i\x0a"); + } retcode = send_rigctld_command(ctrl, sock, buff, buffback, 128); retcode = check_get_response(buffback, retcode, __func__); if (retcode) @@ -2739,6 +2827,7 @@ static void rigctrl_open(GtkRigCtrl * data) } else { + ctrl->vfo_opt_supported = enable_vfo_option(ctrl, ctrl->sock); switch (ctrl->conf->type) { @@ -2762,7 +2851,7 @@ static void rigctrl_open(GtkRigCtrl * data) case RIG_TYPE_TOGGLE_AUTO: case RIG_TYPE_TOGGLE_MAN: - set_toggle(ctrl, ctrl->sock); + setup_split(ctrl); ctrl->last_toggle_tx = -1; exec_toggle_cycle(ctrl); break; diff --git a/src/gtk-rig-ctrl.h b/src/gtk-rig-ctrl.h index 4e1da763..ee3a37c6 100644 --- a/src/gtk-rig-ctrl.h +++ b/src/gtk-rig-ctrl.h @@ -55,6 +55,7 @@ struct _gtk_rig_ctrl { GSList *trsplist; /*!< List of available transponders */ trsp_t *trsp; /*!< Pointer to the current transponder configuration */ gboolean trsplock; /*!< Flag indicating whether uplink and downlink are lockled */ + gboolean vfo_opt_supported; /*!< Does the rig support and have the --vfo enabled in Hamlib*/ GSList *sats; /*!< List of sats in parent module */ sat_t *target; /*!< Target satellite */ diff --git a/src/radio-conf.c b/src/radio-conf.c index 46c70c5d..6238ca20 100644 --- a/src/radio-conf.c +++ b/src/radio-conf.c @@ -199,9 +199,10 @@ gboolean radio_conf_read(radio_conf_t * conf) return FALSE; } - /* VFO up and down, only if radio is full-duplex */ - if (conf->type == RIG_TYPE_DUPLEX) - { + /* VFO up and down, only if radio is full-duplex, auto, manual */ + if ((conf->type == RIG_TYPE_DUPLEX) || + (conf->type == RIG_TYPE_TOGGLE_AUTO) || + (conf->type == RIG_TYPE_TOGGLE_MAN)) { /* downlink */ if (g_key_file_has_key(cfg, GROUP, KEY_VFO_DOWN, NULL)) { @@ -280,8 +281,9 @@ void radio_conf_save(radio_conf_t * conf) else g_key_file_set_integer(cfg, GROUP, KEY_CYCLE, conf->cycle); - if (conf->type == RIG_TYPE_DUPLEX) - { + if ((conf->type == RIG_TYPE_DUPLEX) || + (conf->type == RIG_TYPE_TOGGLE_AUTO) || + (conf->type == RIG_TYPE_TOGGLE_MAN)) { g_key_file_set_integer(cfg, GROUP, KEY_VFO_UP, conf->vfoUp); g_key_file_set_integer(cfg, GROUP, KEY_VFO_DOWN, conf->vfoDown); } diff --git a/src/sat-pref-rig-editor.c b/src/sat-pref-rig-editor.c index e8b73152..24808832 100644 --- a/src/sat-pref-rig-editor.c +++ b/src/sat-pref-rig-editor.c @@ -82,17 +82,25 @@ static void update_widgets(radio_conf_t * conf) gtk_combo_box_set_active(GTK_COMBO_BOX(ptt), conf->ptt); /* vfo up/down */ - if (conf->type == RIG_TYPE_DUPLEX) - { - if (conf->vfoUp == VFO_MAIN) - gtk_combo_box_set_active(GTK_COMBO_BOX(vfo), 1); - else if (conf->vfoUp == VFO_SUB) - gtk_combo_box_set_active(GTK_COMBO_BOX(vfo), 2); - else if (conf->vfoUp == VFO_A) - gtk_combo_box_set_active(GTK_COMBO_BOX(vfo), 3); - else - gtk_combo_box_set_active(GTK_COMBO_BOX(vfo), 4); + guint activeVfoSelection = 0; + if (((conf->type == RIG_TYPE_DUPLEX) || + (conf->type == RIG_TYPE_TOGGLE_AUTO) || + (conf->type == RIG_TYPE_TOGGLE_MAN))) { + switch (conf->type) { + case VFO_MAIN: + activeVfoSelection = 1; + break; + case VFO_SUB: + activeVfoSelection = 2; + break; + case VFO_A: + activeVfoSelection = 3; + break; + default: + activeVfoSelection = 4; + } } + gtk_combo_box_set_active(GTK_COMBO_BOX(vfo), activeVfoSelection); /* lo down in MHz */ gtk_spin_button_set_value(GTK_SPIN_BUTTON(lo), conf->lo / 1000000.0); @@ -317,8 +325,8 @@ static GtkWidget *create_editor_widgets(radio_conf_t * conf) "gpredict cannot know whether to tune the " "RX or the TX).\n\n" "Full-duplex: The radio is a full-duplex" - " radio, such as the IC910H. Gpredict will " - "be continuously tuning both uplink and " + " radio, such as the IC910H or IC-9700. Gpredict " + "will be continuously tuning both uplink and " "downlink simultaneously and not care about " "PTT setting.\n\n" "FT817/857/897 (auto): " @@ -378,10 +386,11 @@ static GtkWidget *create_editor_widgets(radio_conf_t * conf) gtk_widget_set_tooltip_markup(vfo, _ ("Select which VFO to use for uplink and downlink. " - "This setting is used for full-duplex radios only, " + "This setting is used for full-duplex, auto, and manual radios only, " "such as the IC-910H, FT-847 and the TS-2000.\n\n" "IC-910H: MAIN\342\206\221 / SUB\342\206\223\n" "FT-847: SUB\342\206\221 / MAIN\342\206\223\n" + "IC-9700: SUB\342\206\221 / MAIN\342\206\223\n" "TS-2000: B\342\206\221 / A\342\206\223")); gtk_grid_attach(GTK_GRID(table), vfo, 1, 5, 2, 1); @@ -475,8 +484,9 @@ static gboolean apply_changes(radio_conf_t * conf) conf->ptt = gtk_combo_box_get_active(GTK_COMBO_BOX(ptt)); /* vfo up/down */ - if (conf->type == RIG_TYPE_DUPLEX) - { + if ((conf->type == RIG_TYPE_DUPLEX) || + (conf->type == RIG_TYPE_TOGGLE_AUTO) || + (conf->type == RIG_TYPE_TOGGLE_MAN)) { switch (gtk_combo_box_get_active(GTK_COMBO_BOX(vfo))) {