1 /*
2 * Hamlib R&S backend - main file
3 * Copyright (c) 2009-2010 by Stéphane Fillod
4 *
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h> /* String function definitions */
29 #include <unistd.h> /* UNIX standard function definitions */
30 #include <math.h>
31
32 #include "hamlib/rig.h"
33 #include "serial.h"
34 #include "misc.h"
35 #include "register.h"
36 #include "num_stdio.h"
37
38 #include "rs.h"
39 #include "gp2000.h"
40
41
42 #define BUFSZ 64
43 #define RESPSZ 64
44
45 #define LF "\x0a"
46 #define CR "\x0d"
47 #define BOM CR
48 #define EOM CR
49
50 /*
51 * R&S GB2 protocol ?
52 */
53
54
55 /*
56 * rs_transaction
57 * We assume that rig!=NULL, rig->state!= NULL, data!=NULL, data_len!=NULL
58 */
rs_transaction(RIG * rig,const char * cmd,int cmd_len,char * data,int * data_len)59 int rs_transaction(RIG *rig, const char *cmd, int cmd_len, char *data,
60 int *data_len)
61 {
62 int retval;
63 struct rig_state *rs;
64
65 rs = &rig->state;
66
67 rig_flush(&rs->rigport);
68
69 retval = write_block(&rs->rigport, cmd, cmd_len);
70
71 if (retval != RIG_OK)
72 {
73 return retval;
74 }
75
76
77 /* no data expected */
78 if (!data || !data_len)
79 {
80 return RIG_OK;
81 }
82
83 retval = read_string(&rs->rigport, data, BUFSZ, CR, 1);
84
85 if (retval < 0)
86 {
87 return retval;
88 }
89
90 *data_len = retval;
91
92 return RIG_OK;
93 }
94
95 /*
96 * rs_set_freq
97 * Assumes rig!=NULL
98 */
rs_set_freq(RIG * rig,vfo_t vfo,freq_t freq)99 int rs_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
100 {
101 char freqbuf[32];
102 int freq_len, retval;
103
104 // cppcheck-suppress *
105 freq_len = sprintf(freqbuf, BOM "FREQ %"PRIll EOM, (int64_t)freq);
106 retval = rs_transaction(rig, freqbuf, freq_len, NULL, NULL);
107
108 return retval;
109 }
110
111 /*
112 * rs_get_freq
113 * Assumes rig!=NULL
114 */
rs_get_freq(RIG * rig,vfo_t vfo,freq_t * freq)115 int rs_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
116 {
117 char buf[RESPSZ];
118 int len, retval;
119
120 #define FREQ_QUERY BOM "FREQ?" EOM
121
122 retval = rs_transaction(rig, FREQ_QUERY, strlen(FREQ_QUERY), buf, &len);
123
124 if (retval < 0)
125 {
126 return retval;
127 }
128
129 retval = (sscanf(buf, "%"SCNfreq, freq) == 1) ? RIG_OK : -RIG_EPROTO;
130
131 return retval;
132 }
133
134 /*
135 * rs_set_mode
136 * Assumes rig!=NULL
137 */
rs_set_mode(RIG * rig,vfo_t vfo,rmode_t mode,pbwidth_t width)138 int rs_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
139 {
140 char buf[32], *smode;
141 int len, retval;
142
143 switch (mode)
144 {
145 case RIG_MODE_AM: smode = "AM"; break;
146
147 case RIG_MODE_WFM:
148 case RIG_MODE_FM: smode = "FM"; break;
149
150 case RIG_MODE_CW: smode = "CW"; break;
151
152 case RIG_MODE_USB: smode = "USB"; break;
153
154 case RIG_MODE_LSB: smode = "LSB"; break;
155
156 default:
157 return -RIG_EINVAL;
158 }
159
160 len = sprintf(buf, BOM "DEM %s" EOM, smode);
161 retval = rs_transaction(rig, buf, len, NULL, NULL);
162
163 if (retval < 0)
164 {
165 return retval;
166 }
167
168 if (width == RIG_PASSBAND_NOCHANGE) { return retval; }
169
170 if (width == RIG_PASSBAND_NORMAL)
171 {
172 width = rig_passband_normal(rig, mode);
173 }
174
175 if (width > 0)
176 {
177 len = sprintf(buf, BOM "BAND %d" EOM, (int) width);
178 retval = rs_transaction(rig, buf, len, NULL, NULL);
179 }
180
181 return retval;
182 }
183
184 /*
185 * rs_get_mode
186 * Assumes rig!=NULL
187 */
rs_get_mode(RIG * rig,vfo_t vfo,rmode_t * mode,pbwidth_t * width)188 int rs_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
189 {
190 char buf[RESPSZ];
191 int buf_len, retval;
192
193 #define DEM_QUERY BOM "DEM?" EOM
194
195 retval = rs_transaction(rig, DEM_QUERY, strlen(DEM_QUERY), buf, &buf_len);
196
197 if (retval < 0)
198 {
199 return retval;
200 }
201
202 *mode = rig_parse_mode(buf);
203
204 #define BAND_QUERY BOM "BAND?" EOM
205 retval = rs_transaction(rig, BAND_QUERY, strlen(BAND_QUERY), buf, &buf_len);
206
207 if (retval < 0)
208 {
209 return retval;
210 }
211
212 *width = atoi(buf);
213
214 return retval;
215 }
216
217
rs_set_func(RIG * rig,vfo_t vfo,setting_t func,int status)218 int rs_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
219 {
220 char buf[32], *sfunc;
221 int len, retval;
222
223 switch (func)
224 {
225 case RIG_FUNC_AFC: sfunc = "FREQ:AFC"; break;
226
227 case RIG_FUNC_SQL: sfunc = "OUTP:SQU"; break;
228
229 case RIG_FUNC_LOCK: sfunc = "DISP:ENAB"; break;
230
231 default:
232 return -RIG_EINVAL;
233 }
234
235 len = sprintf(buf, BOM "%s %s" EOM, sfunc, status ? "ON" : "OFF");
236 retval = rs_transaction(rig, buf, len, NULL, NULL);
237
238 return retval;
239 }
240
rs_get_func(RIG * rig,vfo_t vfo,setting_t func,int * status)241 int rs_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status)
242 {
243 char buf[RESPSZ], *sfunc;
244 int buf_len, retval;
245
246 switch (func)
247 {
248 case RIG_FUNC_AFC: sfunc = BOM "FREQ:AFC?" EOM; break;
249
250 case RIG_FUNC_SQL: sfunc = BOM "OUTP:SQU?" EOM; break;
251
252 case RIG_FUNC_LOCK: sfunc = BOM "DISP:ENAB?" EOM; break;
253
254 default:
255 return -RIG_EINVAL;
256 }
257
258 retval = rs_transaction(rig, sfunc, strlen(sfunc), buf, &buf_len);
259
260 if (retval < 0)
261 {
262 return retval;
263 }
264
265 *status = (!memcmp(buf, "ON", 2) || !memcmp(buf, "1", 1)) ? 1 : 0;
266
267 return retval;
268 }
269
rs_set_level(RIG * rig,vfo_t vfo,setting_t level,value_t val)270 int rs_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
271 {
272 char buf[32];
273 int len, retval;
274
275 switch (level)
276 {
277 case RIG_LEVEL_ATT:
278 len = sprintf(buf, BOM "INP:ATT:STAT %s" EOM, val.i ? "ON" : "OFF");
279 break;
280
281 case RIG_LEVEL_SQL:
282 /* dBuV */
283 len = sprintf(buf, BOM "OUTP:SQU:THR %d" EOM, (int)(20 + val.f * 20));
284 break;
285
286 case RIG_LEVEL_AF:
287 len = num_sprintf(buf, BOM "SYST:AUD:VOL %.1f" EOM, val.f);
288 break;
289
290 case RIG_LEVEL_AGC:
291 case RIG_LEVEL_RF:
292 return -RIG_ENIMPL;
293
294 default:
295 return -RIG_EINVAL;
296 }
297
298 retval = rs_transaction(rig, buf, len, NULL, NULL);
299
300 return retval;
301 }
302
rs_get_level(RIG * rig,vfo_t vfo,setting_t level,value_t * val)303 int rs_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
304 {
305 char buf[RESPSZ], *slevel;
306 int buf_len, retval;
307
308 switch (level)
309 {
310 case RIG_LEVEL_STRENGTH: slevel = BOM "SENS:DATA? \"VOLT:AC\"" EOM; break;
311
312 case RIG_LEVEL_ATT: slevel = BOM "INP:ATT:STAT?" EOM; break;
313
314 case RIG_LEVEL_AF: slevel = BOM "SYST:AUD:VOL?" EOM; break;
315
316 case RIG_LEVEL_SQL:
317 case RIG_LEVEL_AGC:
318 case RIG_LEVEL_RF:
319 return -RIG_ENIMPL;
320
321 default:
322 return -RIG_EINVAL;
323 }
324
325 retval = rs_transaction(rig, slevel, strlen(slevel), buf, &buf_len);
326
327 if (retval < 0)
328 {
329 return retval;
330 }
331
332 switch (level)
333 {
334 case RIG_LEVEL_STRENGTH:
335 /* assumes FORMAat:DATA ASCii
336 * result in dBuV, keep only integer part
337 */
338 sscanf(buf, "%d", &val->i);
339 val->i -= 34;
340 break;
341
342 case RIG_LEVEL_ATT:
343 val->i = (!memcmp(buf, "ON", 2)
344 || !memcmp(buf, "1", 1)) ? rig->state.attenuator[0] : 0;
345 break;
346
347 case RIG_LEVEL_AF:
348 if (num_sscanf(buf, "%f", &val->f) != 1)
349 {
350 return -RIG_EPROTO;
351 }
352
353 break;
354
355 default:
356 return -RIG_EINVAL;
357 }
358
359 return retval;
360 }
361
rs_get_info(RIG * rig)362 const char *rs_get_info(RIG *rig)
363 {
364 static char infobuf[128];
365 int info_len, retval;
366
367 #define ID_QUERY BOM "*IDN?" EOM
368
369 retval = rs_transaction(rig, ID_QUERY, strlen(ID_QUERY), infobuf, &info_len);
370
371 if (retval < 0)
372 {
373 return NULL;
374 }
375
376 return infobuf;
377 }
378
rs_reset(RIG * rig,reset_t reset)379 int rs_reset(RIG *rig, reset_t reset)
380 {
381 int retval;
382
383 #define RST_CMD BOM "*RST" EOM
384
385 retval = rs_transaction(rig, RST_CMD, strlen(RST_CMD), NULL, NULL);
386
387 return retval;
388 }
389
390
391 /*
392 * initrigs_rs is called by rig_backend_load
393 */
DECLARE_INITRIG_BACKEND(rs)394 DECLARE_INITRIG_BACKEND(rs)
395 {
396 rig_debug(RIG_DEBUG_VERBOSE, "%s: _init called\n", __func__);
397
398 rig_register(&esmc_caps);
399 rig_register(&eb200_caps);
400 rig_register(&xk2100_caps);
401
402 return RIG_OK;
403 }
404
405