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