1 /*
2  * Tlf - contest logging program for amateur radio operators
3  * Copyright (C) 2001-2002-2003-2004 Rein Couperus <pa0r@amsat.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19 
20 /* ------------------------------------------------------------
21  *      get trx info
22  *
23  *--------------------------------------------------------------*/
24 
25 
26 #include <unistd.h>
27 #include <sys/time.h>
28 #include <pthread.h>
29 
30 #include "bands.h"
31 #include "err_utils.h"
32 #include "fldigixmlrpc.h"
33 #include "gettxinfo.h"
34 #include "tlf.h"
35 #include "tlf_curses.h"
36 #include "callinput.h"
37 #include "bands.h"
38 
39 #include <hamlib/rig.h>
40 
41 #ifdef RIG_PASSBAND_NOCHANGE
42 #define TLF_DEFAULT_PASSBAND RIG_PASSBAND_NOCHANGE
43 #else
44 #define TLF_DEFAULT_PASSBAND RIG_PASSBAND_NORMAL
45 #endif
46 
47 extern RIG *my_rig;
48 extern int cw_bandwidth;
49 extern int trxmode;
50 extern rmode_t rigmode;
51 extern int digikeyer;
52 extern rmode_t digi_mode;
53 
54 extern freq_t freq;
55 extern int bandinx;
56 extern freq_t bandfrequency[];
57 
58 extern int trx_control;
59 extern unsigned char rigptt;
60 
61 /* output frequency to rig or other rig-related request
62  *
63  * possible values:
64  *  0 - poll rig
65  *  SETCWMODE
66  *  SETSSBMODE
67  *  RESETRIT
68  *  SETDIGIMODE
69  *  else - set rig frequency
70  *
71  */
72 static freq_t outfreq = 0;
73 
74 static pthread_mutex_t outfreq_mutex = PTHREAD_MUTEX_INITIALIZER;
75 
76 static double get_current_seconds();
77 static void handle_trx_bandswitch(const freq_t freq);
78 
set_outfreq(freq_t hertz)79 void set_outfreq(freq_t hertz) {
80     if (!trx_control) {
81 	hertz = 0;      // no rig control, ignore request
82     }
83     pthread_mutex_lock(&outfreq_mutex);
84     outfreq = hertz;
85     pthread_mutex_unlock(&outfreq_mutex);
86 }
87 
get_outfreq()88 freq_t get_outfreq() {
89     return outfreq;
90 }
91 
get_and_reset_outfreq()92 static freq_t get_and_reset_outfreq() {
93     pthread_mutex_lock(&outfreq_mutex);
94     freq_t f = outfreq;
95     outfreq = 0.0;
96     pthread_mutex_unlock(&outfreq_mutex);
97     return f;
98 }
99 
get_ssb_mode()100 static rmode_t get_ssb_mode() {
101     // LSB below 14 MHz, USB above it
102     return (freq < bandcorner[BANDINDEX_20][0] ? RIG_MODE_LSB : RIG_MODE_USB);
103 }
104 
get_cw_bandwidth()105 static pbwidth_t get_cw_bandwidth() {
106     // use specified bandwidth (CWBANDWIDTH) if available
107     return (cw_bandwidth > 0 ? cw_bandwidth : TLF_DEFAULT_PASSBAND);
108 }
109 
110 
gettxinfo(void)111 void gettxinfo(void) {
112 
113     freq_t rigfreq;
114     vfo_t vfo;
115     pbwidth_t bwidth;
116     int retval;
117     int retvalmode;
118     static double last_freq_time = 0.0;
119 
120     static int oldbandinx;
121     static int fldigi_carrier;
122     static int fldigi_shift_freq;
123 
124     if (!trx_control)
125 	return;
126 
127     /* CAT PTT wanted, available, inactive, and PTT On requested
128      * bits 0, 1, and 3 set.
129      */
130     if (rigptt == 0x0b) {
131 	retval = rig_set_ptt(my_rig, RIG_VFO_CURR, RIG_PTT_ON);
132 
133 	/* Set PTT active bit. */
134 	rigptt |= (1 << 2);		/* 0x0f */
135 
136 	/* Clear PTT On requested bit. */
137 	rigptt &= ~(1 << 3);		/* 0x07 */
138     }
139 
140     /* CAT PTT wanted, available, active and PTT Off requested
141      * bits 0, 1, 2, and 4 set.
142      */
143     if (rigptt == 0x17) {
144 	retval = rig_set_ptt(my_rig, RIG_VFO_CURR, RIG_PTT_OFF);
145 
146 	/* Clear PTT Off requested bit. */
147 	rigptt &= ~(1 << 4);		/* 0x07 */
148 
149 	/* Clear PTT active bit. */
150 	rigptt &= ~(1 << 2);		/* 0x03 */
151     }
152 
153     freq_t reqf = get_and_reset_outfreq();  // get actual request
154 
155     if (reqf == 0) {
156 
157 	rigfreq = 0.0;
158 
159 	double now = get_current_seconds();
160 	if (now < last_freq_time + 0.2) {
161 	    return;   // last read-out was within 200 ms, skip this query
162 	}
163 	last_freq_time = now;
164 
165 	retval = rig_get_vfo(my_rig, &vfo); /* initialize RIG_VFO_CURR */
166 	if (retval == RIG_OK || retval == -RIG_ENIMPL || retval == -RIG_ENAVAIL) {
167 	    retval = rig_get_freq(my_rig, RIG_VFO_CURR, &rigfreq);
168 	    if (trxmode == DIGIMODE && (digikeyer == GMFSK || digikeyer == FLDIGI)
169 		    && retval == RIG_OK) {
170 		retvalmode = rig_get_mode(my_rig, RIG_VFO_CURR, &rigmode, &bwidth);
171 		if (retvalmode != RIG_OK) {
172 		    rigmode = RIG_MODE_NONE;
173 		}
174 	    }
175 	}
176 
177 	if (trxmode == DIGIMODE && (digikeyer == GMFSK || digikeyer == FLDIGI)) {
178 	    fldigi_carrier = fldigi_get_carrier();
179 	    rigfreq += (freq_t)fldigi_carrier;
180 	    if (rigmode == RIG_MODE_RTTY || rigmode == RIG_MODE_RTTYR) {
181 		fldigi_shift_freq = fldigi_get_shift_freq();
182 		if (fldigi_shift_freq != 0) {
183 		    retval = rig_set_freq(my_rig, RIG_VFO_CURR,
184 					  ((freq_t)rigfreq + (freq_t)fldigi_shift_freq));
185 		}
186 	    }
187 	}
188 
189 	if (retval != RIG_OK || rigfreq < 0.1) {
190 	    freq = 0.0;
191 	    return;
192 	}
193 
194 
195 	if (rigfreq >= bandcorner[0][0]) {
196 	    freq = rigfreq; // Hz
197 	}
198 
199 	bandinx = freq2band((unsigned int)freq);
200 
201 	bandfrequency[bandinx] = freq;
202 
203 	if (bandinx != oldbandinx) {	// band change on trx
204 	    oldbandinx = bandinx;
205 	    handle_trx_bandswitch((int) freq);
206 	}
207 
208     } else if (reqf == SETCWMODE) {
209 
210 	retval = rig_set_mode(my_rig, RIG_VFO_CURR, RIG_MODE_CW, get_cw_bandwidth());
211 
212 	if (retval != RIG_OK) {
213 	    TLF_LOG_WARN("Problem with rig link!");
214 	}
215 
216     } else if (reqf == SETSSBMODE) {
217 
218 	retval = rig_set_mode(my_rig, RIG_VFO_CURR, get_ssb_mode(),
219 			      TLF_DEFAULT_PASSBAND);
220 
221 	if (retval != RIG_OK) {
222 	    TLF_LOG_WARN("Problem with rig link!");
223 	}
224 
225     } else if (reqf == SETDIGIMODE) {
226 	rmode_t new_mode = digi_mode;
227 	if (new_mode == RIG_MODE_NONE) {
228 	    if (digikeyer == FLDIGI)
229 		new_mode = RIG_MODE_USB;
230 	    else
231 		new_mode = RIG_MODE_LSB;
232 	}
233 	retval = rig_set_mode(my_rig, RIG_VFO_CURR, new_mode,
234 			      TLF_DEFAULT_PASSBAND);
235 
236 	if (retval != RIG_OK) {
237 	    TLF_LOG_WARN("Problem with rig link!");
238 	}
239 
240     } else if (reqf == RESETRIT) {
241 	retval = rig_set_rit(my_rig, RIG_VFO_CURR, 0);
242 
243 	if (retval != RIG_OK) {
244 	    TLF_LOG_WARN("Problem with rig link!");
245 	}
246 
247     } else {
248 	// set rig frequency to `reqf'
249 	retval = rig_set_freq(my_rig, RIG_VFO_CURR, (freq_t) reqf);
250 
251 	if (retval != RIG_OK) {
252 	    TLF_LOG_WARN("Problem with rig link: set frequency!");
253 	}
254 
255     }
256 
257 }
258 
259 
get_current_seconds()260 static double get_current_seconds() {
261     struct timeval tv;
262     gettimeofday(&tv, NULL);
263     return tv.tv_sec + tv.tv_usec / 1e6;
264 }
265 
266 
handle_trx_bandswitch(const freq_t freq)267 static void handle_trx_bandswitch(const freq_t freq) {
268 
269     send_bandswitch(freq);
270 
271     rmode_t mode = RIG_MODE_NONE;           // default: no change
272     pbwidth_t width = TLF_DEFAULT_PASSBAND; // passband width, in Hz
273 
274     if (trxmode == SSBMODE) {
275 	mode = get_ssb_mode();
276     } else if (trxmode == DIGIMODE) {
277 	if ((rigmode & (RIG_MODE_LSB | RIG_MODE_USB | RIG_MODE_RTTY | RIG_MODE_RTTYR))
278 		!= rigmode) {
279 	    mode = RIG_MODE_LSB;
280 	}
281     } else {
282 	mode = RIG_MODE_CW;
283 	width = get_cw_bandwidth();
284     }
285 
286     if (mode == RIG_MODE_NONE) {
287 	return;     // no change was requested
288     }
289 
290     int retval = rig_set_mode(my_rig, RIG_VFO_CURR, mode, width);
291 
292     if (retval != RIG_OK) {
293 	TLF_LOG_WARN("Problem with rig link!");
294     }
295 
296 }
297 
298