1 /*
2  *  Hamlib Kenwood backend - Elecraft K2 description
3  *  Copyright (c) 2002-2009 by Stephane Fillod
4  *  Copyright (c) 2010 by Nate Bargmann, n0nb@arrl.net
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  *  See the file 'COPYING.LIB' in the main Hamlib distribution directory for
21  *  the complete text of the GNU Lesser Public License version 2.1.
22  *
23  */
24 
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include <hamlib/rig.h>
33 #include "kenwood.h"
34 #include "elecraft.h"
35 
36 
37 #define K2_MODES (RIG_MODE_CW|RIG_MODE_CWR|RIG_MODE_SSB|RIG_MODE_PKTLSB|RIG_MODE_PKTUSB)
38 
39 #define K2_FUNC_ALL (RIG_FUNC_NB|RIG_FUNC_LOCK)
40 
41 #define K2_LEVEL_ALL (RIG_LEVEL_ATT|RIG_LEVEL_PREAMP|RIG_LEVEL_AGC|RIG_LEVEL_SQL|\
42     RIG_LEVEL_STRENGTH|RIG_LEVEL_RFPOWER|RIG_LEVEL_KEYSPD)
43 
44 #define K2_VFO (RIG_VFO_A|RIG_VFO_B)
45 #define K2_VFO_OP (RIG_OP_UP|RIG_OP_DOWN)
46 
47 #define K2_ANTS (RIG_ANT_1|RIG_ANT_2)
48 
49 static rmode_t k2_mode_table[KENWOOD_MODE_TABLE_MAX] =
50 {
51     [0] = RIG_MODE_NONE,
52     [1] = RIG_MODE_LSB,
53     [2] = RIG_MODE_USB,
54     [3] = RIG_MODE_CW,
55     [4] = RIG_MODE_NONE,
56     [5] = RIG_MODE_NONE,
57     [6] = RIG_MODE_PKTLSB,        /* AFSK */
58     [7] = RIG_MODE_CWR,
59     [8] = RIG_MODE_NONE,          /* TUNE mode */
60     [9] = RIG_MODE_PKTUSB         /* AFSK */
61 };
62 
63 /* kenwood_transaction() will add this to command strings
64  * sent to the rig and remove it from strings returned from
65  * the rig, so no need to append ';' manually to command strings.
66  */
67 static struct kenwood_priv_caps k2_priv_caps  =
68 {
69     .cmdtrm =  EOM_KEN,
70     .mode_table = k2_mode_table,
71 };
72 
73 
74 /* K2 Filter list, four per mode */
75 struct k2_filt_s
76 {
77     shortfreq_t width;  /* Filter width in Hz */
78     char fslot;     /* Crystal filter slot number--1-4 */
79     char afslot;        /* AF filter slot number--0-2 */
80 };
81 
82 /* Number of filter slot arrays to allocate (TNX Diane, VA3DB) */
83 #define K2_FILT_NUM 4
84 
85 /* K2 Filter List
86  *
87  * This struct will be populated as modes are queried or in response
88  * to a request to set a given mode.  This way a cache can be maintained
89  * of the installed filters and an appropriate filter can be selected
90  * for a requested bandwidth.  Each mode has up to four filter slots available.
91  */
92 struct k2_filt_lst_s
93 {
94     struct k2_filt_s filt_list[K2_FILT_NUM];
95 };
96 
97 struct k2_filt_lst_s k2_fwmd_ssb;
98 struct k2_filt_lst_s k2_fwmd_cw;
99 struct k2_filt_lst_s k2_fwmd_rtty;
100 
101 /* K2 specific rig_caps API function declarations */
102 int k2_open(RIG *rig);
103 int k2_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width);
104 int k2_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width);
105 int k2_get_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t *val);
106 
107 /* Private function declarations */
108 int k2_probe_mdfw(RIG *rig, struct kenwood_priv_data *priv);
109 int k2_mdfw_rest(RIG *rig, const char *mode, const char *fw);
110 int k2_pop_fw_lst(RIG *rig, const char *cmd);
111 
112 
113 /*
114  * KIO2 rig capabilities.
115  * This kit can recognize a large subset of TS-570 commands.
116  *
117  * Part of info comes from http://www.elecraft.com/K2_Manual_Download_Page.htm#K2
118  * look for KIO2 Programmer's Reference PDF
119  */
120 const struct rig_caps k2_caps =
121 {
122     RIG_MODEL(RIG_MODEL_K2),
123     .model_name =       "K2",
124     .mfg_name =     "Elecraft",
125     .version =      BACKEND_VER ".0",
126     .copyright =        "LGPL",
127     .status =       RIG_STATUS_BETA,
128     .rig_type =     RIG_TYPE_TRANSCEIVER,
129     .ptt_type =     RIG_PTT_RIG,
130     .dcd_type =     RIG_DCD_RIG,
131     .port_type =        RIG_PORT_SERIAL,
132     .serial_rate_min =  4800,
133     .serial_rate_max =  4800,
134     .serial_data_bits = 8,
135     .serial_stop_bits = 2,
136     .serial_parity =    RIG_PARITY_NONE,
137     .serial_handshake = RIG_HANDSHAKE_NONE,
138     .write_delay =      0,  /* Timing between bytes */
139     .post_write_delay = 100,    /* Timing between command strings */
140     // Note that 2000 timeout exceeds usleep but hl_usleep handles it
141     .timeout =      2000,   /* FA and FB make take up to 500 ms on band change */
142     .retry =        10,
143 
144     .has_get_func =     K2_FUNC_ALL,
145     .has_set_func =     K2_FUNC_ALL,
146     .has_get_level =    K2_LEVEL_ALL,
147     .has_set_level =    RIG_LEVEL_SET(K2_LEVEL_ALL),
148     .has_get_parm =     RIG_PARM_NONE,
149     .has_set_parm =     RIG_PARM_NONE,  /* FIXME: parms */
150     .level_gran =       {},     /* FIXME: granularity */
151     .parm_gran =        {},
152     .extlevels =        elecraft_ext_levels,
153     .extparms =     kenwood_cfg_params,
154     .preamp =       { 14, RIG_DBLST_END, },
155     .attenuator =       { 10, RIG_DBLST_END, },
156     .max_rit =      Hz(9990),
157     .max_xit =      Hz(9990),
158     .max_ifshift =      Hz(0),
159     .vfo_ops =      K2_VFO_OP,
160     .targetable_vfo =   RIG_TARGETABLE_FREQ,
161     .transceive =       RIG_TRN_RIG,
162     .bank_qty =     0,
163     .chan_desc_sz =     0,
164 
165     .chan_list =        { RIG_CHAN_END },
166 
167     .rx_range_list1 =  {
168         {kHz(500), MHz(30), K2_MODES, -1, -1, K2_VFO, K2_ANTS},
169         RIG_FRNG_END,
170     }, /* rx range */
171     .tx_range_list1 =  {
172         {kHz(1810), kHz(1850) - 1, K2_MODES, 10, W(15), K2_VFO, K2_ANTS}, /* 15W class */
173         {kHz(3500), kHz(3800) - 1, K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
174         {MHz(7), kHz(7100), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
175         {kHz(10100), kHz(10150), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
176         {MHz(14), kHz(14350), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
177         {kHz(18068), kHz(18168), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
178         {MHz(21), kHz(21450), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
179         {kHz(24890), kHz(24990), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
180         {MHz(28), kHz(29700), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
181         RIG_FRNG_END,
182     }, /* tx range */
183 
184     .rx_range_list2 =  {
185         {kHz(500), MHz(30), K2_MODES, -1, -1, K2_VFO, K2_ANTS},
186         RIG_FRNG_END,
187     }, /* rx range */
188     .tx_range_list2 =  {
189         {kHz(1800), MHz(2) - 1, K2_MODES, 10, W(15), K2_VFO, K2_ANTS}, /* 15W class */
190         {kHz(3500), MHz(4) - 1, K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
191         {MHz(7), kHz(7300), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
192         {kHz(10100), kHz(10150), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
193         {MHz(14), kHz(14350), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
194         {kHz(18068), kHz(18168), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
195         {MHz(21), kHz(21450), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
196         {kHz(24890), kHz(24990), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
197         {MHz(28), kHz(29700), K2_MODES, 10, W(15), K2_VFO, K2_ANTS},
198         RIG_FRNG_END,
199     }, /* tx range */
200     .tuning_steps =  {
201         {K2_MODES, 10},
202         RIG_TS_END,
203     },
204 
205     /* mode/filter list, remember: order matters! */
206     .filters =  {
207         {RIG_MODE_SSB, kHz(2.5)},
208         {RIG_MODE_CW | RIG_MODE_CWR, Hz(500)},
209         {RIG_MODE_PKTLSB | RIG_MODE_PKTUSB, kHz(2.5)},
210         RIG_FLT_END,
211     },
212     .priv = (void *)& k2_priv_caps,
213 
214     .rig_init =     kenwood_init,
215     .rig_cleanup =      kenwood_cleanup,
216     .rig_open =     k2_open,
217     .rig_close =        kenwood_close,
218     .set_freq =     kenwood_set_freq,
219     .get_freq =     kenwood_get_freq,
220     .set_mode =     k2_set_mode,
221     .get_mode =     k2_get_mode,
222     .set_vfo =      kenwood_set_vfo,
223     .get_vfo =      kenwood_get_vfo_if,
224     .set_split_vfo =    kenwood_set_split_vfo,
225     .get_split_vfo =    kenwood_get_split_vfo_if,
226     .set_rit =      kenwood_set_rit,
227     .get_rit =      kenwood_get_rit,
228     .set_xit =      kenwood_set_xit,
229     .get_xit =      kenwood_get_xit,
230     .get_ptt =      kenwood_get_ptt,
231     .set_ptt =      kenwood_set_ptt,
232     .get_dcd =      kenwood_get_dcd,
233     .set_func =     kenwood_set_func,
234     .get_func =     kenwood_get_func,
235     .set_ext_parm =     kenwood_set_ext_parm,
236     .get_ext_parm =     kenwood_get_ext_parm,
237     .set_level =        kenwood_set_level,
238     .get_level =        kenwood_get_level,
239     .get_ext_level =    k2_get_ext_level,
240     .vfo_op =       kenwood_vfo_op,
241     .set_trn =      kenwood_set_trn,
242     .get_powerstat =    kenwood_get_powerstat,
243     .get_trn =      kenwood_get_trn,
244     .set_ant =      kenwood_set_ant,
245     .get_ant =      kenwood_get_ant,
246     .send_morse =       kenwood_send_morse,
247     .wait_morse =       rig_wait_morse
248 };
249 
250 
251 /*
252  * K2 extension function definitions follow
253  */
254 
255 /* k2_open()
256  *
257  */
k2_open(RIG * rig)258 int k2_open(RIG *rig)
259 {
260     int err;
261     struct kenwood_priv_data *priv = rig->state.priv;
262 
263     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
264 
265     err = elecraft_open(rig);
266 
267     if (err != RIG_OK)
268     {
269         return err;
270     }
271 
272     err = k2_probe_mdfw(rig, priv);
273 
274     if (err != RIG_OK)
275     {
276         return err;
277     }
278 
279     return RIG_OK;
280 }
281 
282 
283 /* k2_set_mode()
284  *
285  * Based on the passed in bandwidth, looks up the nearest bandwidth filter
286  * wider than the passed value and sets the radio accordingly.
287  */
288 
k2_set_mode(RIG * rig,vfo_t vfo,rmode_t mode,pbwidth_t width)289 int k2_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
290 {
291 
292     int err;
293     char f = '*';
294     struct k2_filt_lst_s *flt;
295     struct kenwood_priv_data *priv = rig->state.priv;
296 
297     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
298 
299     /* Select the filter array per mode. */
300     switch (mode)
301     {
302     case RIG_MODE_LSB:
303     case RIG_MODE_USB:
304         flt = &k2_fwmd_ssb;
305         break;
306 
307     case RIG_MODE_CW:
308     case RIG_MODE_CWR:
309         flt = &k2_fwmd_cw;
310         break;
311 
312     case RIG_MODE_PKTLSB:
313     case RIG_MODE_PKTUSB:
314         if (priv->k2_md_rtty == 0)
315         {
316             return -RIG_EINVAL;    /* RTTY module not installed */
317         }
318         else
319         {
320             flt = &k2_fwmd_rtty;
321         }
322 
323         break;
324 
325     default:
326         return -RIG_EINVAL;
327     }
328 
329     if (width != RIG_PASSBAND_NOCHANGE)
330     {
331         shortfreq_t freq = 0;
332 
333         if (width < 0)
334         {
335             width = labs(width);
336         }
337 
338         /* Step through the filter list looking for the best match
339          * for the passed in width.  The choice is to select the filter
340          * that is wide enough for the width without being too narrow
341          * if possible.
342          */
343         if (width == RIG_PASSBAND_NORMAL)
344         {
345             width = rig_passband_normal(rig, mode);
346         }
347 
348         if ((width > flt->filt_list[0].width) || (width > flt->filt_list[1].width))
349         {
350             width = flt->filt_list[0].width;
351             f = '1';
352         }
353         else if ((flt->filt_list[1].width >= width)
354                  && (width > flt->filt_list[2].width))
355         {
356             width = flt->filt_list[1].width;
357             f = '2';
358         }
359         else if ((flt->filt_list[2].width >= width)
360                  && (width > flt->filt_list[3].width))
361         {
362             width = flt->filt_list[2].width;
363             f = '3';
364         }
365         else if ((flt->filt_list[3].width >= width) && (width >= freq))
366         {
367             width = flt->filt_list[3].width;
368             f = '4';
369         }
370         else
371         {
372             return -RIG_EINVAL;
373         }
374     }
375 
376     /* kenwood_set_mode() ignores width value for K2/K3/TS-570 */
377     err = kenwood_set_mode(rig, vfo, mode, width);
378 
379     if (err != RIG_OK)
380     {
381         return err;
382     }
383 
384     if (width != RIG_PASSBAND_NOCHANGE)
385     {
386         char fcmd[16];
387 
388         err = kenwood_transaction(rig, "K22", NULL, 0);
389 
390         if (err != RIG_OK)
391         {
392             return err;
393         }
394 
395         /* Construct the filter command and set the radio mode and width*/
396         snprintf(fcmd, 8, "FW0000%c", f);
397 
398         /* Set the filter slot */
399         err = kenwood_transaction(rig, fcmd, NULL, 0);
400 
401         if (err != RIG_OK)
402         {
403             return err;
404         }
405 
406         err = kenwood_transaction(rig, "K20", NULL, 0);
407 
408         if (err != RIG_OK)
409         {
410             return err;
411         }
412     }
413 
414     return RIG_OK;
415 }
416 
417 
418 /* k2_get_mode()
419  *
420  * Uses the FW command in K22 mode to query the filter bandwidth reported
421  * by the radio and returns it to the caller.
422  */
423 
k2_get_mode(RIG * rig,vfo_t vfo,rmode_t * mode,pbwidth_t * width)424 int k2_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
425 {
426     int err;
427     char buf[KENWOOD_MAX_BUF_LEN];
428     char tmp[16];
429     char *bufptr;
430     pbwidth_t temp_w;
431 
432     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
433 
434     if (!mode || !width)
435     {
436         return -RIG_EINVAL;
437     }
438 
439     err = kenwood_get_mode(rig, vfo, mode, &temp_w);
440 
441     if (err != RIG_OK)
442     {
443         return err;
444     }
445 
446     err = kenwood_transaction(rig, "K22", NULL, 0);
447 
448     if (err != RIG_OK)
449     {
450         return err;
451     }
452 
453     err = kenwood_safe_transaction(rig, "FW", buf, KENWOOD_MAX_BUF_LEN, 8);
454 
455     if (err != RIG_OK)
456     {
457         return err;
458     }
459 
460     err = kenwood_transaction(rig, "K20", NULL, 0);
461 
462     if (err != RIG_OK)
463     {
464         return err;
465     }
466 
467     /* Convert received filter string value's first four digits to width */
468     bufptr = buf;
469 
470     strncpy(tmp, bufptr + 2, 4);
471     tmp[4] = '\0';
472     *width = atoi(tmp);
473 
474     rig_debug(RIG_DEBUG_VERBOSE, "%s: Mode: %s, Width: %d\n", __func__,
475               rig_strrmode(*mode), (int)*width);
476 
477     return RIG_OK;
478 }
479 
480 
481 /* TQ command is a quick transmit status query--K2/K3 only.
482  *
483  * token    Defined in elecraft.h or this file
484  * val      Type depends on token type from confparams structure:
485  *      NUMERIC: val.f
486  *      COMBO: val.i, starting from 0 Index to a string table.
487  *      STRING: val.cs for set, val.s for get
488  *      CHECKBUTTON: val.i 0/1
489  */
k2_get_ext_level(RIG * rig,vfo_t vfo,token_t token,value_t * val)490 int k2_get_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t *val)
491 {
492     char buf[KENWOOD_MAX_BUF_LEN];
493     int err;
494     const struct confparams *cfp;
495 
496     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
497 
498     if (!val)
499     {
500         return -RIG_EINVAL;
501     }
502 
503     cfp = rig_ext_lookup_tok(rig, token);
504 
505     switch (token)
506     {
507     case TOK_TX_STAT:
508         err = kenwood_safe_transaction(rig, "TQ", buf, KENWOOD_MAX_BUF_LEN, 3);
509 
510         if (err != RIG_OK)
511         {
512             return err;
513         }
514 
515         if (cfp->type == RIG_CONF_CHECKBUTTON)
516         {
517             val->i = atoi(&buf[2]);
518         }
519         else
520         {
521             rig_debug(RIG_DEBUG_ERR, "%s: protocol error, invalid token type\n",
522                       __func__);
523             return -RIG_EPROTO;
524         }
525 
526         break;
527 
528     default:
529         rig_debug(RIG_DEBUG_WARN, "%s: Unsupported get_ext_level %s\n",
530                   __func__, rig_strlevel(token));
531         return -RIG_EINVAL;
532     }
533 
534     return RIG_OK;
535 }
536 
537 
538 /* K2 private helper functions follow */
539 
540 /* Probes for mode and filter settings, based on information
541  * by Chris Bryant, G3WIE.
542  */
k2_probe_mdfw(RIG * rig,struct kenwood_priv_data * priv)543 int k2_probe_mdfw(RIG *rig, struct kenwood_priv_data *priv)
544 {
545     int err, i, c;
546     char buf[KENWOOD_MAX_BUF_LEN];
547     char mode[16];
548     char fw[16];
549     char cmd[16];
550 
551     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
552 
553     if (!priv)
554     {
555         return -RIG_EINVAL;
556     }
557 
558     /* The K2 extension level has been stored by elecraft_open().  Now set rig
559      * to K22 for detailed query of mode and filter width values...
560      */
561     err = kenwood_transaction(rig, "K22", NULL, 0);
562 
563     if (err != RIG_OK)
564     {
565         return err;
566     }
567 
568     /* Check for mode and store it for later. */
569     err = kenwood_safe_transaction(rig, "MD", buf, KENWOOD_MAX_BUF_LEN, 3);
570 
571     if (err != RIG_OK)
572     {
573         return err;
574     }
575 
576     strcpy(mode, buf);
577 
578     /* Check for filter width and store it for later. */
579     err = kenwood_safe_transaction(rig, "FW", buf, KENWOOD_MAX_BUF_LEN, 8);
580 
581     if (err != RIG_OK)
582     {
583         return err;
584     }
585 
586     strcpy(fw, buf);
587 
588     rig_debug(RIG_DEBUG_VERBOSE, "%s: Mode value: %s, Filter Width value: %s\n",
589               __func__, mode, fw);
590 
591     /* Now begin the process of querying the available modes and filters. */
592 
593     /* First try to put the K2 into RTTY mode and check if it's available. */
594     priv->k2_md_rtty = 0;       /* Assume RTTY module not installed */
595     err = kenwood_transaction(rig, "MD6", NULL, 0);
596 
597     if (err != RIG_OK && err != -RIG_ERJCTED)
598     {
599         return err;
600     }
601 
602     if (RIG_OK == err)
603     {
604         /* Read back mode and test to see if K2 reports RTTY. */
605         err = kenwood_safe_transaction(rig, "MD", buf, KENWOOD_MAX_BUF_LEN, 3);
606 
607         if (err != RIG_OK)
608         {
609             return err;
610         }
611 
612         if (!strcmp("MD6", buf))
613         {
614             priv->k2_md_rtty = 1;    /* set flag for RTTY mode enabled */
615         }
616     }
617 
618     rig_debug(RIG_DEBUG_VERBOSE, "%s: RTTY flag is: %d\n", __func__,
619               priv->k2_md_rtty);
620 
621     i = (priv->k2_md_rtty == 1) ? 2 : 1;
622 
623     /* Now loop through the modes checking for installed filters. */
624     for (c = 0; i > -1; i--, c++)
625     {
626         if (c == 0)
627         {
628             strcpy(cmd, "MD1");    /* SSB */
629         }
630         else if (c == 1)
631         {
632             strcpy(cmd, "MD3");    /* CW */
633         }
634         else if (c == 2)
635         {
636             strcpy(cmd, "MD6");    /* RTTY */
637         }
638         else                    /* Oops! */
639         {
640             err = k2_mdfw_rest(rig, mode, fw);
641 
642             if (err != RIG_OK)
643             {
644                 return err;
645             }
646 
647             return -RIG_EINVAL;
648         }
649 
650         /* Now populate the Filter arrays */
651         err = k2_pop_fw_lst(rig, cmd);
652 
653         if (err != RIG_OK)
654         {
655             return err;
656         }
657     }
658 
659     /* Restore mode, filter, extension level */
660     if (strlen(fw) == 8)
661     {
662         fw[7] = '\0';    /* Truncate AFSlot to set filter slot */
663     }
664 
665     err = k2_mdfw_rest(rig, mode, fw);
666 
667     if (err != RIG_OK)
668     {
669         return err;
670     }
671 
672     return RIG_OK;
673 }
674 
675 
676 /* Restore mode, filter, and ext_lvl to original values */
k2_mdfw_rest(RIG * rig,const char * mode,const char * fw)677 int k2_mdfw_rest(RIG *rig, const char *mode, const char *fw)
678 {
679     int err;
680 
681     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
682 
683     if (!mode || !fw)
684     {
685         return -RIG_EINVAL;
686     }
687 
688     if (strlen(mode) != 3 || strlen(fw) != 7)
689     {
690         return -RIG_EINVAL;
691     }
692 
693     err = kenwood_transaction(rig, mode, NULL, 0);
694 
695     if (err != RIG_OK)
696     {
697         return err;
698     }
699 
700     err = kenwood_transaction(rig, fw, NULL, 0);
701 
702     if (err != RIG_OK)
703     {
704         return err;
705     }
706 
707     err = kenwood_transaction(rig, "K20", NULL, 0);
708 
709     if (err != RIG_OK)
710     {
711         return err;
712     }
713 
714     return RIG_OK;
715 }
716 
717 
718 /* Populate k2_filt_lst_s structure for each mode */
k2_pop_fw_lst(RIG * rig,const char * cmd)719 int k2_pop_fw_lst(RIG *rig, const char *cmd)
720 {
721     int err, f;
722     char fcmd[16];
723     char buf[KENWOOD_MAX_BUF_LEN];
724     char tmp[16];
725     struct k2_filt_lst_s *flt;
726 
727     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
728 
729     if (!cmd)
730     {
731         return -RIG_EINVAL;
732     }
733 
734     /* Store filter data in the correct structure depending on mode */
735     if (strcmp(cmd, "MD1") == 0)
736     {
737         flt = &k2_fwmd_ssb;
738     }
739     else if (strcmp(cmd, "MD3") == 0)
740     {
741         flt = &k2_fwmd_cw;
742     }
743     else if (strcmp(cmd, "MD6") == 0)
744     {
745         flt = &k2_fwmd_rtty;
746     }
747     else
748     {
749         return -RIG_EINVAL;
750     }
751 
752     /* Set the mode */
753     err = kenwood_transaction(rig, cmd, NULL, 0);
754 
755     if (err != RIG_OK)
756     {
757         return err;
758     }
759 
760     for (f = 1; f < 5; f++)
761     {
762         char *bufptr = buf;
763 
764         snprintf(fcmd, 8, "FW0000%d", f);
765 
766         err = kenwood_transaction(rig, fcmd, NULL, 0);
767 
768         if (err != RIG_OK)
769         {
770             return err;
771         }
772 
773         err = kenwood_safe_transaction(rig, "FW", buf, KENWOOD_MAX_BUF_LEN, 8);
774 
775         if (err != RIG_OK)
776         {
777             return err;
778         }
779 
780         /* buf should contain a string "FWxxxxfa;" which corresponds to:
781          * xxxx = filter width in Hz
782          * f = crystal filter slot number--1-4
783          * a = audio filter slot number--0-2
784          */
785         strncpy(tmp, bufptr + 2, 4);
786         tmp[4] = '\0';
787         flt->filt_list[f - 1].width = atoi(tmp);
788 
789         strncpy(tmp, bufptr + 6, 1);
790         tmp[1] = '\0';
791         flt->filt_list[f - 1].fslot = atoi(tmp);
792 
793         strncpy(tmp, bufptr + 7, 1);
794         tmp[1] = '\0';
795         flt->filt_list[f - 1].afslot = atoi(tmp);
796 
797         rig_debug(RIG_DEBUG_VERBOSE, "%s: Width: %04li, FSlot: %i, AFSlot %i\n",
798                   __func__, flt->filt_list[f - 1].width, flt->filt_list[f - 1].fslot,
799                   flt->filt_list[f - 1].afslot);
800     }
801 
802     return RIG_OK;
803 }
804 
805