From 565fa4c082c3c82ffbdce4b095f35298eb24e4bb Mon Sep 17 00:00:00 2001 From: Wijnand Modderman-Lenstra Date: Tue, 27 Oct 2015 17:31:02 +0100 Subject: [PATCH] Added HAMLib support for PTT control --- Makefile.linux | 5 +++ audio.h | 24 +++++++++--- config.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ direwolf.h | 10 ++++- ptt.c | 79 +++++++++++++++++++++++++++++++++++++- 5 files changed, 210 insertions(+), 8 deletions(-) diff --git a/Makefile.linux b/Makefile.linux index 0a3537e..70a6431 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -204,6 +204,11 @@ LDLIBS += -lasound #LDLIBS += -lgps +# Uncomment following lines to enable hamlib support. +CFLAGS += -DUSE_HAMLIB +LDLIBS += -lhamlib + + # Name of current directory. # Used to generate zip file name for distribution. diff --git a/audio.h b/audio.h index 3f6017a..6e27063 100644 --- a/audio.h +++ b/audio.h @@ -12,6 +12,10 @@ #ifndef AUDIO_H #define AUDIO_H 1 +#ifdef USE_HAMLIB +#include +#endif + #include "direwolf.h" /* for MAX_CHANS used throughout the application. */ #include "ax25_pad.h" /* for AX25_MAX_ADDR_LEN */ @@ -25,7 +29,8 @@ enum ptt_method_e { PTT_METHOD_NONE, /* VOX or no transmit. */ PTT_METHOD_SERIAL, /* Serial port RTS or DTR. */ PTT_METHOD_GPIO, /* General purpose I/O, Linux only. */ - PTT_METHOD_LPT }; /* Parallel printer port, Linux only. */ + PTT_METHOD_LPT, /* Parallel printer port, Linux only. */ + PTT_METHOD_HAMLIB }; /* HAMLib, Linux only. */ typedef enum ptt_method_e ptt_method_t; @@ -175,13 +180,14 @@ struct audio_s { #define OCTYPE_PTT 0 #define OCTYPE_DCD 1 -#define OCTYPE_FUTURE 2 +#define OCTYPE_RIG 2 +#define OCTYPE_FUTURE 3 -#define NUM_OCTYPES 3 /* number of values above */ +#define NUM_OCTYPES 4 /* number of values above */ struct { - ptt_method_t ptt_method; /* none, serial port, GPIO, LPT. */ + ptt_method_t ptt_method; /* none, serial port, GPIO, LPT, HAMLIB. */ char ptt_device[20]; /* Serial device name for PTT. e.g. COM1 or /dev/ttyS0 */ @@ -196,6 +202,10 @@ struct audio_s { int ptt_invert; /* Invert the output. */ int ptt_invert2; /* Invert the secondary output. */ +#ifdef USE_HAMLIB + int ptt_rig; /* HAMLib rig. */ +#endif + } octrl[NUM_OCTYPES]; /* Transmit timing. */ @@ -224,6 +234,11 @@ struct audio_s { } achan[MAX_CHANS]; +#ifdef USE_HAMLIB + int rigs; /* Total number of configured rigs */ + RIG *rig[MAX_RIGS]; /* HAMLib rig instances */ +#endif + }; @@ -299,7 +314,6 @@ struct audio_s { * Use one or the other depending on the platform. */ - int audio_open (struct audio_s *pa); int audio_get (int a); /* a = audio device, 0 for first */ diff --git a/config.c b/config.c index d0ebee6..32fccb1 100644 --- a/config.c +++ b/config.c @@ -46,6 +46,10 @@ #include #endif +#ifdef USE_HAMLIB +#include +#endif + #include "ax25_pad.h" #include "textcolor.h" #include "audio.h" @@ -489,6 +493,10 @@ void config_init (char *fname, struct audio_s *p_audio_config, int line; int channel; int adevice; +#if USE_HAMLIB + RIG *rig; + int rigs = 0; +#endif #if DEBUG text_color_set(DW_COLOR_DEBUG); @@ -1367,6 +1375,24 @@ void config_init (char *fname, struct audio_s *p_audio_config, dw_printf ("Config file line %d: %s with LPT is only available on x86 Linux.\n", line, otname); #endif } + else if (strcasecmp(t, "RIG") == 0) { +#ifdef USE_HAMLIB + p_audio_config->achan[channel].octrl[ot].ptt_method = PTT_METHOD_HAMLIB; + + t = strtok (NULL, " ,\t\n\r"); + if (t == NULL) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Config file line %d: Missing RIG number.\n", line); + continue; + } + + p_audio_config->achan[channel].octrl[ot].ptt_rig = atoi(t); + +#else + text_color_set(DW_COLOR_ERROR); + dw_printf ("Config file line %d: %s with RIG is only available when hamlib support is enabled.\n", line, otname); +#endif + } else { /* serial port case. */ @@ -1451,6 +1477,80 @@ void config_init (char *fname, struct audio_s *p_audio_config, } /* end of PTT */ +/* + * RIG - HAMLib rig configuration. + * + * xxx port model + * + * For example a Yeasu FT-817 on /dev/ttyUSB0: + * RIG /dev/ttyUSB0 120 + * + * For example rigctld on localhost: + * RIG 127.0.0.1:4532 2 + */ + + else if (strcasecmp(t, "RIG") == 0) { +#ifdef USE_HAMLIB + int n; + hamlib_port_t port; + rig_model_t rig_model; + + if (rigs == MAX_RIGS) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Config file line %d: Maximum number of rigs reached.\n", line); + continue; + } + + t = strtok (NULL, " ,\t\n\r"); + if (t == NULL) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Config file line %d: Missing port, model[, key=value].\n", + line); + continue; + } + + strncpy (port.pathname, t, FILPATHLEN - 1); + + t = strtok (NULL, " ,\t\n\r"); + if (t == NULL) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Config file line %d: Missing model[, key=value]\n", line); + continue; + } + + if (strcasecmp(t, "AUTO") == 0) { + rig_load_all_backends(); + rig_model = rig_probe(&port); + } + else { + rig_model = atoi(t); + } + + rig = rig_init(rig_model); + if (!rig) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Config file line %d: Unknown rig %d, please check riglist.h.\n", line, rig_model); + continue; + } + + strncpy (rig->state.rigport.pathname, port.pathname, FILPATHLEN - 1); + n = rig_open(rig); + if (n != RIG_OK) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Config file line %d: Rig open error %d: %s\n", line, n, rigerror(n)); + continue; + } + + p_audio_config->rig[rigs++] = rig; + p_audio_config->rigs = rigs; + +#else + text_color_set(DW_COLOR_ERROR); + dw_printf ("Config file line %d: RIG is only available when hamlib support is enabled.\n", line); + continue; +#endif + } + /* * DWAIT - Extra delay for receiver squelch. */ diff --git a/direwolf.h b/direwolf.h index aeac219..8e05199 100644 --- a/direwolf.h +++ b/direwolf.h @@ -31,6 +31,14 @@ #define MAX_CHANS ((MAX_ADEVS) * 2) +/* + * Maximum number of rigs. + */ + +#ifdef USE_HAMLIB +#define MAX_RIGS MAX_CHANS +#endif + /* * Get audio device number for given channel. * and first channel for given device. @@ -158,4 +166,4 @@ typedef pthread_mutex_t dw_mutex_t; -#endif /* ifndef DIREWOLF_H */ \ No newline at end of file +#endif /* ifndef DIREWOLF_H */ diff --git a/ptt.c b/ptt.c index f412971..c230176 100644 --- a/ptt.c +++ b/ptt.c @@ -121,6 +121,7 @@ void ptt_set_debug(int debug) * PTT_METHOD_SERIAL - serial (com) port. * PTT_METHOD_GPIO - general purpose I/O. * PTT_METHOD_LPT - Parallel printer port. + * PTT_METHOD_HAMLIB - HAMLib rig control. * * ptt_device Name of serial port device. * e.g. COM1 or /dev/ttyS0. @@ -173,6 +174,7 @@ void ptt_init (struct audio_s *audio_config_p) strcpy (otnames[OCTYPE_PTT], "PTT"); strcpy (otnames[OCTYPE_DCD], "DCD"); + strcpy (otnames[OCTYPE_RIG], "RIG"); strcpy (otnames[OCTYPE_FUTURE], "FUTURE"); @@ -314,7 +316,7 @@ void ptt_init (struct audio_s *audio_config_p) #else /* - * Does any of them use GPIO? + * Does any of them use GPIO or HAMLIB? */ using_gpio = 0; @@ -561,6 +563,36 @@ void ptt_init (struct audio_s *audio_config_p) #endif /* x86 Linux */ +#ifdef USE_HAMLIB + for (ch = 0; ch < MAX_CHANS; ch++) { + if (save_audio_config_p->achan[ch].valid) { + int ot, retcode; + RIG *rig; + freq_t freq; + + for (ot = 0; ot < NUM_OCTYPES; ot++) { + if (audio_config_p->achan[ch].octrl[ot].ptt_method == PTT_METHOD_HAMLIB) { + if (audio_config_p->achan[ch].octrl[ot].ptt_rig - 1 >= audio_config_p->rigs) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Error: RIG %d not available.\n", audio_config_p->achan[ch].octrl[ot].ptt_rig); + audio_config_p->achan[ch].octrl[ot].ptt_method = PTT_METHOD_NONE; + } + + rig = audio_config_p->rig[audio_config_p->achan[ch].octrl[ot].ptt_rig]; + retcode = rig_get_freq(rig, RIG_VFO_CURR, &freq); + if (retcode == RIG_OK) { + text_color_set(DW_COLOR_INFO); + dw_printf ("RIG tuned on %"PRIfreq"\n", freq); + } else { + text_color_set(DW_COLOR_ERROR); + dw_printf ("RIG rig_get_freq error %s, PTT probably will not work\n", rigerror(retcode)); + } + } + } + } + } +#endif + /* Why doesn't it transmit? Probably forgot to specify PTT option. */ @@ -586,7 +618,7 @@ void ptt_init (struct audio_s *audio_config_p) * probably be renamed something like octrl_set. * * Inputs: ot - Output control type: - * OCTYPE_PTT, OCTYPE_DCD, OCTYPE_FUTURE + * OCTYPE_PTT, OCTYPE_DCD, OCTYPE_HAMLIB, OCTYPE_FUTURE * * chan - channel, 0 .. (number of channels)-1 * @@ -758,6 +790,24 @@ void ptt_set (int ot, int chan, int ptt_signal) #endif /* x86 Linux */ +#ifdef USE_HAMLIB +/* + * Using hamlib? + */ + + if (save_audio_config_p->achan[chan].octrl[ot].ptt_method == PTT_METHOD_HAMLIB) { + int retcode; + RIG *rig = save_audio_config_p->rig[save_audio_config_p->achan[chan].octrl[ot].ptt_rig]; + + if ((retcode = rig_set_ptt(rig, RIG_VFO_CURR, ptt ? RIG_PTT_ON : RIG_PTT_OFF)) != RIG_OK) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Error sending rig_set_ptt command for channel %d %s\n", chan, otnames[ot]); + dw_printf ("%s\n", rigerror(retcode)); + } + } + +#endif + } /* end ptt_set */ @@ -803,6 +853,31 @@ void ptt_term (void) } } } + +#ifdef USE_HAMLIB + for (n = 0; n < save_audio_config_p->rigs; n++) { + RIG *rig = save_audio_config_p->rig[n]; + int retcode; + + if ((retcode = rig_set_ptt(rig, RIG_VFO_CURR, RIG_PTT_OFF)) != RIG_OK) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Error sending rig_set_ptt command for rig %d\n", n); + dw_printf ("%s\n", rigerror(retcode)); + } + + if ((retcode = rig_close(rig)) != RIG_OK) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Error sending rig_close command for rig %d\n", n); + dw_printf ("%s\n", rigerror(retcode)); + } + + if ((retcode = rig_cleanup(rig)) != RIG_OK) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Error sending rig_cleanup command for rig %d\n", n); + dw_printf ("%s\n", rigerror(retcode)); + } + } +#endif }