1 /*
2 * Hamlib Kenwood TH-D74 backend
3 * Copyright (c) 2000-2011 by Stephane Fillod
4 * Copyright (c) 2018 by Sebastian Denz, based on THD72 from Brian Lucas
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 <stdlib.h>
27 #include <unistd.h>
28 #include <math.h>
29
30 #include "hamlib/rig.h"
31 #include "kenwood.h"
32 #include "th.h"
33 #include "num_stdio.h"
34 #include "iofunc.h"
35 #include "serial.h"
36 #include "misc.h"
37
38
39 #define THD74_MODES (RIG_MODE_FM|RIG_MODE_AM|RIG_MODE_LSB|RIG_MODE_USB|RIG_MODE_CW|RIG_MODE_FMN|RIG_MODE_WFM|RIG_MODE_CWR)
40 #define THD74_MODES_TX (RIG_MODE_FM)
41
42 #define THD74_FUNC_ALL (RIG_FUNC_TSQL| \
43 RIG_FUNC_TONE)
44
45 #define THD74_LEVEL_ALL (RIG_LEVEL_RFPOWER|\
46 RIG_LEVEL_SQL|\
47 RIG_LEVEL_ATT|\
48 RIG_LEVEL_VOXGAIN|\
49 RIG_LEVEL_VOXDELAY)
50
51 #define THD74_PARMS (RIG_PARM_TIME)
52
53 #define THD74_VFO_OP (RIG_OP_NONE)
54
55 #define THD74_VFO (RIG_VFO_A|RIG_VFO_B)
56
57 static rmode_t thd74_mode_table[10] =
58 {
59 [0] = RIG_MODE_FM, /* normal, but narrow compared to broadcast */
60 // [1] = RIG_MODE_DV,
61 [2] = RIG_MODE_AM,
62 [3] = RIG_MODE_LSB,
63 [4] = RIG_MODE_USB,
64 [5] = RIG_MODE_CW,
65 [6] = RIG_MODE_FMN, /* what kenwood calls narrow */
66 // [7] = RIG_MODE_DR,
67 [8] = RIG_MODE_WFM,
68 [9] = RIG_MODE_CWR,
69 };
70
71 static pbwidth_t thd74_width_table[10] =
72 {
73 [0] = 10000, // +-5KHz
74 [1] = 5000, // +-2.5KHz
75 [2] = 10000, // FIXME: what should this be?
76 [3] = 10000, // FIXME: what should this be?
77 [4] = 10000, // FIXME: what should this be?
78 [5] = 10000, // FIXME: what should this be?
79 [6] = 10000, // FIXME: what should this be?
80 [7] = 10000, // FIXME: what should this be?
81 [8] = 10000, // FIXME: what should this be?
82 [9] = 10000, // FIXME: what should this be?
83 };
84
85 static rptr_shift_t thd74_rshf_table[3] =
86 {
87 [0] = RIG_RPT_SHIFT_NONE,
88 [1] = RIG_RPT_SHIFT_PLUS,
89 [2] = RIG_RPT_SHIFT_MINUS,
90 };
91
92 static int thd74tuningstep_fine[4] =
93 {
94 [0] = 20,
95 [1] = 100,
96 [2] = 500,
97 [3] = 1000,
98 };
99
100 static int thd74tuningstep[11] =
101 {
102 [0] = 5000,
103 [1] = 6250,
104 [2] = 8330,
105 [3] = 9000,
106 [4] = 10000,
107 [5] = 15000,
108 [6] = 20000,
109 [7] = 25000,
110 [8] = 30000,
111 [9] = 50000,
112 [10] = 100000,
113 };
114
115 static int thd74voxdelay[7] =
116 {
117 [0] = 2500,
118 [1] = 5000,
119 [2] = 7500,
120 [3] = 10000,
121 [4] = 15000,
122 [5] = 20000,
123 [6] = 30000
124 };
125
126 static float thd74sqlevel[6] =
127 {
128 [0] = 0.0, /* open */
129 [1] = 0.2,
130 [2] = 0.4,
131 [3] = 0.6,
132 [4] = 0.8,
133 [5] = 1.0
134 };
135
136 static tone_t thd74dcs_list[105] =
137 {
138 23, 25, 26, 31, 32, 36, 43, 47,
139 51, 53, 54, 65, 71, 72, 73, 74,
140 114, 115, 116, 122, 125, 131, 132, 134,
141 143, 145, 152, 155, 156, 162, 165, 172,
142 174, 205, 212, 223, 225, 226, 243, 244,
143 245, 246, 251, 252, 255, 261, 263, 265,
144 266, 271, 274, 306, 311, 315, 325, 331,
145 332, 343, 346, 351, 356, 364, 365, 371,
146 411, 412, 413, 423, 431, 432, 445, 446,
147 452, 454, 455, 462, 464, 465, 466, 503,
148 506, 516, 523, 526, 532, 546, 565, 606,
149 612, 624, 627, 631, 632, 654, 662, 664,
150 703, 712, 723, 731, 732, 734, 743, 754,
151 0
152 };
153
154 static struct kenwood_priv_caps thd74_priv_caps =
155 {
156 .cmdtrm = EOM_TH, /* Command termination character */
157 .mode_table = thd74_mode_table,
158 };
159
160
161
thd74_open(RIG * rig)162 int thd74_open(RIG *rig)
163 {
164 //int ret;
165 //struct kenwood_priv_data *priv = rig->state.priv;
166 // this is already done in kenwood_init
167 //strcpy(priv->verify_cmd, "ID\r");
168
169 //ret = kenwood_transaction(rig, "", NULL, 0);
170
171 return RIG_OK;
172 }
173
174
175
thd74_set_vfo(RIG * rig,vfo_t vfo)176 static int thd74_set_vfo(RIG *rig, vfo_t vfo)
177 {
178 const char *cmd;
179
180 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
181
182 switch (vfo)
183 {
184 case RIG_VFO_A:
185 case RIG_VFO_VFO:
186 case RIG_VFO_MAIN:
187 cmd = "BC 0";
188 break;
189
190 case RIG_VFO_B:
191 cmd = "BC 1";
192 break;
193
194 default:
195 rig_debug(RIG_DEBUG_ERR, "%s: Unsupported VFO: %s\n", __func__,
196 rig_strvfo(vfo));
197 return -RIG_ENTARGET;
198 }
199
200 return kenwood_simple_transaction(rig, cmd, 4);
201 }
202
thd74_get_vfo(RIG * rig,vfo_t * vfo)203 static int thd74_get_vfo(RIG *rig, vfo_t *vfo)
204 {
205 int retval;
206 char c, buf[10];
207 size_t length;
208
209 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
210
211 retval = kenwood_transaction(rig, "BC", buf, sizeof(buf));
212
213 if (retval != RIG_OK)
214 {
215 return retval;
216 }
217
218 length = strlen(buf);
219
220 if (length == 4)
221 {
222 c = buf[3];
223 }
224 else
225 {
226 rig_debug(RIG_DEBUG_ERR, "%s: Unexpected answer length %d\n", __func__,
227 (int)length);
228 return -RIG_EPROTO;
229 }
230
231 switch (c)
232 {
233 case '0': *vfo = RIG_VFO_A; break;
234
235 case '1': *vfo = RIG_VFO_B; break;
236
237 default:
238 rig_debug(RIG_DEBUG_ERR, "%s: Unsupported VFO: %s\n", __func__,
239 rig_strvfo(*vfo));
240 return -RIG_EVFO;
241 }
242
243 return RIG_OK;
244 }
245
thd74_vfoc(RIG * rig,vfo_t vfo,char * vfoc)246 static int thd74_vfoc(RIG *rig, vfo_t vfo, char *vfoc)
247 {
248 vfo = (vfo == RIG_VFO_CURR) ? rig->state.current_vfo : vfo;
249
250 switch (vfo)
251 {
252 case RIG_VFO_A: *vfoc = '0'; break;
253
254 case RIG_VFO_B: *vfoc = '1'; break;
255
256 default:
257 rig_debug(RIG_DEBUG_ERR, "%s: Unsupported VFO: %s\n", __func__,
258 rig_strvfo(vfo));
259 return -RIG_ENTARGET;
260 }
261
262 return RIG_OK;
263 }
264
thd74_get_freq_info(RIG * rig,vfo_t vfo,char * buf)265 static int thd74_get_freq_info(RIG *rig, vfo_t vfo, char *buf)
266 {
267 int retval;
268 char c, cmd[8];
269
270 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
271 retval = thd74_vfoc(rig, vfo, &c);
272
273 if (retval != RIG_OK)
274 {
275 return retval;
276 }
277
278 sprintf(cmd, "FO %c", c);
279 retval = kenwood_transaction(rig, cmd, buf, 73);
280 return retval;
281 }
282
283 /* item is an offset into reply buf that is a single char */
thd74_get_freq_item(RIG * rig,vfo_t vfo,int item,int hi,int * val)284 static int thd74_get_freq_item(RIG *rig, vfo_t vfo, int item, int hi, int *val)
285 {
286 int retval, lval;
287 char c, buf[128];
288
289 retval = thd74_get_freq_info(rig, vfo, buf);
290
291 if (retval != RIG_OK)
292 {
293 return retval;
294 }
295
296 c = buf[item];
297 rig_debug(RIG_DEBUG_TRACE, "%s: c:%c\n", __func__, c);
298
299 if (c < '0' || c > '9')
300 {
301 return -RIG_EPROTO;
302 }
303
304 lval = c - '0';
305
306 if (lval > hi)
307 {
308 return -RIG_EPROTO;
309 }
310
311 *val = lval;
312 return RIG_OK;
313 }
314
thd74_set_freq_item(RIG * rig,vfo_t vfo,int item,int val)315 static int thd74_set_freq_item(RIG *rig, vfo_t vfo, int item, int val)
316 {
317 int retval;
318 char buf[128];
319
320 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
321
322 retval = thd74_get_freq_info(rig, vfo, buf);
323
324 if (retval != RIG_OK)
325 {
326 return retval;
327 }
328
329 buf[item] = val + '0';
330 return kenwood_simple_transaction(rig, buf, 72);
331 }
332
thd74_get_ts(RIG * rig,vfo_t vfo,shortfreq_t * ts)333 static int thd74_get_ts(RIG *rig, vfo_t vfo, shortfreq_t *ts)
334 {
335 int retval, tsinx, fine, fine_ts;
336
337 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
338
339 retval = thd74_get_freq_item(rig, vfo, 16, 9, &tsinx);
340
341 if (retval != RIG_OK)
342 {
343 rig_debug(RIG_DEBUG_TRACE, "%s: fail1\n", __func__);
344 return retval;
345 }
346
347 retval = thd74_get_freq_item(rig, vfo, 33, 1, &fine);
348
349 if (retval != RIG_OK)
350 {
351 rig_debug(RIG_DEBUG_TRACE, "%s: fail1\n", __func__);
352 return retval;
353 }
354
355 retval = thd74_get_freq_item(rig, vfo, 35, 3, &fine_ts);
356
357 if (retval != RIG_OK)
358 {
359 rig_debug(RIG_DEBUG_TRACE, "%s: fail1\n", __func__);
360 return retval;
361 }
362
363 rig_debug(RIG_DEBUG_TRACE, "%s: tsinx is %d\n", __func__, tsinx);
364 rig_debug(RIG_DEBUG_TRACE, "%s: fine is %d\n", __func__, fine);
365 rig_debug(RIG_DEBUG_TRACE, "%s: fine_ts is %d\n", __func__, fine_ts);
366
367 if (fine > 0)
368 {
369 *ts = thd74tuningstep_fine[fine_ts];
370 }
371 else
372 {
373 *ts = thd74tuningstep[tsinx];
374 }
375
376 rig_debug(RIG_DEBUG_TRACE, "%s: stepsize is %d\n", __func__, (int)*ts);
377 return RIG_OK;
378 }
379
380 // needs rig and vfo to get correct stepsize
thd74_round_freq(RIG * rig,vfo_t vfo,freq_t freq)381 static int thd74_round_freq(RIG *rig, vfo_t vfo, freq_t freq)
382 {
383 int64_t f;
384 long double r;
385 shortfreq_t ts;
386 // cppcheck-suppress *
387 char *fmt = "%s: rounded %"PRIll" to %"PRIll" because stepsize:%d\n";
388
389 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
390
391 thd74_get_ts(rig, vfo, &ts);
392
393 f = (int64_t)freq;
394 r = round((double)f / (double)ts);
395 r = ts * r;
396
397 rig_debug(RIG_DEBUG_TRACE, fmt, __func__, f, (int64_t)r, (int)ts);
398
399 return (freq_t)r;
400 }
401
thd74_set_freq(RIG * rig,vfo_t vfo,freq_t freq)402 static int thd74_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
403 {
404 struct kenwood_priv_data *priv = rig->state.priv;
405 int retval;
406 char buf[128], fbuf[12];
407
408 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
409
410 if (priv->split == RIG_SPLIT_ON)
411 {
412 vfo = RIG_VFO_B;
413 }
414
415 retval = thd74_get_freq_info(rig, vfo, buf);
416
417 if (retval != RIG_OK)
418 {
419 return retval;
420 }
421
422 freq = thd74_round_freq(rig, vfo, freq);
423 sprintf(fbuf, "%010"PRIll, (int64_t)freq);
424 memcpy(buf + 5, fbuf, 10);
425 retval = kenwood_simple_transaction(rig, buf, 72);
426 return retval;
427 }
428
thd74_get_freq(RIG * rig,vfo_t vfo,freq_t * freq)429 static int thd74_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
430 {
431 struct kenwood_priv_data *priv = rig->state.priv;
432 int retval;
433 char buf[128];
434
435 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
436
437 if (priv->split == RIG_SPLIT_ON)
438 {
439 vfo = RIG_VFO_B;
440 }
441
442 retval = thd74_get_freq_info(rig, vfo, buf);
443
444 if (retval != RIG_OK)
445 {
446 return retval;
447 }
448
449 sscanf(buf + 5, "%"SCNfreq, freq);
450 return RIG_OK;
451 }
452
453 // setting the mode via FO leads to response 'N.' from the handset
thd74_set_mode(RIG * rig,vfo_t vfo,rmode_t mode,pbwidth_t width)454 int thd74_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
455 {
456 char kmode, mdbuf[8], replybuf[8], v;
457 int retval;
458 const struct kenwood_priv_caps *priv = (const struct kenwood_priv_caps *)
459 rig->caps->priv;
460
461 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
462
463 retval = thd74_vfoc(rig, vfo, &v);
464
465 if (retval != RIG_OK)
466 {
467 return retval;
468 }
469
470 if (priv->mode_table)
471 {
472 kmode = rmode2kenwood(mode, priv->mode_table);
473
474 if (kmode < 0)
475 {
476 rig_debug(RIG_DEBUG_WARN, "%s: Unsupported Mode value '%s'\n",
477 __func__, rig_strrmode(mode));
478 return -RIG_EINVAL;
479 }
480
481 kmode += '0';
482 }
483 else
484 {
485 switch (mode)
486 {
487 case RIG_MODE_FM: kmode = '0'; break;
488
489 case RIG_MODE_AM: kmode = '1'; break;
490
491 // case RIG_MODE_DV: kmode = '2'; break;
492
493 case RIG_MODE_LSB: kmode = '3'; break;
494
495 case RIG_MODE_USB: kmode = '4'; break;
496
497 case RIG_MODE_CW: kmode = '5'; break;
498
499 case RIG_MODE_FMN: kmode = '6'; break;
500
501 // case RIG_MODE_DR: kmode = '7'; break;
502
503 case RIG_MODE_WFM: kmode = '8'; break;
504
505 case RIG_MODE_CWR: kmode = '9'; break;
506
507 default:
508 rig_debug(RIG_DEBUG_ERR, "%s: unsupported mode %s\n", __func__,
509 rig_strrmode(mode));
510 return -RIG_EINVAL;
511 }
512 }
513
514 sprintf(mdbuf, "MD %c,%c", v, kmode);
515 rig_debug(RIG_DEBUG_ERR, "%s: mdbuf: %s\n", __func__, mdbuf);
516
517 retval = kenwood_transaction(rig, mdbuf, replybuf, 7);
518 rig_debug(RIG_DEBUG_ERR, "%s: retval: %d\n", __func__, retval);
519
520 if (retval != RIG_OK)
521 {
522 return retval;
523 }
524
525 return RIG_OK;
526 }
527
thd74_get_mode(RIG * rig,vfo_t vfo,rmode_t * mode,pbwidth_t * width)528 static int thd74_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
529 {
530 int retval;
531 char modec, buf[128];
532
533 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
534
535 retval = thd74_get_freq_info(rig, vfo, buf);
536
537 if (retval != RIG_OK)
538 {
539 return retval;
540 }
541
542 modec = buf[31];
543
544 if (modec >= '0' && modec <= '9')
545 {
546 *mode = thd74_mode_table[modec - '0'];
547 *width = thd74_width_table[modec - '0'];
548 }
549 else
550 {
551 return -RIG_EINVAL;
552 }
553
554 return RIG_OK;
555 }
556
thd74_set_rptr_shft(RIG * rig,vfo_t vfo,rptr_shift_t rptr_shift)557 static int thd74_set_rptr_shft(RIG *rig, vfo_t vfo, rptr_shift_t rptr_shift)
558 {
559 int rsinx;
560
561 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
562
563 switch (rptr_shift)
564 {
565 case RIG_RPT_SHIFT_NONE: rsinx = 0; break;
566
567 case RIG_RPT_SHIFT_PLUS: rsinx = 1; break;
568
569 case RIG_RPT_SHIFT_MINUS: rsinx = 2; break;
570
571 default:
572 return -RIG_EINVAL;
573 }
574
575 return thd74_set_freq_item(rig, vfo, 47, rsinx);
576 }
577
thd74_get_rptr_shft(RIG * rig,vfo_t vfo,rptr_shift_t * rptr_shift)578 static int thd74_get_rptr_shft(RIG *rig, vfo_t vfo, rptr_shift_t *rptr_shift)
579 {
580 int retval, rsinx;
581
582 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
583
584 retval = thd74_get_freq_item(rig, vfo, 47, 3, &rsinx);
585
586 if (retval != RIG_OK)
587 {
588 return retval;
589 }
590
591 /* rsinx == 3 indicates split mode? */
592 *rptr_shift = (rsinx == 3) ? RIG_RPT_SHIFT_NONE : thd74_rshf_table[rsinx];
593 return RIG_OK;
594 }
595
596
thd74_set_rptr_offs(RIG * rig,vfo_t vfo,shortfreq_t offs)597 static int thd74_set_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t offs)
598 {
599 int retval;
600 char boff[11], buf[128];
601
602 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
603
604 retval = thd74_get_freq_info(rig, vfo, buf);
605
606 if (retval != RIG_OK)
607 {
608 return retval;
609 }
610
611 sprintf(boff, "%010ld", offs);
612 memcpy(buf + 16, boff, 10);
613 retval = kenwood_simple_transaction(rig, buf, 72);
614 return retval;
615 }
616
thd74_get_rptr_offs(RIG * rig,vfo_t vfo,shortfreq_t * offs)617 static int thd74_get_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t *offs)
618 {
619 int retval;
620 char buf[128];
621
622 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
623
624 retval = thd74_get_freq_info(rig, vfo, buf);
625
626 if (retval != RIG_OK)
627 {
628 return retval;
629 }
630
631 sscanf(buf + 16, "%ld", offs);
632 return RIG_OK;
633 }
634
thd74_set_ts(RIG * rig,vfo_t vfo,shortfreq_t ts)635 static int thd74_set_ts(RIG *rig, vfo_t vfo, shortfreq_t ts)
636 {
637 int tsinx;
638
639 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
640
641 for (tsinx = 0; tsinx < 10; tsinx++)
642 {
643 if (thd74tuningstep[tsinx] >= ts)
644 {
645 thd74_set_freq_item(rig, vfo, 16, tsinx);
646 return RIG_OK;
647 }
648 }
649
650 return -RIG_EINVAL;
651 }
652
thd74_set_ctcss_tone(RIG * rig,vfo_t vfo,tone_t tone)653 static int thd74_set_ctcss_tone(RIG *rig, vfo_t vfo, tone_t tone)
654 {
655 int retval, tinx;
656 char buf[64], tmp[4];
657
658 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
659
660 tinx = 0; /* default */
661
662 if (tone != 0)
663 {
664 for (tinx = 0; tinx < 42; tinx++)
665 {
666 if (tone == kenwood42_ctcss_list[tinx])
667 {
668 break;
669 }
670 }
671
672 if (tinx >= 42)
673 {
674 return -RIG_EINVAL;
675 }
676 }
677
678 retval = thd74_get_freq_info(rig, vfo, buf);
679
680 if (retval != RIG_OK)
681 {
682 return retval;
683 }
684
685 buf[22] = (tone == 0) ? '0' : '1';
686 sprintf(tmp, "%02d", tinx);
687 memcpy(buf + 30, tmp, 2);
688 return kenwood_simple_transaction(rig, buf, 52);
689 }
690
thd74_get_ctcss_tone(RIG * rig,vfo_t vfo,tone_t * tone)691 static int thd74_get_ctcss_tone(RIG *rig, vfo_t vfo, tone_t *tone)
692 {
693 int retval, tinx;
694 char buf[64];
695
696 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
697
698 retval = thd74_get_freq_info(rig, vfo, buf);
699
700 if (retval != RIG_OK)
701 {
702 return retval;
703 }
704
705 if (buf[22] == '0') /* no tone */
706 {
707 *tone = 0;
708 }
709 else
710 {
711 sscanf(buf + 30, "%d", &tinx);
712
713 if (tinx >= 0 && tinx <= 41)
714 {
715 *tone = kenwood42_ctcss_list[tinx];
716 }
717 else
718 {
719 return -RIG_EINVAL;
720 }
721 }
722
723 return RIG_OK;
724 }
725
thd74_set_dcs_code(RIG * rig,vfo_t vfo,tone_t code)726 static int thd74_set_dcs_code(RIG *rig, vfo_t vfo, tone_t code)
727 {
728 int retval, cinx;
729 char buf[64], tmp[4];
730
731 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
732
733 cinx = 0; /* default */
734
735 if (code != 0)
736 {
737 for (cinx = 0; cinx < 104; cinx++)
738 {
739 if (code == thd74dcs_list[cinx])
740 {
741 break;
742 }
743 }
744
745 if (cinx >= 104)
746 {
747 return -RIG_EINVAL;
748 }
749 }
750
751 retval = thd74_get_freq_info(rig, vfo, buf);
752
753 if (retval != RIG_OK)
754 {
755 return retval;
756 }
757
758 buf[26] = (code == 0) ? '0' : '1';
759 sprintf(tmp, "%03d", cinx);
760 memcpy(buf + 36, tmp, 3);
761 return kenwood_simple_transaction(rig, buf, 52);
762 }
763
thd74_get_dcs_code(RIG * rig,vfo_t vfo,tone_t * code)764 static int thd74_get_dcs_code(RIG *rig, vfo_t vfo, tone_t *code)
765 {
766 int retval, cinx;
767 char buf[64];
768
769 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
770
771 retval = thd74_get_freq_info(rig, vfo, buf);
772
773 if (retval != RIG_OK)
774 {
775 return retval;
776 }
777
778 if (buf[26] == '0') /* no tone */
779 {
780 *code = 0;
781 }
782 else
783 {
784 sscanf(buf + 36, "%d", &cinx);
785 *code = thd74dcs_list[cinx];
786 }
787
788 return RIG_OK;
789 }
790
thd74_set_ctcss_sql(RIG * rig,vfo_t vfo,tone_t tone)791 static int thd74_set_ctcss_sql(RIG *rig, vfo_t vfo, tone_t tone)
792 {
793 int retval, tinx;
794 char buf[64], tmp[4];
795
796 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
797
798 tinx = 0; /* default */
799
800 if (tone != 0)
801 {
802 for (tinx = 0; tinx < 42; tinx++)
803 {
804 if (tone == kenwood42_ctcss_list[tinx])
805 {
806 break;
807 }
808 }
809
810 if (tinx >= 42)
811 {
812 return -RIG_EINVAL;
813 }
814 }
815
816 retval = thd74_get_freq_info(rig, vfo, buf);
817
818 if (retval != RIG_OK)
819 {
820 return retval;
821 }
822
823 buf[24] = (tone == 0) ? '0' : '1';
824 sprintf(tmp, "%02d", tinx);
825 memcpy(buf + 33, tmp, 2);
826 return kenwood_simple_transaction(rig, buf, 52);
827 }
828
thd74_get_ctcss_sql(RIG * rig,vfo_t vfo,tone_t * tone)829 static int thd74_get_ctcss_sql(RIG *rig, vfo_t vfo, tone_t *tone)
830 {
831 int retval, tinx;
832 char buf[64];
833
834 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
835
836 retval = thd74_get_freq_info(rig, vfo, buf);
837
838 if (retval != RIG_OK)
839 {
840 return retval;
841 }
842
843 if (buf[24] == '0') /* no tsql */
844 {
845 *tone = 0;
846 }
847 else
848 {
849 sscanf(buf + 33, "%d", &tinx);
850
851 if (tinx >= 0 && tinx <= 41)
852 {
853 *tone = kenwood42_ctcss_list[tinx];
854 }
855 else
856 {
857 return -RIG_EINVAL;
858 }
859 }
860
861 return RIG_OK;
862 }
863
thd74_set_ptt(RIG * rig,vfo_t vfo,ptt_t ptt)864 int thd74_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
865 {
866 const char *ptt_cmd;
867
868 rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
869
870 switch (ptt)
871 {
872 case RIG_PTT_ON:
873 ptt_cmd = "TX";
874 return kenwood_simple_transaction(rig, ptt_cmd, 4);
875 break;
876
877 case RIG_PTT_OFF:
878 ptt_cmd = "RX";
879 return kenwood_simple_transaction(rig, ptt_cmd, 2);
880 break;
881
882 default: return -RIG_EINVAL;
883 }
884 }
885
thd74_set_level(RIG * rig,vfo_t vfo,setting_t level,value_t val)886 static int thd74_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
887 {
888 int retval, lvl;
889 char c, lvlc, cmd[11];
890
891 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
892 rig_debug(RIG_DEBUG_TRACE, "%s: level: %s\n", __func__, rig_strlevel(level));
893 rig_debug(RIG_DEBUG_TRACE, "%s: value.i: %d\n", __func__, val.i);
894 rig_debug(RIG_DEBUG_TRACE, "%s: value.f: %lf\n", __func__, val.f);
895
896 retval = thd74_vfoc(rig, vfo, &c);
897
898 if (retval != RIG_OK)
899 {
900 return retval;
901 }
902
903 switch (level)
904 {
905 case RIG_LEVEL_RFPOWER:
906 if (val.f <= 0.01) { lvlc = '3'; }
907 else if (val.f <= 0.1) { lvlc = '2'; }
908 else if (val.f <= 0.4) { lvlc = '1'; }
909 else { lvlc = '0'; }
910
911 sprintf(cmd, "PC %c,%c", c, lvlc);
912 return kenwood_simple_transaction(rig, cmd, 6);
913
914 case RIG_LEVEL_VOXGAIN:
915 sprintf(cmd, "VG %d", (int)(val.f * 10.0 - 0.5));
916 return kenwood_simple_transaction(rig, cmd, 4);
917
918 case RIG_LEVEL_VOXDELAY:
919 if (val.i > 20000) { lvl = 6; }
920 else if (val.i > 10000) { lvl = val.i / 10000 + 3; }
921 else { lvl = val.i / 2500; }
922
923 sprintf(cmd, "VD %d", lvl);
924 return kenwood_simple_transaction(rig, cmd, 4);
925
926 case RIG_LEVEL_SQL:
927 sprintf(cmd, "SQ %c,%d", c, (int)val.f);
928 return kenwood_simple_transaction(rig, cmd, 6);
929
930 case RIG_LEVEL_ATT: // no value provided to distinguish between on/off??
931 sprintf(cmd, "RA %c,%d", c, (int)val.f);
932 return kenwood_simple_transaction(rig, cmd, 6);
933
934 default:
935 rig_debug(RIG_DEBUG_ERR, "%s: unsupported level %s\n", __func__,
936 rig_strlevel(level));
937 return -RIG_EINVAL;
938 }
939
940 return retval;
941 }
942
thd74_get_level(RIG * rig,vfo_t vfo,setting_t level,value_t * val)943 static int thd74_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
944 {
945 int retval, v, l;
946 char c, cmd[10], buf[128];
947
948 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
949
950 retval = thd74_vfoc(rig, vfo, &c);
951
952 if (retval != RIG_OK)
953 {
954 return retval;
955 }
956
957 switch (level)
958 {
959 case RIG_LEVEL_RFPOWER:
960 sprintf(cmd, "PC %c", c);
961 retval = kenwood_transaction(rig, cmd, buf, sizeof(buf));
962
963 if (retval != RIG_OK)
964 {
965 return retval;
966 }
967
968 retval = sscanf(buf, "PC %d,%d", &v, &l);
969
970 if (retval != 2 || l < 0 || l > 3)
971 {
972 rig_debug(RIG_DEBUG_ERR, "%s: Unexpected reply '%s'\n", __func__, buf);
973 return -RIG_ERJCTED;
974 }
975
976 switch (l)
977 {
978 case 0: val->f = 1.00; break; /* 5.0 W */
979
980 case 1: val->f = 0.40; break; /* 2.0 W */
981
982 case 2: val->f = 0.1; break; /* 500 mW */
983
984 case 3: val->f = 0.01; break; /* 50 mW */
985 }
986
987 break;
988
989 case RIG_LEVEL_VOXGAIN:
990 sprintf(cmd, "VG");
991 retval = kenwood_transaction(rig, cmd, buf, sizeof(buf));
992
993 if (retval != RIG_OK)
994 {
995 return retval;
996 }
997
998 rig_debug(RIG_DEBUG_TRACE, "%s: VOXGAIN buf:%s\n", __func__, buf);
999 /* FIXME - if VOX is off, what do we return */
1000 val->f = (buf[0] - '0') / 9.0;
1001 break;
1002
1003 case RIG_LEVEL_VOXDELAY:
1004 sprintf(cmd, "VD");
1005 retval = kenwood_transaction(rig, cmd, buf, sizeof(buf));
1006
1007 if (retval != RIG_OK)
1008 {
1009 return retval;
1010 }
1011
1012 /* FIXME - if VOX is off, what do we return */
1013 rig_debug(RIG_DEBUG_TRACE, "%s: VOXDELAY buf:%s\n", __func__, buf);
1014 val->i = thd74voxdelay[buf[0] - '0'];
1015 break;
1016
1017 case RIG_LEVEL_SQL:
1018 sprintf(cmd, "SQ %c", c);
1019 retval = kenwood_transaction(rig, cmd, buf, sizeof(buf));
1020
1021 if (retval != RIG_OK)
1022 {
1023 return retval;
1024 }
1025
1026 retval = sscanf(buf, "SQ %d,%d", &v, &l);
1027
1028 if (retval != 2 || l < 0 || l >= 6)
1029 {
1030 rig_debug(RIG_DEBUG_ERR, "%s: Unexpected reply '%s'\n", __func__, buf);
1031 return -RIG_ERJCTED;
1032 }
1033
1034 val->f = thd74sqlevel[l];
1035 break;
1036
1037 case RIG_LEVEL_ATT:
1038 sprintf(cmd, "RA %c", c);
1039 retval = kenwood_transaction(rig, cmd, buf, 7);
1040
1041 if (retval != RIG_OK)
1042 {
1043 return retval;
1044 }
1045
1046 sscanf(buf + 5, "%d", &val->i);
1047 break;
1048
1049 default:
1050 rig_debug(RIG_DEBUG_ERR, "%s: unsupported level %s\n", __func__,
1051 rig_strlevel(level));
1052 return -RIG_EINVAL;
1053 }
1054
1055 return RIG_OK;
1056 }
1057
thd74_set_func(RIG * rig,vfo_t vfo,setting_t func,int status)1058 static int thd74_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
1059 {
1060 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
1061
1062 switch (func)
1063 {
1064 case RIG_FUNC_TONE:
1065 return thd74_set_freq_item(rig, vfo, 37, status);
1066
1067 case RIG_FUNC_TSQL:
1068 return thd74_set_freq_item(rig, vfo, 39, status);
1069
1070 default:
1071 return -RIG_EINVAL;
1072 }
1073
1074 return RIG_OK;
1075 }
1076
thd74_get_func(RIG * rig,vfo_t vfo,setting_t func,int * status)1077 static int thd74_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status)
1078 {
1079 int retval, f;
1080
1081 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
1082
1083 switch (func)
1084 {
1085 case RIG_FUNC_TONE:
1086 retval = thd74_get_freq_item(rig, vfo, 37, 1, &f);
1087 break;
1088
1089 case RIG_FUNC_TSQL:
1090 retval = thd74_get_freq_item(rig, vfo, 39, 1, &f);
1091 break;
1092
1093 default:
1094 return -RIG_EINVAL;
1095 }
1096
1097 if (retval != RIG_OK)
1098 {
1099 return retval;
1100 }
1101
1102 *status = f;
1103 return RIG_OK;
1104 }
1105
thd74_set_parm(RIG * rig,setting_t parm,value_t val)1106 static int thd74_set_parm(RIG *rig, setting_t parm, value_t val)
1107 {
1108 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
1109
1110 switch (parm)
1111 {
1112 case RIG_PARM_TIME: // FIXME check val, send formatted via RT
1113 default:
1114 return -RIG_EINVAL;
1115 }
1116
1117 return RIG_OK;
1118 }
1119
thd74_get_parm(RIG * rig,setting_t parm,value_t * val)1120 static int thd74_get_parm(RIG *rig, setting_t parm, value_t *val)
1121 {
1122 int retval, hh, mm, ss;
1123 char buf[48];
1124
1125 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
1126
1127 switch (parm)
1128 {
1129 case RIG_PARM_TIME:
1130 retval = kenwood_transaction(rig, "RT", buf, sizeof(buf));
1131
1132 if (retval != RIG_OK)
1133 {
1134 return retval;
1135 }
1136
1137 sscanf(buf + 11, "%2d%2d%2d", &hh, &mm, &ss);
1138 val->i = ss + 60 * (mm + 60 * hh);
1139 break;
1140
1141 default:
1142 return -RIG_EINVAL;
1143 }
1144
1145 return RIG_OK;
1146 }
1147
thd74_set_mem(RIG * rig,vfo_t vfo,int ch)1148 static int thd74_set_mem(RIG *rig, vfo_t vfo, int ch)
1149 {
1150 int retval;
1151 char c, cmd[10];
1152
1153 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
1154
1155 retval = thd74_vfoc(rig, vfo, &c);
1156
1157 if (retval != RIG_OK)
1158 {
1159 return retval;
1160 }
1161
1162 sprintf(cmd, "MR %c,%03d", c, ch);
1163 return kenwood_simple_transaction(rig, cmd, 8);
1164 }
1165
thd74_get_mem(RIG * rig,vfo_t vfo,int * ch)1166 static int thd74_get_mem(RIG *rig, vfo_t vfo, int *ch)
1167 {
1168 int retval;
1169 char c, cmd[10], buf[10];
1170
1171 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
1172
1173 retval = thd74_vfoc(rig, vfo, &c);
1174
1175 if (retval != RIG_OK)
1176 {
1177 return retval;
1178 }
1179
1180 sprintf(cmd, "MR %c", c);
1181 retval = kenwood_transaction(rig, cmd, buf, sizeof(buf));
1182
1183 if (retval != RIG_OK)
1184 {
1185 return retval;
1186 }
1187
1188 sscanf(buf + 3, "%d", ch);
1189 return RIG_OK;
1190 }
1191
thd74_set_channel(RIG * rig,vfo_t vfo,const channel_t * chan)1192 static int thd74_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
1193 {
1194 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
1195
1196 return -RIG_EINVAL;
1197 }
1198
thd74_parse_channel(int kind,const char * buf,channel_t * chan)1199 static int thd74_parse_channel(int kind, const char *buf, channel_t *chan)
1200 {
1201 int tmp;
1202 char c;
1203 const char *data;
1204
1205 if (kind == 0) { data = buf + 5; }
1206 else { data = buf + 7; }
1207
1208 sscanf(data, "%"SCNfreq, &chan->freq);
1209 c = data[46]; // mode
1210
1211 if (c >= '0' && c <= '2')
1212 {
1213 chan->mode = thd74_mode_table[c - '0'];
1214 chan->width = thd74_width_table[c - '0'];
1215 }
1216
1217 c = data[11]; // tuning step
1218
1219 if (c >= '0' && c <= '9')
1220 {
1221 chan->tuning_step = thd74tuningstep[c - '0'];
1222 }
1223
1224 c = data[13]; // repeater shift
1225
1226 if (c >= '0' && c <= '2')
1227 {
1228 chan->rptr_shift = thd74_rshf_table[c - '0'];
1229 }
1230
1231 sscanf(data + 37, "%ld", &chan->rptr_offs);
1232 c = data[17]; // Tone status
1233
1234 if (c != '0')
1235 {
1236 sscanf(data + 25, "%d", &tmp);
1237
1238 if (tmp > 0 && tmp < 42)
1239 {
1240 chan->ctcss_tone = kenwood42_ctcss_list[tmp];
1241 }
1242 }
1243 else
1244 {
1245 chan->ctcss_tone = 0;
1246 }
1247
1248 c = data[19]; // TSQL status
1249
1250 if (c != '0')
1251 {
1252 sscanf(data + 28, "%d", &tmp);
1253
1254 if (tmp > 0 && tmp < 42)
1255 {
1256 chan->ctcss_sql = kenwood42_ctcss_list[tmp];
1257 }
1258 }
1259 else
1260 {
1261 chan->ctcss_sql = 0;
1262 }
1263
1264 c = data[21]; // DCS status
1265
1266 if (c != '0')
1267 {
1268 sscanf(data + 31, "%d", &tmp);
1269 chan->dcs_code = tmp;
1270 }
1271 else
1272 {
1273 chan->dcs_code = 0;
1274 }
1275
1276 return RIG_OK;
1277 }
1278
thd74_get_channel(RIG * rig,vfo_t vfo,channel_t * chan,int read_only)1279 static int thd74_get_channel(RIG *rig, vfo_t vfo, channel_t *chan,
1280 int read_only)
1281 {
1282 int retval;
1283 char buf[72];
1284
1285 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
1286
1287 if (chan->vfo == RIG_VFO_MEM) /* memory channel */
1288 {
1289 int len;
1290 char cmd[16];
1291 sprintf(cmd, "ME %03d", chan->channel_num);
1292 retval = kenwood_transaction(rig, cmd, buf, sizeof(buf));
1293
1294 if (retval != RIG_OK)
1295 {
1296 return retval;
1297 }
1298
1299 retval = thd74_parse_channel(1, buf, chan);
1300
1301 if (retval != RIG_OK)
1302 {
1303 return retval;
1304 }
1305
1306 cmd[1] = 'N'; /* change ME to MN */
1307 retval = kenwood_transaction(rig, cmd, buf, sizeof(buf));
1308
1309 if (retval != RIG_OK)
1310 {
1311 return retval;
1312 }
1313
1314 len = strlen(buf);
1315 memcpy(chan->channel_desc, buf + 7, len - 7);
1316 }
1317 else /* current channel */
1318 {
1319 retval = thd74_get_freq_info(rig, chan->vfo, buf);
1320
1321 if (retval != RIG_OK)
1322 {
1323 return retval;
1324 }
1325
1326 return thd74_parse_channel(0, buf, chan);
1327 }
1328
1329 if (!read_only)
1330 {
1331 // Set rig to channel values
1332 rig_debug(RIG_DEBUG_ERR,
1333 "%s: please contact hamlib mailing list to implement this\n", __func__);
1334 rig_debug(RIG_DEBUG_ERR,
1335 "%s: need to know if rig updates when channel read or not\n", __func__);
1336 return -RIG_ENIMPL;
1337 }
1338
1339 return RIG_OK;
1340 }
1341
thd74_set_split_vfo(RIG * rig,vfo_t vfo,split_t split,vfo_t txvfo)1342 int thd74_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t txvfo)
1343 {
1344 struct kenwood_priv_data *priv = rig->state.priv;
1345
1346 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
1347
1348 if (txvfo != RIG_VFO_A)
1349 {
1350 return -RIG_EINVAL;
1351 }
1352
1353 priv->split = split;
1354
1355 return RIG_OK;
1356 }
1357
thd74_get_split_vfo(RIG * rig,vfo_t vfo,split_t * split,vfo_t * txvfo)1358 int thd74_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split, vfo_t *txvfo)
1359 {
1360 struct kenwood_priv_data *priv = rig->state.priv;
1361
1362 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
1363
1364 if (priv->split == RIG_SPLIT_ON)
1365 {
1366 *txvfo = RIG_VFO_A;
1367 }
1368 else
1369 {
1370 return -RIG_EPROTO;
1371 }
1372
1373 return RIG_OK;
1374 }
1375
1376 /*
1377 if priv->split is RIG_SPLIT_ON set *tx_freq to freq of VFOA and return RIG_OK
1378 otherwise return -RIG_EPROTO
1379 */
thd74_get_split_freq(RIG * rig,vfo_t vfo,freq_t * tx_freq)1380 int thd74_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
1381 {
1382 struct kenwood_priv_data *priv = rig->state.priv;
1383 int retval;
1384 char buf[128];
1385
1386 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
1387
1388 if (priv->split == RIG_SPLIT_ON)
1389 {
1390 vfo = RIG_VFO_A;
1391 }
1392 else
1393 {
1394 return -RIG_EINVAL;
1395 }
1396
1397 retval = thd74_get_freq_info(rig, vfo, buf);
1398
1399 if (retval != RIG_OK)
1400 {
1401 return retval;
1402 }
1403
1404 sscanf(buf + 5, "%"SCNfreq, tx_freq);
1405 return RIG_OK;
1406 }
1407
1408 /*
1409 if priv->split is RIG_SPLIT_ON set freq of VFOA to txfreq and return RIG_OK
1410 otherwise return -RIG_EPROTO
1411 */
thd74_set_split_freq(RIG * rig,vfo_t vfo,freq_t tx_freq)1412 int thd74_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
1413 {
1414 struct kenwood_priv_data *priv = rig->state.priv;
1415
1416 rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
1417
1418 if (priv->split == RIG_SPLIT_ON)
1419 {
1420 char fbuf[12], buf[128];
1421 int retval = thd74_get_freq_info(rig, RIG_VFO_A, buf);
1422
1423 if (retval != RIG_OK)
1424 {
1425 return retval;
1426 }
1427
1428 tx_freq = thd74_round_freq(rig, RIG_VFO_A, tx_freq);
1429 sprintf(fbuf, "%010"PRIll, (int64_t)tx_freq);
1430 memcpy(buf + 5, fbuf, 10);
1431 return kenwood_simple_transaction(rig, buf, 72);
1432 }
1433
1434 return -RIG_EPROTO;
1435 }
1436
1437 #ifdef false /* not working */
1438 #define CMD_SZ 5
1439 #define BLOCK_SZ 256
1440 #define BLOCK_COUNT 256
1441 #define CHAN_PER_BLOCK 4
1442
thd74_get_block(RIG * rig,int block_num,char * block)1443 static int thd74_get_block(RIG *rig, int block_num, char *block)
1444 {
1445 hamlib_port_t *rp = &rig->state.rigport;
1446 char cmd[CMD_SZ] = "R\0\0\0\0";
1447 char resp[CMD_SZ];
1448 int ret;
1449
1450 /* fetching block i */
1451 cmd[2] = block_num & 0xff;
1452
1453 ret = write_block(rp, cmd, CMD_SZ);
1454
1455 if (ret != RIG_OK)
1456 {
1457 return ret;
1458 }
1459
1460 /* read response first */
1461 ret = read_block(rp, resp, CMD_SZ);
1462
1463 if (ret != CMD_SZ)
1464 {
1465 return ret;
1466 }
1467
1468 if (resp[0] != 'W' || memcmp(cmd + 1, resp + 1, CMD_SZ - 1))
1469 {
1470 return -RIG_EPROTO;
1471 }
1472
1473 /* read block */
1474 ret = read_block(rp, block, BLOCK_SZ);
1475
1476 if (ret != BLOCK_SZ)
1477 {
1478 return ret;
1479 }
1480
1481 ret = write_block(rp, "\006", 1);
1482
1483 if (ret != RIG_OK)
1484 {
1485 return ret;
1486 }
1487
1488 ret = read_block(rp, resp, 1);
1489
1490 if (ret != 1)
1491 {
1492 return ret;
1493 }
1494
1495 if (resp[0] != 0x06)
1496 {
1497 return -RIG_EPROTO;
1498 }
1499
1500 return RIG_OK;
1501 }
1502
1503 #ifdef XXREMOVEDXX
thd74_get_chan_all_cb(RIG * rig,chan_cb_t chan_cb,rig_ptr_t arg)1504 int thd74_get_chan_all_cb(RIG *rig, chan_cb_t chan_cb, rig_ptr_t arg)
1505 {
1506 int i, j, ret;
1507 hamlib_port_t *rp = &rig->state.rigport;
1508 channel_t *chan;
1509 chan_t *chan_list = rig->state.chan_list;
1510 int chan_next = chan_list[0].start;
1511 char block[BLOCK_SZ];
1512 char resp[CMD_SZ];
1513
1514 ret = kenwood_transaction(rig, "0M PROGRAM", resp, CMD_SZ);
1515
1516 if (ret != RIG_OK)
1517 {
1518 return ret;
1519 }
1520
1521 if (strlen(resp) != 2 || memcmp(resp, "0M", 2))
1522 {
1523 return -RIG_EPROTO;
1524 }
1525
1526 rp->parm.serial.rate = 57600;
1527 serial_setup(rp);
1528
1529
1530 hl_usleep(100 * 1000); /* let the pcr settle */
1531 rig_flush(rp); /* flush any remaining data */
1532 ret = ser_set_rts(rp, 1); /* setRTS or Hardware flow control? */
1533
1534 if (ret != RIG_OK)
1535 {
1536 return ret;
1537 }
1538
1539 /*
1540 * setting chan to NULL means the application
1541 * has to provide a struct where to store data
1542 * future data for channel channel_num
1543 */
1544 chan = NULL;
1545 ret = chan_cb(rig, &chan, chan_next, chan_list, arg);
1546
1547 if (ret != RIG_OK)
1548 {
1549 return ret;
1550 }
1551
1552 if (chan == NULL)
1553 {
1554 return -RIG_ENOMEM;
1555 }
1556
1557 for (i = 0; i < BLOCK_COUNT; i++)
1558 {
1559
1560 ret = thd74_get_block(rig, i, block);
1561
1562 if (ret != RIG_OK)
1563 {
1564 return ret;
1565 }
1566
1567 /*
1568 * Most probably, there's 64 bytes per channel (256*256 / 1000+)
1569 */
1570 for (j = 0; j < CHAN_PER_BLOCK; j++)
1571 {
1572 char *block_chan = block + j * (BLOCK_SZ / CHAN_PER_BLOCK);
1573 memset(chan, 0, sizeof(channel_t));
1574 chan->vfo = RIG_VFO_MEM;
1575 chan->channel_num = i * CHAN_PER_BLOCK + j;
1576
1577 /* What are the extra 64 channels ? */
1578 if (chan->channel_num >= 1000)
1579 {
1580 break;
1581 }
1582
1583 /* non-empty channel ? */
1584 // if (block_chan[0] != 0xff) {
1585 // since block_chan is *signed* char, this maps to -1
1586 if (block_chan[0] != -1)
1587 {
1588
1589 memcpy(chan->channel_desc, block_chan, 8);
1590 /* TODO: chop off trailing chars */
1591 chan->channel_desc[8] = '\0';
1592
1593 /* TODO: parse block and fill in chan */
1594 }
1595
1596 /* notify the end? */
1597 chan_next = chan_next < chan_list[i].end ? chan_next + 1 : chan_next;
1598
1599 /*
1600 * provide application with channel data,
1601 * and ask for a new channel structure
1602 */
1603 chan_cb(rig, &chan, chan_next, chan_list, arg);
1604 }
1605 }
1606
1607 ret = write_block(rp, "E", 1);
1608
1609 if (ret != RIG_OK)
1610 {
1611 return ret;
1612 }
1613
1614 ret = read_block(rp, resp, 1);
1615
1616 if (ret != 1)
1617 {
1618 return ret;
1619 }
1620
1621 if (resp[0] != 0x06)
1622 {
1623 return -RIG_EPROTO;
1624 }
1625
1626 /* setRTS?? getCTS needed? */
1627 ret = ser_set_rts(rp, 1);
1628
1629 if (ret != RIG_OK)
1630 {
1631 return ret;
1632 }
1633
1634 return RIG_OK;
1635 }
1636 #endif
1637 #endif /* none working stuff */
1638 /*
1639 * th-d74 rig capabilities.
1640 */
1641 const struct rig_caps thd74_caps =
1642 {
1643 RIG_MODEL(RIG_MODEL_THD74),
1644 .model_name = "TH-D74",
1645 .mfg_name = "Kenwood",
1646 .version = BACKEND_VER ".2",
1647 .copyright = "LGPL",
1648 .status = RIG_STATUS_STABLE,
1649 .rig_type = RIG_TYPE_HANDHELD | RIG_FLAG_APRS | RIG_FLAG_TNC | RIG_FLAG_DXCLUSTER,
1650 .ptt_type = RIG_PTT_RIG,
1651 .dcd_type = RIG_DCD_RIG,
1652 .port_type = RIG_PORT_SERIAL,
1653 .serial_rate_min = 9600,
1654 .serial_rate_max = 9600,
1655 .serial_data_bits = 8,
1656 .serial_stop_bits = 1,
1657 .serial_parity = RIG_PARITY_NONE,
1658 .serial_handshake = RIG_HANDSHAKE_XONXOFF,
1659 .write_delay = 0,
1660 .post_write_delay = 0,
1661 .timeout = 500,
1662 .retry = 3,
1663
1664 .has_get_func = THD74_FUNC_ALL,
1665 .has_set_func = THD74_FUNC_ALL,
1666 .has_get_level = THD74_LEVEL_ALL,
1667 .has_set_level = RIG_LEVEL_SET(THD74_LEVEL_ALL),
1668 .has_get_parm = THD74_PARMS,
1669 .has_set_parm = THD74_PARMS,
1670 .level_gran = {
1671 [LVL_RAWSTR] = { .min = { .i = 0 }, .max = { .i = 5 } },
1672 [LVL_SQL] = { .min = { .i = 0 }, .max = { .i = 5 } },
1673 [LVL_RFPOWER] = { .min = { .i = 2 }, .max = { .i = 0 } },
1674 },
1675 .parm_gran = {},
1676 .ctcss_list = kenwood38_ctcss_list,
1677 .dcs_list = NULL,
1678 .preamp = { RIG_DBLST_END, },
1679 .attenuator = { RIG_DBLST_END, },
1680 .max_rit = Hz(0),
1681 .max_xit = Hz(0),
1682 .max_ifshift = Hz(0),
1683 .vfo_ops = THD74_VFO_OP,
1684 .targetable_vfo = RIG_TARGETABLE_FREQ,
1685 .transceive = RIG_TRN_RIG,
1686 .bank_qty = 0,
1687 .chan_desc_sz = 6, /* TBC */
1688 .chan_list = {
1689 { 0, 999, RIG_MTYPE_MEM, {TH_CHANNEL_CAPS}}, /* TBC MEM */
1690 RIG_CHAN_END,
1691 },
1692 .rx_range_list1 = { RIG_FRNG_END, }, /* FIXME: enter region 1 setting */
1693 .tx_range_list1 = { RIG_FRNG_END, },
1694 .rx_range_list2 = {
1695 {MHz(118), MHz(174), THD74_MODES, -1, -1, THD74_VFO},
1696 {MHz(320), MHz(524), THD74_MODES, -1, -1, THD74_VFO},
1697 RIG_FRNG_END,
1698 }, /* rx range */
1699 .tx_range_list2 = {
1700 {MHz(144), MHz(148), THD74_MODES_TX, W(0.05), W(5), THD74_VFO},
1701 {MHz(430), MHz(440), THD74_MODES_TX, W(0.05), W(5), THD74_VFO},
1702 RIG_FRNG_END,
1703 }, /* tx range */
1704
1705 .tuning_steps = {
1706 {THD74_MODES, kHz(5)},
1707 {THD74_MODES, kHz(6.25)},
1708 /* kHz(8.33) ?? */
1709 {THD74_MODES, kHz(10)},
1710 {THD74_MODES, kHz(12.5)},
1711 {THD74_MODES, kHz(15)},
1712 {THD74_MODES, kHz(20)},
1713 {THD74_MODES, kHz(25)},
1714 {THD74_MODES, kHz(30)},
1715 {THD74_MODES, kHz(50)},
1716 {THD74_MODES, kHz(100)},
1717 RIG_TS_END,
1718 },
1719 /* mode/filter list, remember: order matters! */
1720 .filters = {
1721 {RIG_MODE_FM, kHz(14)},
1722 {RIG_MODE_FMN, kHz(7)},
1723 {RIG_MODE_AM, kHz(9)},
1724 RIG_FLT_END,
1725 },
1726 .priv = (void *)& thd74_priv_caps,
1727
1728 .rig_init = kenwood_init,
1729 .rig_cleanup = kenwood_cleanup,
1730 .rig_open = kenwood_open,
1731 .set_freq = thd74_set_freq,
1732 .get_freq = thd74_get_freq,
1733 .set_mode = thd74_set_mode,
1734 .get_mode = thd74_get_mode,
1735 .set_vfo = thd74_set_vfo,
1736 .get_vfo = thd74_get_vfo,
1737 .set_ptt = thd74_set_ptt,
1738 .set_rptr_shift = thd74_set_rptr_shft,
1739 .get_rptr_shift = thd74_get_rptr_shft,
1740 .set_rptr_offs = thd74_set_rptr_offs,
1741 .get_rptr_offs = thd74_get_rptr_offs,
1742 .set_ts = thd74_set_ts,
1743 .get_ts = thd74_get_ts,
1744 .set_ctcss_tone = thd74_set_ctcss_tone,
1745 .get_ctcss_tone = thd74_get_ctcss_tone,
1746 .set_dcs_code = thd74_set_dcs_code,
1747 .get_dcs_code = thd74_get_dcs_code,
1748 .set_ctcss_sql = thd74_set_ctcss_sql,
1749 .get_ctcss_sql = thd74_get_ctcss_sql, .set_level = thd74_set_level,
1750 .get_level = thd74_get_level,
1751 .set_func = thd74_set_func,
1752 .get_func = thd74_get_func,
1753 .set_parm = thd74_set_parm,
1754 .get_parm = thd74_get_parm,
1755 .set_mem = thd74_set_mem,
1756 .get_mem = thd74_get_mem,
1757 .set_channel = thd74_set_channel,
1758 .get_channel = thd74_get_channel,
1759 .set_split_vfo = thd74_set_split_vfo,
1760 .get_split_vfo = thd74_get_split_vfo,
1761 .set_split_freq = thd74_set_split_freq,
1762 .get_split_freq = thd74_get_split_freq,
1763 //.get_chan_all_cb = thd74_get_chan_all_cb, this doesn't work yet
1764
1765 .get_info = th_get_info,
1766 };
1767