1 /*
2  *  Hamlib AOR backend - AR7030 Plus description
3  *  Copyright (c) 2000-2010 by Stephane Fillod & Fritz Melchert
4  *  Copyright (c) 2009-2010 by Larry Gadallah (VE6VQ)
5  *
6  *
7  *   This library is free software; you can redistribute it and/or
8  *   modify it under the terms of the GNU Lesser General Public
9  *   License as published by the Free Software Foundation; either
10  *   version 2.1 of the License, or (at your option) any later version.
11  *
12  *   This library is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *   Lesser General Public License for more details.
16  *
17  *   You should have received a copy of the GNU Lesser General Public
18  *   License along with this library; if not, write to the Free Software
19  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22 
23 /*
24  * Version 2009.11.21 Larry Gadallah (VE6VQ)
25  */
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 
31 #include <stdio.h>
32 #include <string.h>
33 #include <math.h>
34 #include <assert.h>
35 #include <stdlib.h>
36 
37 #include "hamlib/rig.h"
38 #include "ar7030p.h"
39 #include "serial.h"
40 #include "idx_builtin.h"
41 
42 #define AR7030P_MODES ( RIG_MODE_AM | \
43                         RIG_MODE_SSB | \
44                         RIG_MODE_CW | \
45                         RIG_MODE_RTTY | \
46                         RIG_MODE_FM | \
47                         RIG_MODE_AMS )
48 
49 #define AR7030P_FUNC ( RIG_FUNC_FAGC | \
50                        RIG_FUNC_NB | \
51                        RIG_FUNC_ANF | \
52                        RIG_FUNC_AIP | \
53                        RIG_FUNC_MN | \
54                        RIG_FUNC_RF | \
55                        RIG_FUNC_LOCK | \
56                        RIG_FUNC_MUTE | \
57                        RIG_FUNC_SQL )
58 
59 #define AR7030P_LEVEL ( RIG_LEVEL_PREAMP | \
60                         RIG_LEVEL_ATT | \
61                         RIG_LEVEL_AF | \
62                         RIG_LEVEL_RF | \
63                         RIG_LEVEL_SQL | \
64                         RIG_LEVEL_PBT_IN | \
65                         RIG_LEVEL_CWPITCH | \
66                         RIG_LEVEL_NOTCHF | \
67                         RIG_LEVEL_AGC | \
68                         RIG_LEVEL_RAWSTR | \
69                         RIG_LEVEL_STRENGTH )
70 
71 #define AR7030P_PARM ( RIG_PARM_APO | \
72                        RIG_PARM_TIME | \
73                        RIG_PARM_BAT )
74 
75 #define AR7030P_VFO_OPS ( RIG_OP_CPY | \
76                           RIG_OP_XCHG | \
77                           RIG_OP_TOGGLE )
78 
79 #define AR7030P_VFO ( RIG_VFO_A | \
80                       RIG_VFO_B)
81 
82 #define AR7030P_STR_CAL { 8, { \
83                                { 10, -113 }, \
84                            { 10, -103 }, \
85                        { 10,  -93 }, \
86                        { 10,  -83 }, \
87                        { 10,  -73 }, \
88                        { 10,  -63 }, \
89                        { 20,  -43 }, \
90                        { 20,  -23 }, \
91                      } }
92 
93 /* Channel capabilities
94    - Frequency
95    - Mode
96    - Width
97    - Scan lockout
98    - PBT
99    - Squelch
100    - ID
101  */
102 #define AR7030P_MEM_CAP { \
103     .freq = 1,  \
104     .mode = 1,  \
105     .width = 1, \
106     .funcs = RIG_FUNC_NONE, \
107     .levels = RIG_LEVEL_SQL | RIG_LEVEL_PBT_IN, \
108         .flags = 1, \
109         .channel_desc = 1 \
110 }
111 
112 struct ar7030p_priv_caps
113 {
114     int max_freq_len;
115     int info_len;
116     int mem_len;
117     int pbs_info_len;
118     int pbs_len;
119     int chan_num;
120 };
121 
122 static const struct ar7030p_priv_caps ar7030p_priv_caps =
123 {
124     .max_freq_len = 3,
125     .info_len = 14,
126     .mem_len = 17,
127     .pbs_info_len = 1,
128     .pbs_len = 1,
129     .chan_num = 0,
130 };
131 
132 #define NB_CHAN 400     /* see caps->chan_list */
133 
134 struct ar7030p_priv_data
135 {
136     vfo_t curr_vfo;
137     vfo_t last_vfo;   /* VFO A or VFO B, when in MEM mode */
138 
139     powerstat_t powerstat;
140     int bank;
141     value_t parms[ RIG_SETTING_MAX ];
142 
143     channel_t *curr;  /* points to vfo_a, vfo_b or mem[] */
144 
145     channel_t vfo_a;
146     channel_t vfo_b;
147     channel_t mem[ NB_CHAN ];
148 
149     struct ext_list *ext_parms;
150 };
151 
152 static const struct confparams ar7030p_ext_levels[] =
153 {
154     {
155         TOK_EL_MAGICLEVEL, "MGL", "Magic level", "Magic level, as an example",
156         NULL, RIG_CONF_NUMERIC, { .n = { 0, 1, .001 } }
157     },
158 
159     {
160         TOK_EL_MAGICFUNC, "MGF", "Magic func", "Magic function, as an example",
161         NULL, RIG_CONF_CHECKBUTTON
162     },
163 
164     {
165         TOK_EL_MAGICOP, "MGO", "Magic Op", "Magic Op, as an example",
166         NULL, RIG_CONF_BUTTON
167     },
168 
169     { RIG_CONF_END, NULL, }
170 };
171 
172 static const struct confparams ar7030p_ext_parms[] =
173 {
174     {
175         TOK_EP_MAGICPARM, "MGP", "Magic parm", "Magic parameter, as an example",
176         NULL, RIG_CONF_NUMERIC, { .n = { 0, 1, .001 } }
177     },
178 
179     { RIG_CONF_END, NULL, }
180 };
181 
182 /* TODO - move this somewhere where it belongs */
183 static unsigned int filterTab[ 6 + 1 ] = { 0 };
184 
185 
init_chan(RIG * rig,vfo_t vfo,channel_t * chan)186 static void init_chan(RIG *rig, vfo_t vfo, channel_t *chan)
187 {
188     assert(NULL != rig);
189     assert(NULL != chan);
190 
191     chan->channel_num = 0;
192     chan->vfo = vfo;
193 
194     strcpy(chan->channel_desc, rig_strvfo(vfo));
195 
196     chan->freq = MHz(10);
197     chan->mode = RIG_MODE_AM;
198     chan->width = rig_passband_normal(rig, RIG_MODE_AM);
199 
200     chan->tuning_step = 110;
201 
202     chan->funcs = (setting_t) 0;
203 
204     memset(chan->levels, 0, RIG_SETTING_MAX * sizeof(value_t));
205 }
206 
alloc_init_ext(const struct confparams * cfp)207 static struct ext_list *alloc_init_ext(const struct confparams *cfp)
208 {
209     struct ext_list *elp;
210     int i, nb_ext;
211 
212     assert(NULL != cfp);
213 
214     for (nb_ext = 0; !RIG_IS_EXT_END(cfp[nb_ext]); nb_ext++)
215     {
216         ;
217     }
218 
219     elp = calloc((nb_ext + 1), sizeof(struct ext_list));
220 
221     if (!elp)
222     {
223         return NULL;
224     }
225 
226     for (i = 0; !RIG_IS_EXT_END(cfp[i]); i++)
227     {
228         elp[i].token = cfp[i].token;
229         /* value reset already by calloc */
230     }
231 
232     /* last token in array is set to 0 by calloc */
233     return elp;
234 }
235 
236 #if 0 /* unused; re-enabled as needed. */
237 static struct ext_list *find_ext(struct ext_list *elp, token_t token)
238 {
239     int i;
240 
241     for (i = 0; elp[ i ].token != 0; i++)
242     {
243         if (elp[ i ].token == token)
244         {
245             return &(elp[ i ]);
246         }
247     }
248 
249     return NULL;
250 }
251 #endif /* unused */
252 
ar7030p_init(RIG * rig)253 static int ar7030p_init(RIG *rig)
254 {
255     struct ar7030p_priv_data *priv;
256     int rc = RIG_OK;
257 
258     assert(NULL != rig);
259 
260     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
261 
262     priv = (struct ar7030p_priv_data *)
263            malloc(sizeof(struct ar7030p_priv_data));
264 
265     if (!priv)
266     {
267         rc = -RIG_ENOMEM;
268     }
269     else
270     {
271         int i;
272 
273         rig->state.priv = (void *) priv;
274 
275         rig->state.rigport.type.rig = RIG_PORT_SERIAL;
276 
277         priv->powerstat = RIG_POWER_ON;
278         priv->bank = 0;
279 
280         memset(priv->parms, 0, RIG_SETTING_MAX * sizeof(value_t));
281 
282         memset(priv->mem, 0, sizeof(priv->mem));
283 
284         for (i = 0; i < NB_CHAN; i++)
285         {
286             priv->mem[ i ].channel_num = i;
287             priv->mem[ i ].vfo = RIG_VFO_MEM;
288 
289             priv->mem[ i ].ext_levels = alloc_init_ext(ar7030p_ext_levels);
290 
291             if (!priv->mem[ i ].ext_levels)
292             {
293                 rc = -RIG_ENOMEM;
294                 break;
295             }
296         }
297 
298         if (RIG_OK == rc)
299         {
300             priv->vfo_a.ext_levels = alloc_init_ext(ar7030p_ext_levels);
301 
302             if (!priv->vfo_a.ext_levels)
303             {
304                 return -RIG_ENOMEM;
305             }
306             else
307             {
308                 priv->vfo_b.ext_levels = alloc_init_ext(ar7030p_ext_levels);
309             }
310 
311             if (!priv->vfo_b.ext_levels)
312             {
313                 return -RIG_ENOMEM;
314             }
315 
316             priv->ext_parms = alloc_init_ext(ar7030p_ext_parms);
317 
318             if (!priv->ext_parms)
319             {
320                 return -RIG_ENOMEM;
321             }
322 
323             init_chan(rig, RIG_VFO_A, &priv->vfo_a);
324             init_chan(rig, RIG_VFO_B, &priv->vfo_b);
325 
326             priv->curr = &priv->vfo_a;
327             priv->curr_vfo = priv->last_vfo = RIG_VFO_A;
328         }
329     }
330 
331     return (rc);
332 }
333 
ar7030p_cleanup(RIG * rig)334 static int ar7030p_cleanup(RIG *rig)
335 {
336     struct ar7030p_priv_data *priv = (struct ar7030p_priv_data *) rig->state.priv;
337     int rc = RIG_OK;
338     int i;
339 
340     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
341 
342     for (i = 0; i < NB_CHAN; i++)
343     {
344         free(priv->mem[ i ].ext_levels);
345     }
346 
347     free(priv->vfo_a.ext_levels);
348     free(priv->vfo_b.ext_levels);
349 
350     free(priv->ext_parms);
351 
352     if (NULL != rig->state.priv)
353     {
354         free(rig->state.priv);
355     }
356 
357     rig->state.priv = NULL;
358 
359     return (rc);
360 }
361 
362 /*
363  * /brief Open I/O to receiver
364  *
365  * /param rig Pointer to rig struct
366  *
367  * /return 0 on success, < 0 on failure
368  */
ar7030p_open(RIG * rig)369 static int ar7030p_open(RIG *rig)
370 {
371     int rc = RIG_OK;
372     unsigned char v;
373 
374     assert(NULL != rig);
375 
376     rc = lockRx(rig, LOCK_1);
377 
378     if (RIG_OK == rc)
379     {
380         int i;
381 
382         /* Load calibration table */
383         rig->state.str_cal.size = rig->caps->str_cal.size;
384 
385         for (i = 0; i < rig->state.str_cal.size; i++)
386         {
387             rc = readByte(rig, EEPROM1, SM_CAL + i, &v);
388 
389             if (RIG_OK != rc)
390             {
391                 break;
392             }
393 
394             rig->state.str_cal.table[ i ].val = rig->caps->str_cal.table[ i ].val;
395             rig->state.str_cal.table[ i ].raw = (int) v;
396 
397             rig_debug(RIG_DEBUG_VERBOSE, "%s: index %d, val %d, raw %d\n",
398                       __func__, i, rig->state.str_cal.table[ i ].val,
399                       rig->state.str_cal.table[ i ].raw);
400         }
401 
402         if (RIG_OK == rc)
403         {
404             /* Load filter BW table */
405             for (i = 1; i <= 6; i++)
406             {
407                 rc = getFilterBW(rig, i);
408 
409                 if (rc < 0)
410                 {
411                     rig_debug(RIG_DEBUG_ERR, "%s: err in getFilterBW: %s\n", __func__,
412                               rigerror(rc));
413                     return rc;
414                 }
415                 else
416                 {
417                     filterTab[i] = (unsigned int) rc;
418                 }
419             }
420         }
421 
422         rc = lockRx(rig, LOCK_0);
423 
424         rig_debug(RIG_DEBUG_VERBOSE, "%s: \n", __func__);
425     }
426 
427     return (rc);
428 }
429 
430 /*
431  * /brief Close I/O to receiver
432  *
433  * /param rig Pointer to rig struct
434  *
435  * /return 0 on success, < 0 on failure
436  */
ar7030p_close(RIG * rig)437 static int ar7030p_close(RIG *rig)
438 {
439     assert(NULL != rig);
440 
441     rig_debug(RIG_DEBUG_VERBOSE, "%s: \n", __func__);
442 
443     return (RIG_OK);
444 }
445 
ar7030p_get_info(RIG * rig)446 static const char *ar7030p_get_info(RIG *rig)
447 {
448     static char version[10] = "";
449     unsigned int i;
450     char *p = &(version[ 0 ]);
451 
452     assert(NULL != rig);
453 
454     for (i = 0; i < pageSize(ROM); i++)
455     {
456         if (RIG_OK != readByte(rig, ROM, i, (unsigned char *) p++))
457         {
458             p = NULL;
459             break;
460         }
461     }
462 
463     if (NULL != p)
464     {
465         *p++ = '\0';
466         p = &(version[ 0 ]);
467 
468         rig_debug(RIG_DEBUG_VERBOSE, "%s: ident - %s\n", __func__, version);
469     }
470 
471     return (p);
472 }
473 
474 /*
475  * /brief Set receiver frequency
476  *
477  * /param rig Pointer to rig struct
478  * /param vfo VFO to operate on
479  * /param freq Frequency to set
480  *
481  */
ar7030p_set_freq(RIG * rig,vfo_t vfo,freq_t freq)482 static int ar7030p_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
483 {
484     int rc = RIG_OK;
485 
486     assert(NULL != rig);
487 
488     rc = lockRx(rig, LOCK_1);
489 
490     if (RIG_OK == rc)
491     {
492         const struct rig_caps *caps = rig->caps;
493 
494         if ((caps->rx_range_list1[ 0 ].endf   > freq) &&
495                 (caps->rx_range_list1[ 0 ].startf < freq))
496         {
497             switch (vfo)
498             {
499             case RIG_VFO_CURR:
500             case RIG_VFO_A:
501                 rc = write3Bytes(rig, WORKING, FREQU, hzToDDS(freq));
502                 break;
503 
504             case RIG_VFO_B:
505                 rc = write3Bytes(rig, WORKING, FREQU_B, hzToDDS(freq));
506                 break;
507 
508             default:
509                 rc = -RIG_EINVAL;
510                 break;
511             }
512         }
513         else
514         {
515             rc = -RIG_EINVAL;
516         }
517 
518         // this RIG_OK check added to clear cppcheck warnings
519         // not sure if it's needed but seem like RIG_OK should be expected
520         // if this debug prints out when things are working need to reexamine
521         if (rc != RIG_OK)
522         {
523             rig_debug(RIG_DEBUG_ERR, "%s: unexpected error?? %s\n", __func__, rigerror(rc));
524         }
525 
526         rc = execRoutine(rig, SET_ALL);
527 
528         if (rc == RIG_OK) { rc = lockRx(rig, LOCK_0); }
529     }
530 
531     return (rc);
532 }
533 
534 /*
535  * /brief Get receiver frequency
536  *
537  * /param rig Pointer to rig struct
538  * /param vfo VFO to operate on
539  * /param freq Pointer to hold frequency value (in Hz)
540  *
541  */
ar7030p_get_freq(RIG * rig,vfo_t vfo,freq_t * freq)542 static int ar7030p_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
543 {
544     int rc = RIG_OK;
545     unsigned int x;
546 
547     rc = lockRx(rig, LOCK_1);
548 
549     if (RIG_OK == rc)
550     {
551         switch (vfo)
552         {
553         case RIG_VFO_CURR:
554         case RIG_VFO_A:
555             rc = read3Bytes(rig, WORKING, FREQU, &x);
556 
557             if (RIG_OK == rc)
558             {
559                 *freq = ddsToHz(x);
560             }
561 
562             break;
563 
564         case RIG_VFO_B:
565             rc = read3Bytes(rig, WORKING, FREQU_B, &x);
566             {
567                 *freq = ddsToHz(x);
568             }
569             break;
570 
571         default:
572             rc = -RIG_EINVAL;
573             break;
574         }
575 
576         // this RIG_OK check added to clear cppcheck warnings
577         // not sure if it's needed but seem like RIG_OK should be expected
578         // if this debug prints out when things are working need to reexamine
579         if (rc != RIG_OK)
580         {
581             rig_debug(RIG_DEBUG_ERR, "%s: unexpected error?? %s\n", __func__, rigerror(rc));
582         }
583 
584         rc = lockRx(rig, LOCK_0);
585     }
586 
587     return (rc);
588 }
589 
590 /*
591  * /brief Set receiver mode
592  *
593  * /param rig Pointer to rig struct
594  * /param vfo VFO to operate on
595  * /param mode Mode to set
596  * /param width Bandwidth to set
597  *
598  */
ar7030p_set_mode(RIG * rig,vfo_t vfo,rmode_t mode,pbwidth_t width)599 static int ar7030p_set_mode(RIG *rig, vfo_t vfo, rmode_t mode,
600                             pbwidth_t width)
601 {
602     int rc = RIG_OK;
603 
604     rc = lockRx(rig, LOCK_1);
605 
606     if (RIG_OK == rc)
607     {
608         /* TODO - deal with selected VFO */
609         unsigned char ar_mode = modeToNative(mode);
610 
611         rc = writeByte(rig, WORKING, MODE, ar_mode);
612 
613         if (RIG_OK == rc && width != RIG_PASSBAND_NOCHANGE)
614         {
615             int i;
616 
617             /* TODO - get filter BWs at startup */
618             unsigned char ar_filter = (unsigned char) 6;
619 
620             for (i = 1; i <= 6; i++)
621             {
622                 if (width <= filterTab[ i ])
623                 {
624                     if (filterTab[ i ] < filterTab[(int) ar_filter ])
625                     {
626                         ar_filter = (unsigned char) i;
627                     }
628                 }
629 
630                 rig_debug(RIG_DEBUG_VERBOSE, "%s: width %d ar_filter %d filterTab[%d] %u\n",
631                           __func__, (int)width, ar_filter, i, filterTab[i]);
632             }
633 
634             rc = writeByte(rig, WORKING, FILTER, ar_filter);
635 
636             if (RIG_OK == rc)
637             {
638                 rc = execRoutine(rig, SET_ALL);
639             }
640         }
641 
642         // this RIG_OK check added to clear cppcheck warnings
643         // not sure if it's needed but seem like RIG_OK should be expected
644         // if this debug prints out when things are working need to reexamine
645         if (rc != RIG_OK)
646         {
647             rig_debug(RIG_DEBUG_ERR, "%s: unexpected error?? %s\n", __func__, rigerror(rc));
648         }
649 
650         rc = lockRx(rig, LOCK_0);
651     }
652 
653     return (rc);
654 }
655 
656 /*
657  * /brief Get receiver mode and bandwidth
658  *
659  * /param rig Pointer to rig struct
660  * /param vfo VFO to operate on
661  * /param mode Pointer to value to hold mode
662  * /param width Pointer to value to hold bandwidth
663  *
664  */
ar7030p_get_mode(RIG * rig,vfo_t vfo,rmode_t * mode,pbwidth_t * width)665 static int ar7030p_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode,
666                             pbwidth_t *width)
667 {
668     int rc = RIG_OK;
669     unsigned char bcd_bw;
670     unsigned char m;
671 
672     assert(NULL != rig);
673     assert(NULL != mode);
674     assert(NULL != width);
675 
676     rc = lockRx(rig, LOCK_1);
677 
678     if (RIG_OK == rc)
679     {
680         /* TODO - deal with selected VFO */
681         rc = readByte(rig, WORKING, MODE, &m);
682 
683         if (RIG_OK == rc)
684         {
685             *mode = modeToHamlib(m);
686             rc = readByte(rig, WORKING, FLTBW, &bcd_bw);
687 
688             if (RIG_OK == rc)
689             {
690                 *width = (pbwidth_t)((int) bcd2Int(bcd_bw) * 100);
691             }
692         }
693 
694         rc = lockRx(rig, LOCK_0);
695     }
696 
697     return (rc);
698 }
699 
700 /*
701  * /brief Get memory channel parameters
702  *
703  * /param rig Pointer to rig struct
704  * /param chan Channel number (0-399)
705  * /param freq Pointer to frequency value
706  * /param mode Pointer to mode value (1-7)
707  * /param filt Pointer to filter value (1-6)
708  * /param pbs Pointer to passband tuning value
709  * /param sql Pointer to squelch value (0-255)
710  * /param id Pointer to channel ident string (14 chars)
711  *
712  */
713 #if 0 /* unused; re-enabled as needed. */
714 static void ar7030p_get_memory(RIG *rig, const unsigned int chan,
715                                double *const freq, unsigned char *const mode,
716                                unsigned char *const filt, unsigned char *const pbs,
717                                unsigned char *const sql, char *const id)
718 {
719     int rc = RIG_OK;
720     unsigned char v;
721     unsigned int f;
722     unsigned char *p = (unsigned char *) id;
723     int i;
724 
725     assert(NULL != rig);
726     assert(NULL != freq);
727     assert(NULL != mode);
728     assert(NULL != filt);
729     assert(NULL != pbs);
730     assert(NULL != sql);
731     assert(NULL != id);
732 
733     rc = lockRx(rig, LOCK_1);
734 
735     if (RIG_OK == rc)
736     {
737         /* Squelch values */
738         if (100 > chan)
739         {
740             rc = readByte(rig, BBRAM, (MEM_SQ + chan), &v);   /* mem_sq */
741         }
742         else if (176 > chan)
743         {
744             rc = readByte(rig, EEPROM2, (MEX_SQ + (chan * 16)), &v);    /* mex_sq */
745         }
746         else
747         {
748             rc = readByte(rig, EEPROM3, (MEY_SQ + ((chan - 176) * 16)), &v);    /* mey_sq */
749         }
750 
751         if (RIG_OK == rc)
752         {
753             *sql = v;
754         }
755 
756         /* Frequency, mode and filter values */
757         if (100 > chan)
758         {
759             rc = read3Bytes(rig, EEPROM2, (MEM_FR + (chan * 4)), &f);    /* mem_fr */
760             rc = readByte(rig, EEPROM2, (MEM_MD + (chan * 4)), &v);      /* mem_md */
761         }
762         else
763         {
764             rc = read3Bytes(rig, EEPROM3, (MEX_FR + ((chan - 100) * 4)),
765                             &f);    /* mex_fr */
766             rc = readByte(rig, EEPROM3, (MEX_MD + ((chan - 100) * 4)),
767                           &v);      /* mex_md */
768         }
769 
770         if (RIG_OK == rc)
771         {
772             *freq = ddsToHz(f);
773             *mode = (v & 0x07);
774             *filt = ((v & 0x70) >> 4);
775             /* lockout = ( ( v & 0x80 ) >> 7 ); */
776         }
777 
778         /* PBT values */
779         if (100 > chan)
780         {
781             rc = readByte(rig, EEPROM1, (MEM_PB + chan), &v);   /* mem_pb */
782         }
783         else if (176 > chan)
784         {
785             rc = readByte(rig, EEPROM2, (MEX_PB + (chan * 16)), &v);   /* mex_pb */
786         }
787         else
788         {
789             rc = readByte(rig, EEPROM3, (MEY_PB + ((chan - 176) * 16)), &v);   /* mey_pb */
790         }
791 
792         if (RIG_OK == rc)
793         {
794             *pbs = v;
795         }
796 
797         /* Memory ID values */
798         for (i = 0; i < 14; i++)
799         {
800             if (176 > chan)
801             {
802                 rc = readByte(rig, EEPROM2, (MEX_ID + (chan * 16)), p++);   /* mex_id */
803             }
804             else
805             {
806                 rc = readByte(rig, EEPROM3, (MEY_ID + ((chan - 176) * 16)), p++);   /* mey_id */
807             }
808 
809             if (RIG_OK != rc)
810             {
811                 p = (unsigned char *) id;
812                 break;
813             }
814         }
815 
816         *p++ = '\0';
817 
818         rc = lockRx(rig, LOCK_0);
819     }
820 
821 }
822 #endif /* unused */
823 
824 /*
825  * /brief Set receiver levels
826  *
827  * /param rig Pointer to rig struct
828  * /param vfo VFO to operate on
829  * /param level Level to set
830  * /param val Value to set level to
831  *
832  * /return RIG_OK on success
833  */
ar7030p_set_level(RIG * rig,vfo_t vfo,setting_t level,value_t val)834 static int ar7030p_set_level(RIG *rig, vfo_t vfo, setting_t level,
835                              value_t val)
836 {
837     int rc = RIG_OK;
838 
839     rc = lockRx(rig, LOCK_1);
840 
841     if (RIG_OK == rc)
842     {
843         /* TODO - deal with selected VFO */
844         switch (level)
845         {
846             unsigned char v;
847 
848         case RIG_LEVEL_PREAMP:
849 
850             /* Scale parameter */
851             if (10 <= val.i)
852             {
853                 v = (unsigned char) 0;
854             }
855             else
856             {
857                 v = (unsigned char) 1;
858             }
859 
860             rc = writeByte(rig, WORKING, RFGAIN, v);   /* rfgain */
861 
862             rig_debug(RIG_DEBUG_VERBOSE, "%s: rfgain %d (%d)\n", __func__, val.i, v);
863 
864             if (rc == RIG_OK) { rc = execRoutine(rig, SET_ALL); }
865 
866             break;
867 
868         case RIG_LEVEL_ATT:
869 
870             /* Scale parameter */
871             if (10 > val.i)
872             {
873                 v = (unsigned char) 1;
874             }
875             else if (20 > val.i)
876             {
877                 v = (unsigned char) 2;
878             }
879             else if (40 > val.i)
880             {
881                 v = (unsigned char) 3;
882             }
883             else if (80 > val.i)
884             {
885                 v = (unsigned char) 4;
886             }
887             else
888             {
889                 v = (unsigned char) 5;
890             }
891 
892             rc = writeByte(rig, WORKING, RFGAIN, v);   /* rfgain */
893 
894             rig_debug(RIG_DEBUG_VERBOSE, "%s: rfgain %d (%d)\n", __func__, val.i, v);
895 
896             if (rc == RIG_OK) { rc = execRoutine(rig, SET_ALL); }
897 
898             break;
899 
900         case RIG_LEVEL_AF:
901             /* Scale parameter */
902             v = (unsigned char)((val.f * (VOL_MAX - VOL_MIN)) + VOL_MIN);
903             v = (v & 0x3f);
904 
905             rc = writeByte(rig, WORKING, AF_VOL, v);   /* af_vol */
906 
907             rig_debug(RIG_DEBUG_VERBOSE, "%s: af_vol %f (%d)\n", __func__, val.f, v);
908 
909             v = ((v >> 1) & 0x1f);        /* half value for L/R volume */
910 
911             if (rc == RIG_OK) { rc = writeByte(rig, WORKING, AF_VLL, v); }   /* af_vll */
912 
913             if (rc == RIG_OK) { rc = writeByte(rig, WORKING, AF_VLR, v); }   /* af_vlr */
914 
915             if (rc == RIG_OK) { rc = execRoutine(rig, SET_AUDIO); }
916 
917             break;
918 
919         case RIG_LEVEL_RF:
920             /* Scale parameter, values 0 (99%) to 130 (3%) */
921             v = (unsigned char)(134U - ((unsigned int)(val.f * 135.0)));
922 
923             rc = writeByte(rig, WORKING, IFGAIN, v);   /* ifgain */
924 
925             rig_debug(RIG_DEBUG_VERBOSE, "%s: ifgain %f (%d)\n", __func__, val.f, v);
926 
927             if (rc == RIG_OK) { rc = execRoutine(rig, SET_ALL); }
928 
929             break;
930 
931         case RIG_LEVEL_SQL:
932             /* Scale parameter */
933             v = (unsigned char)(val.f * 255.0);
934 
935             rc = writeByte(rig, WORKING, SQLVAL, v);   /* sqlval */
936 
937             rig_debug(RIG_DEBUG_VERBOSE, "%s: sqlval %f (%d)\n", __func__, val.f, v);
938 
939             if (rc == RIG_OK) { rc = execRoutine(rig, SET_ALL); }
940 
941             break;
942 
943         case RIG_LEVEL_PBT_IN:
944             /* Scale parameter */
945             v = (unsigned char)(val.f / (HZ_PER_STEP * 12.5));
946 
947             rc = writeByte(rig, WORKING, PBSVAL, v);   /* pbsval */
948 
949             rig_debug(RIG_DEBUG_VERBOSE, "%s: pbsval %f (%d)\n", __func__, val.f, v);
950 
951             if (rc == RIG_OK) { rc = execRoutine(rig, SET_ALL); }
952 
953             break;
954 
955         case RIG_LEVEL_CWPITCH:
956             /* Scale parameter */
957             v = (unsigned char)(val.f / (HZ_PER_STEP * 12.5));
958 
959             rc = writeByte(rig, WORKING, BFOVAL, v);   /* bfoval */
960 
961             rig_debug(RIG_DEBUG_VERBOSE, "%s: bfoval %f (%d)\n", __func__, val.f, v);
962 
963             if (rc == RIG_OK) { rc = execRoutine(rig, SET_ALL); }
964 
965             break;
966 
967         case RIG_LEVEL_NOTCHF:
968             rc = -RIG_ENIMPL;
969             break;
970 
971         case RIG_LEVEL_AGC:
972             /* Scale parameter */
973             v = agcToNative(val.i);
974             rc = writeByte(rig, WORKING, AGCSPD, v);   /* agcspd */
975 
976             rig_debug(RIG_DEBUG_VERBOSE, "%s: agcspd %d (%d)\n", __func__, val.i, v);
977 
978             if (rc == RIG_OK) { rc = execRoutine(rig, SET_ALL); }
979 
980             break;
981 
982         default:
983             rc = -RIG_EINVAL;
984             break;
985         }
986 
987         // this RIG_OK check added to clear cppcheck warnings
988         // not sure if it's needed but seem like RIG_OK should be expected
989         // if this debug prints out when things are working need to reexamine
990         if (rc != RIG_OK)
991         {
992             rig_debug(RIG_DEBUG_ERR, "%s: unexpected error?? %s\n", __func__, rigerror(rc));
993         }
994 
995         rc = lockRx(rig, LOCK_0);
996     }
997 
998     return (rc);
999 }
1000 
1001 
1002 /*
1003  * /brief Get receiver levels
1004  *
1005  * /param rig Pointer to rig struct
1006  * /param vfo VFO to operate on
1007  * /param level Level to get
1008  * /param val Pointer to value to get
1009  *
1010  * /return RIG_OK on success
1011  */
ar7030p_get_level(RIG * rig,vfo_t vfo,setting_t level,value_t * val)1012 static int ar7030p_get_level(RIG *rig, vfo_t vfo, setting_t level,
1013                              value_t *val)
1014 {
1015     int rc = RIG_OK;
1016     unsigned char v;
1017     unsigned short s = 0;
1018     int i;
1019 
1020     rc = lockRx(rig, LOCK_1);
1021 
1022     if (RIG_OK == rc)
1023     {
1024         /* TODO - deal with selected VFO */
1025         switch (level)
1026         {
1027         case RIG_LEVEL_PREAMP:
1028             rc = readByte(rig, WORKING, RFGAIN, &v);   /* rfgain */
1029 
1030             if (RIG_OK == rc)
1031             {
1032                 /* Scale parameter */
1033                 if (0 == v)
1034                 {
1035                     val->i = 10;
1036                 }
1037                 else
1038                 {
1039                     val->i = 0;
1040                 }
1041 
1042                 rig_debug(RIG_DEBUG_VERBOSE, "%s: rfgain %d (%d)\n",
1043                           __func__, v, val->i);
1044             }
1045 
1046             break;
1047 
1048         case RIG_LEVEL_ATT:
1049             rc = readByte(rig, WORKING, RFGAIN, &v);   /* rfgain */
1050 
1051             if (RIG_OK == rc)
1052             {
1053                 /* Scale parameter */
1054                 switch (v)
1055                 {
1056                 case 2:
1057                     val->i = 10;
1058                     break;
1059 
1060                 case 3:
1061                     val->i = 20;
1062                     break;
1063 
1064                 case 4:
1065                     val->i = 40;
1066                     break;
1067 
1068                 default:
1069                 case 0:
1070                 case 1:
1071                     val->i = 0;
1072                 };
1073 
1074                 rig_debug(RIG_DEBUG_VERBOSE, "%s: rfgain %d (%d)\n",
1075                           __func__, v, val->i);
1076             }
1077 
1078             break;
1079 
1080         case RIG_LEVEL_AF:
1081             rc = readByte(rig, WORKING, AF_VOL, &v);   /* af_vol */
1082 
1083             if (RIG_OK == rc)
1084             {
1085                 /* Scale parameter */
1086                 v = (v & 0x3f);
1087                 val->f = (((float) v - VOL_MIN) / (VOL_MAX - VOL_MIN));
1088 
1089                 rig_debug(RIG_DEBUG_VERBOSE, "%s: af_vol %d (%f)\n",
1090                           __func__, v, val->f);
1091             }
1092 
1093             break;
1094 
1095         case RIG_LEVEL_RF:
1096             rc = readByte(rig, WORKING, IFGAIN, &v);   /* ifgain */
1097 
1098             if (RIG_OK == rc)
1099             {
1100                 /* Scale parameter, values 0 (99%) to 130 (3%) */
1101                 val->f = ((float)(134 - v) / 135.0);
1102 
1103                 rig_debug(RIG_DEBUG_VERBOSE, "%s: ifgain %d (%f)\n",
1104                           __func__, v, val->f);
1105             }
1106 
1107             break;
1108 
1109         case RIG_LEVEL_SQL:
1110             rc = readByte(rig, WORKING, SQLVAL, &v);   /* sqlval */
1111 
1112             if (RIG_OK == rc)
1113             {
1114                 /* Scale parameter */
1115                 val->f = ((float)(v) / 255.0);
1116 
1117                 rig_debug(RIG_DEBUG_VERBOSE, "%s: sqlval %d (%f)\n",
1118                           __func__, v, val->f);
1119             }
1120 
1121             break;
1122 
1123         case RIG_LEVEL_PBT_IN:
1124             rc = readByte(rig, WORKING, PBSVAL, &v);   /* pbsval */
1125 
1126             if (RIG_OK == rc)
1127             {
1128                 /* Scale parameter */
1129                 if (127 < v)
1130                 {
1131                     v = v | 0xffffff00;
1132                 }
1133 
1134                 val->f = ((float)(v) * HZ_PER_STEP * 12.5);
1135 
1136                 rig_debug(RIG_DEBUG_VERBOSE, "%s: pbsval %d (%f)\n",
1137                           __func__, v, val->f);
1138             }
1139 
1140             break;
1141 
1142         case RIG_LEVEL_CWPITCH:
1143             rc = readByte(rig, WORKING, BFOVAL, &v);   /* bfoval */
1144 
1145             if (RIG_OK == rc)
1146             {
1147                 /* Scale parameter */
1148                 if (127 < v)
1149                 {
1150                     v = v | 0xffffff00;
1151                 }
1152 
1153                 val->f = ((float)(v) * HZ_PER_STEP * 12.5);
1154 
1155                 rig_debug(RIG_DEBUG_VERBOSE, "%s: bfoval %d (%f)\n",
1156                           __func__, v, val->f);
1157             }
1158 
1159             break;
1160 
1161         case RIG_LEVEL_NOTCHF:
1162             rc = readShort(rig, WORKING, NCHFR, &s);   /* nchfr */
1163 
1164             if (RIG_OK == rc)
1165             {
1166                 unsigned int x = (unsigned int) s;
1167 
1168                 /* Scale parameter */
1169                 val->i = (int)((float)(x) / NOTCH_STEP_HZ);
1170 
1171                 rig_debug(RIG_DEBUG_VERBOSE, "%s: nchfr %u (%d)\n",
1172                           __func__, x, val->i);
1173             }
1174 
1175             break;
1176 
1177         case RIG_LEVEL_AGC:
1178             rc = readByte(rig, WORKING, AGCSPD, &v);   /* agcspd */
1179 
1180             if (RIG_OK == rc)
1181             {
1182                 /* Scale parameter */
1183                 val->i = agcToHamlib(v);
1184 
1185                 rig_debug(RIG_DEBUG_VERBOSE, "%s: agcspd %d (%d)\n",
1186                           __func__, v, val->i);
1187             }
1188 
1189             break;
1190 
1191         case RIG_LEVEL_RAWSTR:
1192             rc = readSignal(rig, &v);
1193 
1194             if (RIG_OK == rc)
1195             {
1196                 val->i = (int) v;
1197             }
1198 
1199             break;
1200 
1201         case RIG_LEVEL_STRENGTH:
1202             rc = readSignal(rig, &v);
1203 
1204             if (RIG_OK == rc)
1205             {
1206                 rc = getCalLevel(rig, v, &i);
1207 
1208                 if (RIG_OK == rc)
1209                 {
1210                     val->i = i;
1211                 }
1212             }
1213 
1214             break;
1215 
1216         default:
1217             rc = -RIG_EINVAL;
1218         }
1219 
1220         if (RIG_OK == rc) { rc = lockRx(rig, LOCK_0); }
1221     }
1222 
1223     return (rc);
1224 }
1225 
ar7030p_set_vfo(RIG * rig,vfo_t vfo)1226 static int ar7030p_set_vfo(RIG *rig, vfo_t vfo)
1227 {
1228     int rc = RIG_OK;
1229     struct ar7030p_priv_data *priv = (struct ar7030p_priv_data *) rig->state.priv;
1230 
1231     switch (vfo)
1232     {
1233     case RIG_VFO_B:
1234         if (RIG_VFO_B != priv->curr_vfo)
1235         {
1236             rc = sendIRCode(rig, IR_VFO);
1237 
1238             if (RIG_OK == rc)
1239             {
1240                 priv->curr_vfo = RIG_VFO_B;
1241                 priv->last_vfo = RIG_VFO_A;
1242             }
1243         }
1244 
1245         break;
1246 
1247     case RIG_VFO_A:
1248     case RIG_VFO_CURR:
1249         if (RIG_VFO_A != priv->curr_vfo)
1250         {
1251             rc = sendIRCode(rig, IR_VFO);
1252 
1253             if (RIG_OK == rc)
1254             {
1255                 priv->curr_vfo = RIG_VFO_A;
1256                 priv->last_vfo = RIG_VFO_B;
1257             }
1258         }
1259 
1260         break;
1261 
1262     default:
1263         rc = -RIG_EINVAL;
1264         break;
1265     }
1266 
1267     return (rc);
1268 }
1269 
ar7030p_get_vfo(RIG * rig,vfo_t * vfo)1270 static int ar7030p_get_vfo(RIG *rig, vfo_t *vfo)
1271 {
1272     int rc = RIG_OK;
1273     struct ar7030p_priv_data *priv = (struct ar7030p_priv_data *) rig->state.priv;
1274 
1275     assert(NULL != vfo);
1276 
1277     *vfo = priv->curr_vfo;
1278 
1279     return (rc);
1280 }
1281 
ar7030p_set_parm(RIG * rig,setting_t parm,value_t val)1282 static int ar7030p_set_parm(RIG *rig, setting_t parm, value_t val)
1283 {
1284     int rc = -RIG_ENIMPL;
1285 
1286     assert(NULL != rig);
1287 
1288     switch (parm)
1289     {
1290     case RIG_PARM_APO:
1291         break;
1292 
1293     case RIG_PARM_TIME:
1294         break;
1295 
1296     case RIG_PARM_BAT:
1297         break;
1298 
1299     default:
1300         break;
1301     };
1302 
1303     return (rc);
1304 }
1305 
ar7030p_get_parm(RIG * rig,setting_t parm,value_t * val)1306 static int ar7030p_get_parm(RIG *rig, setting_t parm, value_t *val)
1307 {
1308     int rc = -RIG_ENIMPL;
1309 
1310     assert(NULL != rig);
1311     assert(NULL != val);
1312 
1313     switch (parm)
1314     {
1315     case RIG_PARM_APO:
1316         break;
1317 
1318     case RIG_PARM_TIME:
1319         break;
1320 
1321     case RIG_PARM_BAT:
1322         break;
1323 
1324     default:
1325         break;
1326     };
1327 
1328     return (rc);
1329 }
1330 
ar7030p_set_mem(RIG * rig,vfo_t vfo,int ch)1331 static int ar7030p_set_mem(RIG *rig, vfo_t vfo, int ch)
1332 {
1333     int rc = RIG_OK;
1334 
1335     struct ar7030p_priv_data *priv = (struct ar7030p_priv_data *) rig->state.priv;
1336 
1337     if (RIG_VFO_MEM == priv->curr_vfo)
1338     {
1339         priv->curr = &priv->mem[ ch ];
1340     }
1341     else
1342     {
1343         priv->curr->channel_num = ch;
1344     }
1345 
1346     rig_debug(RIG_DEBUG_VERBOSE, "%s: ch %d\n", __func__, ch);
1347 
1348     return (rc);
1349 }
1350 
ar7030p_get_mem(RIG * rig,vfo_t vfo,int * ch)1351 static int ar7030p_get_mem(RIG *rig, vfo_t vfo, int *ch)
1352 {
1353     int rc = RIG_OK;
1354 
1355     struct ar7030p_priv_data *priv = (struct ar7030p_priv_data *) rig->state.priv;
1356     channel_t *curr = priv->curr;
1357 
1358     assert(NULL != ch);
1359 
1360     *ch = curr->channel_num;
1361 
1362     rig_debug(RIG_DEBUG_VERBOSE, "%s: ch %d\n", __func__, *ch);
1363 
1364     return (rc);
1365 }
1366 
ar7030p_vfo_op(RIG * rig,vfo_t vfo,vfo_op_t op)1367 static int ar7030p_vfo_op(RIG *rig, vfo_t vfo, vfo_op_t op)
1368 {
1369     int rc = -RIG_ENIMPL;
1370 
1371     assert(NULL != rig);
1372 
1373     switch (op)
1374     {
1375     case RIG_OP_CPY:
1376         rc = -RIG_ENIMPL;
1377         break;
1378 
1379     case RIG_OP_XCHG:
1380         rc = -RIG_ENIMPL;
1381         break;
1382 
1383     case RIG_OP_TOGGLE:
1384         rc = sendIRCode(rig, IR_VFO);
1385         break;
1386 
1387     default:
1388         break;
1389     };
1390 
1391     return (rc);
1392 }
1393 
ar7030p_scan(RIG * rig,vfo_t vfo,scan_t scan,int ch)1394 static int ar7030p_scan(RIG *rig, vfo_t vfo, scan_t scan, int ch)
1395 {
1396     int rc = -RIG_ENIMPL;
1397 
1398     assert(NULL != rig);
1399 
1400     return (rc);
1401 }
1402 
ar7030p_get_dcd(RIG * rig,vfo_t vfo,dcd_t * dcd)1403 static int ar7030p_get_dcd(RIG *rig, vfo_t vfo, dcd_t *dcd)
1404 {
1405     int rc = RIG_OK;
1406     unsigned char v;
1407 
1408     assert(NULL != rig);
1409     assert(NULL != dcd);
1410 
1411     rc = lockRx(rig, LOCK_1);
1412 
1413     if (RIG_OK == rc)
1414     {
1415         rc = readByte(rig, WORKING, BITS + 2, &v);
1416 
1417         if (RIG_OK == rc)
1418         {
1419             if ((v & 0x02))
1420             {
1421                 if ((v & 0x01))   /* low bit set if Squelch is NOT active/open */
1422                 {
1423                     *dcd = RIG_DCD_OFF;
1424                 }
1425                 else
1426                 {
1427                     *dcd = RIG_DCD_ON;
1428                 }
1429             }
1430             else
1431             {
1432                 *dcd = RIG_DCD_ON;
1433             }
1434         }
1435 
1436         rc = lockRx(rig, LOCK_0);
1437     }
1438 
1439     return (rc);
1440 }
1441 
ar7030p_set_ts(RIG * rig,vfo_t vfo,shortfreq_t ts)1442 static int ar7030p_set_ts(RIG *rig, vfo_t vfo, shortfreq_t ts)
1443 {
1444     int rc = RIG_OK;
1445 
1446     assert(NULL != rig);
1447 
1448     rc = lockRx(rig, LOCK_1);
1449 
1450     if (RIG_OK == rc)
1451     {
1452         /* Scale parameter */
1453         unsigned short v = (unsigned short)((double)(ts + 1) / HZ_PER_STEP);
1454 
1455         rc = writeShort(rig, WORKING, CHNSTP, v);   /* chnstp */
1456 
1457         if (RIG_OK == rc)
1458         {
1459             rc = execRoutine(rig, SET_ALL);
1460 
1461             rig_debug(RIG_DEBUG_VERBOSE, "%s: chnstp %d (%d)\n", __func__, (int)ts, v);
1462         }
1463 
1464         if (RIG_OK == rc) { rc = lockRx(rig, LOCK_0); }
1465     }
1466 
1467     return (rc);
1468 }
1469 
1470 /*
1471  * /brief Get receiver tuning step size
1472  *
1473  * /param rig Pointer to rig struct
1474  * /param vfo VFO to operate on
1475  * /param ts Pointer to tuning step value
1476  *
1477  * /return RIG_OK on success
1478  */
ar7030p_get_ts(RIG * rig,vfo_t vfo,shortfreq_t * ts)1479 static int ar7030p_get_ts(RIG *rig, vfo_t vfo, shortfreq_t *ts)
1480 {
1481     int rc = RIG_OK;
1482     unsigned short v;
1483 
1484     assert(NULL != rig);
1485     assert(NULL != ts);
1486 
1487     rc = lockRx(rig, LOCK_1);
1488 
1489     if (RIG_OK == rc)
1490     {
1491         rc = readShort(rig, WORKING, CHNSTP, &v);   /* chnstp */
1492 
1493         if (RIG_OK == rc)
1494         {
1495             double x = (double) v;
1496             *ts = (shortfreq_t)(x * HZ_PER_STEP);
1497 
1498             rig_debug(RIG_DEBUG_VERBOSE, "%s: step= %d\n", __func__, (int)*ts);
1499         }
1500 
1501         rc = lockRx(rig, LOCK_0);
1502     }
1503 
1504     return (rc);
1505 }
1506 
1507 /*
1508  * /brief Set receiver power status
1509  *
1510  * /param rig Pointer to rig struct
1511  * /param status Power status to set
1512  *
1513  * /return RIG_OK on success
1514  */
ar7030p_set_powerstat(RIG * rig,powerstat_t status)1515 static int ar7030p_set_powerstat(RIG *rig, powerstat_t status)
1516 {
1517     int rc;
1518 
1519     assert(NULL != rig);
1520 
1521     rc = lockRx(rig, LOCK_1);
1522 
1523     if (RIG_OK == rc)
1524     {
1525         switch (status)
1526         {
1527         case RIG_POWER_OFF:
1528             break;
1529 
1530         case RIG_POWER_ON:
1531             break;
1532 
1533         default:
1534             break;
1535         }
1536 
1537         lockRx(rig, LOCK_0);
1538     }
1539 
1540     return (-RIG_ENIMPL);
1541 }
1542 
1543 /*
1544  * /brief Get receiver power status
1545  *
1546  * /param rig Pointer to rig struct
1547  * /param status Pointer to power status value
1548  *
1549  * /return RIG_OK on success
1550  */
ar7030p_get_powerstat(RIG * rig,powerstat_t * status)1551 static int ar7030p_get_powerstat(RIG *rig, powerstat_t *status)
1552 {
1553     int rc = RIG_OK;
1554     unsigned char v;
1555 
1556     assert(NULL != rig);
1557 
1558     rc = lockRx(rig, LOCK_1);
1559 
1560     if (RIG_OK == rc)
1561     {
1562         rc = readByte(rig, WORKING, PDFLGS, &v);
1563 
1564         if (RIG_OK == rc)
1565         {
1566             if (0 == (v & 0x01))
1567             {
1568                 *status = RIG_POWER_OFF;
1569             }
1570             else
1571             {
1572                 *status = RIG_POWER_ON;
1573             }
1574         }
1575 
1576         rc = lockRx(rig, LOCK_0);
1577     }
1578 
1579     return (rc);
1580 }
1581 
1582 /*
1583  * /brief Reset receiver
1584  *
1585  * /param rig Pointer to rig struct
1586  * /param reset Reset operation to perform
1587  *
1588  * /return RIG_OK on success
1589  */
ar7030p_reset(RIG * rig,reset_t reset)1590 static int ar7030p_reset(RIG *rig, reset_t reset)
1591 {
1592     int rc = RIG_OK;
1593 
1594     assert(NULL != rig);
1595 
1596     switch (reset)
1597     {
1598     case RIG_RESET_SOFT:
1599         rc = execRoutine(rig, RESET);
1600         break;
1601 
1602     default:
1603         rc = -RIG_EINVAL;
1604     }
1605 
1606     return (rc);
1607 }
1608 
ar7030p_set_func(RIG * rig,vfo_t vfo,setting_t func,int status)1609 static int ar7030p_set_func(RIG *rig, vfo_t vfo, setting_t func,
1610                             int status)
1611 {
1612     assert(NULL != rig);
1613 
1614     return (-RIG_ENIMPL);
1615 }
1616 
ar7030p_get_func(RIG * rig,vfo_t vfo,setting_t func,int * status)1617 static int ar7030p_get_func(RIG *rig, vfo_t vfo, setting_t func,
1618                             int *status)
1619 {
1620     assert(NULL != rig);
1621     assert(NULL != status);
1622 
1623     return (-RIG_ENIMPL);
1624 }
1625 
ar7030p_decode_event(RIG * rig)1626 static int ar7030p_decode_event(RIG *rig)
1627 {
1628     assert(NULL != rig);
1629 
1630     return (-RIG_ENIMPL);
1631 }
1632 
ar7030p_set_channel(RIG * rig,vfo_t vfo,const channel_t * chan)1633 static int ar7030p_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
1634 {
1635     assert(NULL != rig);
1636     assert(NULL != chan);
1637 
1638     return (-RIG_ENIMPL);
1639 }
1640 
ar7030p_get_channel(RIG * rig,vfo_t vfo,channel_t * chan,int read_only)1641 static int ar7030p_get_channel(RIG *rig, vfo_t vfo, channel_t *chan,
1642                                int read_only)
1643 {
1644     int rc = RIG_OK;
1645     unsigned char v;
1646     unsigned int f;
1647     unsigned char *p = NULL;
1648     int ch;
1649     struct ar7030p_priv_data *priv = (struct ar7030p_priv_data *)rig->state.priv;
1650     channel_t *curr = priv->curr;
1651 
1652     assert(NULL != chan);
1653 
1654     ch = curr->channel_num;
1655 
1656     rc = lockRx(rig, LOCK_1);
1657 
1658     if (RIG_OK == rc)
1659     {
1660         int i;
1661 
1662         /* Squelch values */
1663         /* TODO - fix magic numbers */
1664         if (100 > ch)
1665         {
1666             rc = readByte(rig, BBRAM, (MEM_SQ + ch), &v);   /* mem_sq */
1667         }
1668         else if (176 > ch)
1669         {
1670             rc = readByte(rig, EEPROM2, (MEX_SQ + (ch * 16)), &v);    /* mex_sq */
1671         }
1672         else
1673         {
1674             rc = readByte(rig, EEPROM3, (MEY_SQ + ((ch - 176) * 16)), &v);    /* mey_sq */
1675         }
1676 
1677         if (RIG_OK == rc)
1678         {
1679             // cppcheck-suppress *
1680             chan->levels[ LVL_SQL ].f = (float) v / 255.0;
1681         }
1682 
1683         /* Frequency, mode and filter values */
1684         if (100 > ch)
1685         {
1686             rc = read3Bytes(rig, EEPROM1, (MEM_FR + (ch * 4)), &f);    /* mem_fr */
1687 
1688             if (RIG_OK == rc) { rc = readByte(rig, EEPROM1, (MEM_MD + (ch * 4)), &v); }      /* mem_md */
1689         }
1690         else
1691         {
1692             rc = read3Bytes(rig, EEPROM2, (MEX_FR + ((ch - 100) * 4)), &f);    /* mex_fr */
1693 
1694             if (RIG_OK == rc) { rc = readByte(rig, EEPROM2, (MEX_MD + ((ch - 100) * 4)), &v); }      /* mex_md */
1695         }
1696 
1697         if (RIG_OK == rc)
1698         {
1699             chan->freq = ddsToHz(f);
1700             chan->mode = modeToHamlib((v & 0x07));
1701             chan->width = getFilterBW(rig, ((v & 0x70) >> 4));
1702 
1703             if ((v & 0x80) >> 7)
1704             {
1705                 chan->flags = RIG_CHFLAG_SKIP;
1706             }
1707             else
1708             {
1709                 chan->flags = RIG_CHFLAG_NONE;
1710             }
1711         }
1712 
1713         /* PBT values */
1714         if (100 > ch)
1715         {
1716             rc = readByte(rig, EEPROM1, (MEM_PB + ch), &v);   /* mem_pb */
1717         }
1718         else if (176 > ch)
1719         {
1720             rc = readByte(rig, EEPROM2, (MEX_PB + (ch * 16)), &v);   /* mex_pb */
1721         }
1722         else
1723         {
1724             rc = readByte(rig, EEPROM3, (MEY_PB + ((ch - 176) * 16)), &v);   /* mey_pb */
1725         }
1726 
1727         if (RIG_OK == rc)
1728         {
1729             chan->levels[ LVL_PBT_IN ].f = pbsToHz(v);
1730         }
1731 
1732         /* Memory ID values */
1733         p = (unsigned char *) chan->channel_desc;
1734 
1735         for (i = 0; i < 14; i++)
1736         {
1737             if (176 > ch)
1738             {
1739                 rc = readByte(rig, EEPROM2, (MEX_ID + (ch * 16) + i), p++);   /* mex_id */
1740             }
1741             else
1742             {
1743                 rc = readByte(rig, EEPROM3, (MEY_ID + ((ch - 176) * 16) + i),
1744                               p++);   /* mey_id */
1745             }
1746 
1747             if (RIG_OK != rc)
1748             {
1749                 p = (unsigned char *) chan->channel_desc;
1750                 break;
1751             }
1752         }
1753 
1754         *p++ = '\0';
1755 
1756         rc = lockRx(rig, LOCK_0);
1757     }
1758 
1759     if (!read_only)
1760     {
1761         // Set rig to channel values
1762         rig_debug(RIG_DEBUG_ERR,
1763                   "%s: please contact hamlib mailing list to implement this\n", __func__);
1764         rig_debug(RIG_DEBUG_ERR,
1765                   "%s: need to know if rig updates when channel read or not\n", __func__);
1766         return -RIG_ENIMPL;
1767     }
1768 
1769     return (rc);
1770 }
1771 
1772 const struct rig_caps ar7030p_caps =
1773 {
1774     RIG_MODEL(RIG_MODEL_AR7030P),
1775     .model_name = "AR7030 Plus",
1776     .mfg_name = "AOR",
1777     .version = "20200319.0",
1778     .copyright = "LGPL",
1779     .status = RIG_STATUS_BETA,
1780     .rig_type = RIG_TYPE_RECEIVER,
1781 
1782     .dcd_type = RIG_DCD_RIG,
1783 
1784     .port_type = RIG_PORT_SERIAL,
1785     .serial_rate_min = 1200,
1786     .serial_rate_max = 1200,
1787     .serial_data_bits = 8,
1788     .serial_stop_bits = 1,
1789     .serial_parity = RIG_PARITY_NONE,
1790     .serial_handshake = RIG_HANDSHAKE_NONE,
1791     .write_delay = 0,
1792     .post_write_delay = 12,
1793     .timeout = 650,
1794     .retry = 0,
1795 
1796     .has_get_func = AR7030P_FUNC,
1797     .has_set_func = AR7030P_FUNC,
1798     .has_get_level = AR7030P_LEVEL,
1799     .has_set_level = RIG_LEVEL_SET(AR7030P_LEVEL),
1800     .has_get_parm = AR7030P_PARM,
1801     .has_set_parm = RIG_PARM_SET(AR7030P_PARM),
1802 
1803     .level_gran = {
1804         [LVL_PREAMP]   = {.min = {.i = 0},    .max = {.i = 10} },
1805         [LVL_ATT]      = {.min = {.i = 0},    .max = {.i = 20} },
1806         [LVL_RF]       = {.min = {.f = 0.0},  .max = {.f = 1.0} },
1807         [LVL_AF]       = {.min = {.f = 0.0},  .max = {.f = 1.0} },
1808         [LVL_SQL]      = {.min = {.f = 0.0},  .max = {.f = 1.0} },
1809         [LVL_IF]       = {.min = {.i = 255},  .max = {.i = 0} },
1810         [LVL_PBT_IN]  = {.min = {.f = -4248.0}, .max = {.f = 4248.0} },
1811         [LVL_CWPITCH]  = {.min = {.i = -4248}, .max = {.i = 4248} },
1812         [LVL_NOTCHF]   = {.min = {.i = 0},    .max = {.i = 10000} },
1813         [LVL_AGC]      = {.min = {.i = 0},    .max = {.i = 10} },
1814         [LVL_BALANCE]  = {.min = {.f = -1.0}, .max = {.f = 1.0} },
1815         [LVL_RAWSTR]   = {.min = {.i = 0},    .max = {.i = 255} },
1816         [LVL_STRENGTH] = {.min = {.i = 0},    .max = {.i = 255} },
1817     },
1818 
1819     .extparms = NULL,
1820     .extlevels = NULL,
1821 
1822     .parm_gran = {
1823         [PARM_APO]  = {.min = {.i = 1}, .max = {.i = 86400} },
1824         [PARM_TIME] = {.min = {.i = 0}, .max = {.i = 86400} },
1825         [PARM_BAT]  = {.min = {.f = 0.0}, .max = {.f = 1.0} },
1826     },
1827 
1828     .preamp = {10, RIG_DBLST_END,},
1829     .attenuator = {10, 20, RIG_DBLST_END,},
1830     .max_rit = Hz(0),
1831     .max_xit = Hz(0),
1832     .max_ifshift = Hz(4248),
1833     .announces = RIG_ANN_NONE,
1834     .vfo_ops = AR7030P_VFO_OPS,
1835     .scan_ops = RIG_SCAN_STOP | RIG_SCAN_MEM | RIG_SCAN_VFO,
1836     .targetable_vfo = 0,
1837     .transceive = RIG_TRN_OFF,
1838     .bank_qty = 0,
1839     .chan_desc_sz = 14,
1840 
1841     .chan_list = {{0, 399, RIG_MTYPE_MEM, AR7030P_MEM_CAP}, RIG_CHAN_END,},
1842 
1843     .rx_range_list1 = {
1844         {
1845             kHz(10), kHz(32010), AR7030P_MODES, -1, -1,
1846             AR7030P_VFO
1847         },
1848         RIG_FRNG_END,
1849     },
1850     .tx_range_list1 = {RIG_FRNG_END,},
1851 
1852     .rx_range_list2 = {
1853         {
1854             kHz(10), kHz(32010), AR7030P_MODES, -1, -1,
1855             AR7030P_VFO
1856         },
1857         RIG_FRNG_END,
1858     },
1859     .tx_range_list2 = {RIG_FRNG_END,},
1860 
1861     .tuning_steps = {
1862         {AR7030P_MODES, Hz(10)},
1863         {AR7030P_MODES, Hz(20)},
1864         {AR7030P_MODES, Hz(50)},
1865         {AR7030P_MODES, Hz(100)},
1866         {AR7030P_MODES, Hz(200)},
1867         {AR7030P_MODES, Hz(500)},
1868         {AR7030P_MODES, kHz(1)},
1869         {AR7030P_MODES, kHz(2)},
1870         {AR7030P_MODES, kHz(5)},
1871         {AR7030P_MODES, kHz(6.25)},
1872         {AR7030P_MODES, kHz(9)},
1873         {AR7030P_MODES, kHz(10)},
1874         {AR7030P_MODES, Hz(12500)},
1875         {AR7030P_MODES, kHz(20)},
1876         {AR7030P_MODES, kHz(25)},
1877         RIG_TS_END,
1878     },
1879 
1880     .filters = {
1881         {RIG_MODE_FM,   kHz(9.5)},
1882         {RIG_MODE_FM,   kHz(0)},
1883         {RIG_MODE_FM,   kHz(0)},
1884         {RIG_MODE_AMS,  kHz(6.5)},
1885         {RIG_MODE_AMS,  kHz(5.3)},
1886         {RIG_MODE_AMS,  kHz(9.5)},
1887         {RIG_MODE_AM,   kHz(5.3)},
1888         {RIG_MODE_AM,   kHz(3.7)},
1889         {RIG_MODE_AM,   kHz(6.5)},
1890         {RIG_MODE_SSB,  kHz(2.0)},
1891         {RIG_MODE_SSB,  kHz(1.4)},
1892         {RIG_MODE_SSB,  kHz(3.7)},
1893         {RIG_MODE_CW,   kHz(1.4)},
1894         {RIG_MODE_CW,   kHz(0)},
1895         {RIG_MODE_CW,   kHz(2.0)},
1896         {RIG_MODE_RTTY, kHz(1.4)},
1897         {RIG_MODE_RTTY, kHz(0)},
1898         {RIG_MODE_RTTY, kHz(2.0)},
1899         RIG_FLT_END,
1900     },
1901 
1902     .str_cal = AR7030P_STR_CAL,
1903     .cfgparams = NULL,
1904     .priv = (void *)& ar7030p_priv_caps,
1905 
1906     .rig_init = ar7030p_init,
1907     .rig_cleanup = ar7030p_cleanup,
1908     .rig_open = ar7030p_open,
1909     .rig_close = ar7030p_close,
1910     .set_freq = ar7030p_set_freq,
1911     .get_freq = ar7030p_get_freq,
1912     .set_mode = ar7030p_set_mode,
1913     .get_mode = ar7030p_get_mode,
1914     .set_vfo = ar7030p_set_vfo,
1915     .get_vfo = ar7030p_get_vfo,
1916 
1917     .get_dcd = ar7030p_get_dcd,
1918 
1919     .set_ts = ar7030p_set_ts,
1920     .get_ts = ar7030p_get_ts,
1921 
1922     .set_powerstat = ar7030p_set_powerstat,
1923     .get_powerstat = ar7030p_get_powerstat,
1924     .reset = ar7030p_reset,
1925 
1926     .set_level = ar7030p_set_level,
1927     .get_level = ar7030p_get_level,
1928     .set_func = ar7030p_set_func,
1929     .get_func = ar7030p_get_func,
1930     .set_parm = ar7030p_set_parm,
1931     .get_parm = ar7030p_get_parm,
1932 
1933     .set_ext_level = RIG_FUNC_NONE,
1934     .get_ext_level = RIG_FUNC_NONE,
1935     .set_ext_parm = RIG_FUNC_NONE,
1936     .get_ext_parm = RIG_FUNC_NONE,
1937     .set_conf = RIG_FUNC_NONE,
1938     .get_conf = RIG_FUNC_NONE,
1939 
1940     .set_mem = ar7030p_set_mem,
1941     .get_mem = ar7030p_get_mem,
1942     .vfo_op = ar7030p_vfo_op,
1943     .scan = ar7030p_scan,
1944 
1945     .decode_event = ar7030p_decode_event,
1946     .set_channel = ar7030p_set_channel,
1947     .get_channel = ar7030p_get_channel,
1948     .get_info = ar7030p_get_info,
1949 
1950     .set_chan_all_cb = RIG_FUNC_NONE,
1951     .get_chan_all_cb = RIG_FUNC_NONE,
1952     .set_mem_all_cb = RIG_FUNC_NONE,
1953     .get_mem_all_cb = RIG_FUNC_NONE,
1954 
1955 };
1956