1 /*
2  *  Hamlib AOR backend - AR7030 Plus utility functions
3  *  Copyright (c) 2009-2010 by Larry Gadallah (VE6VQ)
4  *
5  *
6  *   This library is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU Lesser General Public
8  *   License as published by the Free Software Foundation; either
9  *   version 2.1 of the License, or (at your option) any later version.
10  *
11  *   This library is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *   Lesser General Public License for more details.
15  *
16  *   You should have received a copy of the GNU Lesser General Public
17  *   License along with this library; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21 
22 /*
23  * Version 2009.12.31 Larry Gadallah (VE6VQ)
24  */
25 
26 #include <stdio.h>
27 #include <string.h>
28 #include <math.h>
29 #include <assert.h>
30 
31 #include <hamlib/rig.h>
32 #include "ar7030p.h"
33 #include "serial.h"
34 #include "idx_builtin.h"
35 
36 static enum PAGE_e curPage = NONE; /* Current memory page */
37 static unsigned int curAddr = 65535; /* Current page address */
38 static enum LOCK_LVL_e curLock = LOCK_0; /* Current lock level */
39 static const unsigned int AR7030_PAGE_SIZE[] =
40 {
41     256, 256, 512, 4096, 4096,
42     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43     8
44 }; /* Page size table */
45 
46 
47 #if 0
48 /*
49  *     Code Ident Operation
50  *     0x   NOP   No Operation
51  */
52 int NOP(RIG *rig, unsigned char x)
53 {
54     int rc = RIG_OK;
55 
56     unsigned char op = ((0x0f & x) | op_NOP);
57 
58     assert(NULL != rig);
59 
60     rc = write_block(&rig->state.rigport, (char *) &op, 1);
61 
62     if (0 != rc)
63     {
64         rc = -RIG_EIO;
65     }
66 
67     return (rc);
68 }
69 
70 /*
71  *     Code Ident Operation
72  *     3x   SRH   Set H-register    x -> H-register (4-bits)
73  */
74 int SRH(RIG *rig, unsigned char x)
75 {
76     int rc = RIG_OK;
77 
78     unsigned char op = ((0x0f & x) | op_SRH);
79 
80     assert(NULL != rig);
81 
82     rc = write_block(&rig->state.rigport, (char *) &op, 1);
83 
84     if (0 != rc)
85     {
86         rc = -RIG_EIO;
87     }
88 
89     return (rc);
90 }
91 
92 /*
93  *     Code Ident Operation
94  *     5x   PGE   Set page          x -> Page register (4-bits)
95  */
96 int PGE(RIG *rig, enum PAGE_e page)
97 {
98     int rc = RIG_OK;
99 
100     unsigned char op = ((0x0f & page) | op_PGE);
101 
102     assert(NULL != rig);
103 
104     switch (page)
105     {
106     case WORKING:
107     case BBRAM:
108     case EEPROM1:
109     case EEPROM2:
110     case EEPROM3:
111     case ROM:
112         rc = write_block(&rig->state.rigport, (char *) &op, 1);
113 
114         if (0 != rc)
115         {
116             rc = -RIG_EIO;
117         }
118 
119         break;
120 
121     case NONE:
122     default:
123         rig_debug(RIG_DEBUG_VERBOSE, "PGE: invalid page %d\n", page);
124 
125         rc = -RIG_EINVAL;
126         break;
127     };
128 
129     return (rc);
130 }
131 
132 /*
133  *     Code Ident Operation
134  *     4x   ADR   Set address       0Hx -> Address register (12-bits)
135  *                                  0 -> H-register
136  */
137 int ADR(RIG *rig, unsigned char x)
138 {
139     int rc = RIG_OK;
140 
141     unsigned char op = ((0x0f & x) | op_ADR);
142 
143     assert(NULL != rig);
144 
145     rc = write_block(&rig->state.rigport, (char *) &op, 1);
146 
147     if (0 != rc)
148     {
149         rc = -RIG_EIO;
150     }
151 
152     return (rc);
153 }
154 
155 /*
156  *     Code Ident Operation
157  *     1x   ADH   Set address high  x -> Address register (high 4-bits)
158  */
159 int ADH(RIG *rig, unsigned char x)
160 {
161     int rc = RIG_OK;
162 
163     unsigned char op = ((0x0f & x) | op_ADH);
164 
165     assert(NULL != rig);
166 
167     rc = write_block(&rig->state.rigport, (char *) &op, 1);
168 
169     if (0 != rc)
170     {
171         rc = -RIG_EIO;
172     }
173 
174     return (rc);
175 }
176 
177 /*
178  *     Code Ident Operation
179  *     6x   WRD   Write data        Hx -> [Page, Address]
180  *                                  Address register + 1 -> Address register
181  *                                  0 -> H-register, 0 -> Mask register
182  */
183 int WRD(RIG *rig, unsigned char out)
184 {
185     int rc = RIG_OK;
186 
187     unsigned char op = ((0x0f & out) | op_WRD);
188 
189     assert(NULL != rig);
190 
191     rc = write_block(&rig->state.rigport, (char *) &op, 1);
192 
193     if (0 != rc)
194     {
195         rc = -RIG_EIO;
196     }
197 
198     return (rc);
199 }
200 
201 /*
202  *     Code Ident Operation
203  *     9x   MSK   Set mask          Hx -> Mask register <1>
204  *                                  0 -> H-register
205  */
206 int MSK(RIG *rig, unsigned char mask)
207 {
208     int rc = RIG_OK;
209 
210     unsigned char op = ((0x0f & mask) | op_MSK);
211 
212     assert(NULL != rig);
213 
214     rc = write_block(&rig->state.rigport, (char *) &op, 1);
215 
216     if (0 != rc)
217     {
218         rc = -RIG_EIO;
219     }
220 
221     return (rc);
222 }
223 
224 /*
225  *     Code Ident Operation
226  *     2x   EXE   Execute routine x
227  */
228 int EXE(RIG *rig, enum ROUTINE_e routine)
229 {
230     int rc = RIG_OK;
231 
232     unsigned char op = ((0x0f & routine) | op_EXE);
233 
234     assert(NULL != rig);
235 
236     switch (routine)
237     {
238     case RESET:
239     case SET_FREQ:
240     case SET_MODE:
241     case SET_PASS:
242     case SET_ALL:
243     case SET_AUDIO:
244     case SET_RFIF:
245     case DIR_RX_CTL:
246     case DIR_DDS_CTL:
247     case DISP_MENUS:
248     case DISP_FREQ:
249     case DISP_BUFF:
250     case READ_SIGNAL:
251     case READ_BTNS:
252         rc = write_block(&rig->state.rigport, (char *) &op, 1);
253 
254         if (0 != rc)
255         {
256             rc = -RIG_EIO;
257         }
258 
259         break;
260 
261     default:
262         rig_debug(RIG_DEBUG_VERBOSE, "EXE: invalid routine %d\n", routine);
263 
264         rc = -RIG_EINVAL;
265         break;
266     };
267 
268     return (rc);
269 }
270 
271 /*
272  *     Code Ident Operation
273  *     7x   RDD   Read data         [Page, Address] -> Serial output
274  *                                  Address register + x -> Address register
275  */
276 int RDD(RIG *rig, unsigned char len)
277 {
278     int rc = RIG_OK;
279     unsigned char inChr = 0;
280     unsigned char op = ((0x0f & len) | op_RDD);
281 
282     assert(NULL != rig);
283 
284     rc = write_block(&rig->state.rigport, (char *) &op, 1);
285 
286     if (0 != rc)
287     {
288         rc = -RIG_EIO;
289     }
290     else
291     {
292         rc = read_block(&rig->state.rigport, (char *) &inChr, len);
293 
294         if (1 != rc)
295         {
296             rc = -RIG_EIO;
297         }
298         else
299         {
300             rc = (int) inChr;
301         }
302     }
303 
304     return (rc);
305 }
306 
307 /*
308  *     Code Ident Operation
309  *     8x   LOC   Set lock level x
310  */
311 int LOC(RIG *rig, enum LOCK_LVL_e level)
312 {
313     int rc = RIG_OK;
314 
315     unsigned char op = ((0x0f & level) | op_LOC);
316 
317     assert(NULL != rig);
318 
319     switch (level)
320     {
321     case LOCK_0:
322     case LOCK_1:
323     case LOCK_2:
324     case LOCK_3:
325         rc = write_block(&rig->state.rigport, (char *) &op, 1);
326 
327         if (0 != rc)
328         {
329             rc = -RIG_EIO;
330         }
331 
332         break;
333 
334     default:
335         rig_debug(RIG_DEBUG_VERBOSE, "LOC: invalid lock level %d\n", level);
336 
337         rc = -RIG_EINVAL;
338         break;
339     };
340 
341     return (rc);
342 }
343 
344 /*
345  *     Code Ident Operation
346  *     Ax   BUT   Operate button x  <1>
347  */
348 int BUT(RIG *rig, enum BUTTON_e button)
349 {
350     int rc = RIG_OK;
351 
352     unsigned char op = ((0x0f & button) | op_BUT);
353 
354     assert(NULL != rig);
355 
356     switch (button)
357     {
358     case BTN_NONE:
359         break;
360 
361     case BTN_UP:
362     case BTN_DOWN:
363     case BTN_FAST:
364     case BTN_FILTER:
365     case BTN_RFIF:
366     case BTN_MEMORY:
367     case BTN_STAR:
368     case BTN_MENU:
369     case BTN_POWER:
370         rc = write_block(&rig->state.rigport, (char *) &op, 1);
371 
372         if (0 != rc)
373         {
374             rc = -RIG_EIO;
375         }
376 
377         break;
378 
379     default:
380         rig_debug(RIG_DEBUG_VERBOSE, "BUT: invalid button %d\n", button);
381 
382         rc = -RIG_EINVAL;
383         break;
384     };
385 
386     return (rc);
387 }
388 
389 #endif // 0
390 
391 /*
392  * /brief Execute routine
393  *
394  * /param rig Pointer to rig struct
395  * /param rtn Receiver routine to execute
396  *
397  * \return RIG_OK on success, error code on failure
398  *
399  */
execRoutine(RIG * rig,enum ROUTINE_e rtn)400 int execRoutine(RIG *rig, enum ROUTINE_e rtn)
401 {
402     int rc = -RIG_EIO;
403     unsigned char v = EXE((rtn & 0x0f));
404 
405     assert(NULL != rig);
406 
407     if (0 == write_block(&rig->state.rigport, (char *) &v, 1))
408     {
409         rc = RIG_OK;
410 
411         rig_debug(RIG_DEBUG_VERBOSE, "%s: routine %2d\n", __func__, rtn);
412     }
413 
414     return (rc);
415 }
416 
417 /*
418  * /brief Set address for I/O with radio
419  *
420  * /param rig Pointer to rig struct
421  * /param page Memory page number (0-4, 15)
422  * /param addr Address offset within page (0-4095, depending on page)
423  *
424  * \return RIG_OK on success, error code on failure
425  *
426  * Statics curPage and curAddr shadow radio's copies so that
427  * page and address are only set when needed
428  */
setAddr(RIG * rig,enum PAGE_e page,unsigned int addr)429 static int setAddr(RIG *rig, enum PAGE_e page, unsigned int addr)
430 {
431     int rc = RIG_OK;
432     unsigned char v;
433 
434     assert(NULL != rig);
435 
436     if ((EEPROM3 >= page) || (ROM == page))
437     {
438         if (AR7030_PAGE_SIZE[page] > addr)
439         {
440             if (curPage != page)
441             {
442                 v = PGE(page);
443 
444                 if (0 == write_block(&rig->state.rigport, (char *) &v, 1))
445                 {
446                     curPage = page;
447                     rc = RIG_OK;
448 
449                     rig_debug(RIG_DEBUG_VERBOSE, "%s: set page %2d\n", __func__, page);
450                 }
451                 else
452                 {
453                     rc = -RIG_EIO;
454                 }
455             }
456 
457             if (curAddr != addr)
458             {
459                 v = SRH((0x0f0 & addr) >> 4);
460 
461                 rc = write_block(&rig->state.rigport, (char *) &v, 1);
462 
463                 if (rc != RIG_OK)
464                 {
465                     return -RIG_EIO;
466                 }
467 
468                 v = ADR((0x00f & addr));
469 
470                 if (0 == write_block(&rig->state.rigport, (char *) &v, 1))
471                 {
472                     if (0xff < addr)
473                     {
474                         v = ADH((0xf00 & addr) >> 8);
475 
476                         if (0 == write_block(&rig->state.rigport, (char *) &v, 1))
477                         {
478                             curAddr = addr;
479                             rc = RIG_OK;
480 
481                             rig_debug(RIG_DEBUG_VERBOSE, "%s: set addr 0x%04x\n", __func__, addr);
482                         }
483                         else
484                         {
485                             rc = -RIG_EIO;
486                         }
487                     }
488                     else
489                     {
490                         curAddr = addr;
491                         rc = RIG_OK;
492 
493                         rig_debug(RIG_DEBUG_VERBOSE, "%s: set addr 0x%04x\n", __func__, addr);
494                     }
495                 }
496                 else
497                 {
498                     rc = -RIG_EIO;
499                 }
500             }
501         }
502         else
503         {
504             rc = -RIG_EINVAL; /* invalid address */
505         }
506     }
507     else
508     {
509         rc = -RIG_EINVAL; /* invalid page */
510     }
511 
512     return (rc);
513 }
514 
515 /*
516  * /brief Write one byte to the receiver
517  *
518  * /param rig Pointer to rig struct
519  * /param page Memory page number (0-4, 15)
520  * /param addr Address offset within page (0-4095, depending on page)
521  * /param x    Value to write to radio
522  *
523  * \return RIG_OK on success, error code on failure
524  *
525  */
writeByte(RIG * rig,enum PAGE_e page,unsigned int addr,unsigned char x)526 int writeByte(RIG *rig, enum PAGE_e page, unsigned int addr, unsigned char x)
527 {
528     int rc;
529     unsigned char hi = SRH((x & 0xf0) >> 4);
530     unsigned char lo = WRD(x & 0x0f);
531 
532     assert(NULL != rig);
533 
534     rc = setAddr(rig, page, addr);
535 
536     if (RIG_OK == rc)
537     {
538         rc = -RIG_EIO;
539 
540         if (0 == write_block(&rig->state.rigport, (char *) &hi, 1))
541         {
542             if (0 == write_block(&rig->state.rigport, (char *) &lo, 1))
543             {
544                 rc = RIG_OK;
545                 curAddr++;
546 
547                 rig_debug(RIG_DEBUG_VERBOSE, "%s: wrote byte 0x%02x\n", __func__, x);
548             }
549         }
550     }
551 
552     return (rc);
553 }
554 
555 /*
556  * /brief Write two bytes to the receiver
557  *
558  * /param rig  Pointer to rig struct
559  * /param page Memory page number (0-4, 15)
560  * /param addr Address offset within page (0-4095, depending on page)
561  * /param x    Value to write to radio
562  *
563  * \return Number of bytes written, 0 on error. Get error code with getErrno.
564  *
565  */
writeShort(RIG * rig,enum PAGE_e page,unsigned int addr,unsigned short x)566 int writeShort(RIG *rig, enum PAGE_e page, unsigned int addr, unsigned short x)
567 {
568     int rc;
569     unsigned char v = (unsigned char)((x & 0xff00) >> 8);
570 
571     rc = writeByte(rig, page, addr, v);
572 
573     if (RIG_OK == rc)
574     {
575         v = (unsigned char)(x & 0x00ff);
576         rc = writeByte(rig, page, addr + 1, v);
577     }
578 
579     return (rc);
580 }
581 
582 /*
583  * /brief Write three bytes to the receiver
584  *
585  * /param rig  Pointer to rig struct
586  * /param page Memory page number (0-4, 15)
587  * /param addr Address offset within page (0-4095, depending on page)
588  * /param x    Value to write to radio
589  *
590  * \return Number of bytes written, 0 on error. Get error code with getErrno.
591  *
592  */
write3Bytes(RIG * rig,enum PAGE_e page,unsigned int addr,unsigned int x)593 int write3Bytes(RIG *rig, enum PAGE_e page, unsigned int addr, unsigned int x)
594 {
595     int rc;
596     unsigned char v = (unsigned char)((x & 0xff0000) >> 16);
597 
598     rc = writeByte(rig, page, addr, v);
599 
600     if (RIG_OK == rc)
601     {
602         v = (unsigned char)((x & 0x00ff00) >> 8);
603         rc = writeByte(rig, page, addr + 1, v);
604 
605         if (RIG_OK == rc)
606         {
607             v = (unsigned char)(x & 0x0000ff);
608             rc = writeByte(rig, page, addr + 2, v);
609         }
610     }
611 
612     return (rc);
613 }
614 
615 #ifdef XXREMOVEDXX
616 // this function is not referenced anywhere
617 /*
618  * /brief Write unsigned int (4 bytes) to the receiver
619  *
620  * /param rig  Pointer to rig struct
621  * /param page Memory page number (0-4, 15)
622  * /param addr Address offset within page (0-4095, depending on page)
623  * /param x    Value to write to radio
624  *
625  * \return Number of bytes written, 0 on error. Get error code with getErrno.
626  *
627  */
writeInt(RIG * rig,enum PAGE_e page,unsigned int addr,unsigned int x)628 int writeInt(RIG *rig, enum PAGE_e page, unsigned int addr, unsigned int x)
629 {
630     int rc;
631     unsigned char v = (unsigned char)((x & 0xff000000) >> 24);
632 
633     rc = writeByte(rig, page, addr, v);
634 
635     if (RIG_OK == rc)
636     {
637         v = (unsigned char)((x & 0x00ff0000) >> 16);
638         rc = writeByte(rig, page, addr + 1, v);
639 
640         if (RIG_OK == rc)
641         {
642             v = (unsigned char)((x & 0x0000ff00) >> 8);
643             rc = writeByte(rig, page, addr + 2, v);
644 
645             if (RIG_OK == rc)
646             {
647                 v = (unsigned char)(x & 0x000000ff);
648                 rc = writeByte(rig, page, addr + 3, v);
649             }
650         }
651     }
652 
653     return (rc);
654 }
655 #endif
656 
657 /*
658  * /brief Read one byte from the receiver
659  *
660  * /param rig Pointer to rig struct
661  * /param page Memory page number (0-4, 15)
662  * /param addr Address offset within page (0-4095, depending on page)
663  * /param x    Pointer to value to read from radio
664  *
665  * \return RIG_OK on success, error code on failure
666  *
667  */
readByte(RIG * rig,enum PAGE_e page,unsigned int addr,unsigned char * x)668 int readByte(RIG *rig, enum PAGE_e page, unsigned int addr, unsigned char *x)
669 {
670     int rc = RIG_OK;
671     unsigned char v = RDD(1);   // Read command
672 
673     assert(NULL != rig);
674     assert(NULL != x);
675 
676     rc = setAddr(rig, page, addr);
677 
678     if (RIG_OK == rc)
679     {
680         rc = -RIG_EIO;
681 
682         if (0 == write_block(&rig->state.rigport, (char *) &v, 1))
683         {
684             if (1 == read_block(&rig->state.rigport, (char *) x, 1))
685             {
686                 curAddr++;
687                 rc = RIG_OK;
688 
689                 rig_debug(RIG_DEBUG_VERBOSE, "%s: read 0x%02x\n", __func__, *x);
690             }
691         }
692     }
693 
694     return (rc);
695 }
696 
697 /*
698  * /brief Read an unsigned short (two bytes) from the receiver
699  *
700  * /param rig Pointer to rig struct
701  * /param page Memory page number (0-4, 15)
702  * /param addr Address offset within page (0-4095, depending on page)
703  * /param x    Pointer to value to read from radio
704  *
705  * \return RIG_OK on success, error code on failure
706  *
707  */
readShort(RIG * rig,enum PAGE_e page,unsigned int addr,unsigned short * x)708 int readShort(RIG *rig, enum PAGE_e page, unsigned int addr, unsigned short *x)
709 {
710     int rc = RIG_OK;
711     unsigned char v;
712 
713     assert(NULL != rig);
714     assert(NULL != x);
715 
716     rc = readByte(rig, page, addr, &v);
717 
718     if (RIG_OK == rc)
719     {
720         *x = (unsigned short) v << 8;
721         rc = readByte(rig, page, addr + 1, &v);
722 
723         if (RIG_OK == rc)
724         {
725             *x += (unsigned short) v;
726 
727             rig_debug(RIG_DEBUG_VERBOSE, "%s: read 0x%04x\n", __func__, *x);
728         }
729     }
730 
731     return (rc);
732 }
733 
734 /*
735  * /brief Read an unsigned int (three bytes) from the receiver
736  *
737  * /param rig Pointer to rig struct
738  * /param page Memory page number (0-4, 15)
739  * /param addr Address offset within page (0-4095, depending on page)
740  * /param x    Pointer to value to read from radio
741  *
742  * \return RIG_OK on success, error code on failure
743  *
744  */
read3Bytes(RIG * rig,enum PAGE_e page,unsigned int addr,unsigned int * x)745 int read3Bytes(RIG *rig, enum PAGE_e page, unsigned int addr, unsigned int *x)
746 {
747     int rc = RIG_OK;
748     unsigned char v;
749 
750     assert(NULL != rig);
751     assert(NULL != x);
752 
753     rc = readByte(rig, page, addr, &v);
754 
755     if (RIG_OK == rc)
756     {
757         *x = (unsigned int) v << 16;
758         rc = readByte(rig, page, addr + 1, &v);
759 
760         if (RIG_OK == rc)
761         {
762             *x += (unsigned int) v << 8;
763             rc = readByte(rig, page, addr + 2, &v);
764 
765             if (RIG_OK == rc)
766             {
767                 *x += (unsigned int) v;
768 
769                 rig_debug(RIG_DEBUG_VERBOSE, "%s: read 0x%06x\n", __func__, *x);
770             }
771         }
772     }
773 
774     return (rc);
775 }
776 
777 #ifdef XXREMOVEDXX
778 // this function is not referenced anywhere
779 /*
780  * /brief Read an unsigned int (four bytes) from the receiver
781  *
782  * /param rig Pointer to rig struct
783  * /param page Memory page number (0-4, 15)
784  * /param addr Address offset within page (0-4095, depending on page)
785  * /param x    Pointer to value to read from radio
786  *
787  * \return RIG_OK on success, error code on failure
788  *
789  */
readInt(RIG * rig,enum PAGE_e page,unsigned int addr,unsigned int * x)790 int readInt(RIG *rig, enum PAGE_e page, unsigned int addr, unsigned int *x)
791 {
792     int rc = 0;
793     unsigned char v;
794 
795     assert(NULL != rig);
796     assert(NULL != x);
797 
798     rc = readByte(rig, page, addr, &v);
799 
800     if (RIG_OK == rc)
801     {
802         *x = (unsigned int) v << 24;
803         rc = readByte(rig, page, addr + 1, &v);
804 
805         if (RIG_OK == rc)
806         {
807             *x += (unsigned int) v << 16;
808             rc = readByte(rig, page, addr + 2, &v);
809 
810             if (RIG_OK == rc)
811             {
812                 *x += (unsigned int) v << 8;
813                 rc = readByte(rig, page, addr + 3, &v);
814                 {
815                     *x += (unsigned int) v;
816 
817                     rig_debug(RIG_DEBUG_VERBOSE, "%s: read 0x%08x\n", __func__, *x);
818                 }
819             }
820         }
821     }
822 
823     return (rc);
824 }
825 #endif
826 
827 /*
828  * /brief Read raw AGC value from the radio
829  *
830  * /param rig Pointer to rig struct
831  *
832  * \return RIG_OK on success, error code on failure
833  */
readSignal(RIG * rig,unsigned char * x)834 int readSignal(RIG *rig, unsigned char *x)
835 {
836     int rc;
837 
838     assert(NULL != rig);
839     assert(NULL != x);
840 
841     rc = execRoutine(rig, READ_SIGNAL);   // Read raw AGC value
842 
843     if (RIG_OK == rc)
844     {
845         if (1 == read_block(&rig->state.rigport, (char *) x, 1))
846         {
847             rc = RIG_OK;
848 
849             rig_debug(RIG_DEBUG_VERBOSE, "%s: raw AGC %03d\n", __func__, *x);
850         }
851     }
852 
853     return (rc);
854 }
855 
856 #ifdef XXREMOVEDXX
857 // this function is not referenced anywhere
858 /*
859  * /brief Flush I/O with radio
860  *
861  * /param rig Pointer to rig struct
862  *
863  */
flushBuffer(RIG * rig)864 int flushBuffer(RIG *rig)
865 {
866     int rc = -RIG_EIO;
867     char v = '/';
868 
869     assert(NULL != rig);
870 
871     if (0 == write_block(&rig->state.rigport, &v, 1))
872     {
873         rc = RIG_OK;
874     }
875 
876     return (rc);
877 }
878 #endif
879 
880 /*
881  * /brief Lock receiver for remote operations
882  *
883  * /param rig Pointer to rig struct
884  * /param level Lock level (0-3)
885  *
886  */
lockRx(RIG * rig,enum LOCK_LVL_e level)887 int lockRx(RIG *rig, enum LOCK_LVL_e level)
888 {
889     int rc = -RIG_EIO;
890     unsigned char v;
891 
892     assert(NULL != rig);
893 
894     if (LOCK_NONE > level)   /* valid level? */
895     {
896         if (curLock != level)   /* need to change level? */
897         {
898             v = LOC(level);
899 
900             if (0 == write_block(&rig->state.rigport, (char *) &v, 1))
901             {
902                 rc = RIG_OK;
903 
904                 curLock = level;
905             }
906         }
907         else
908         {
909             rc = RIG_OK;
910         }
911     }
912     else
913     {
914         rc = -RIG_EINVAL;
915     }
916 
917     return (rc);
918 }
919 
920 /*
921  * \brief Convert one byte BCD value to int
922  *
923  * \param bcd BCD value (0-99)
924  *
925  * \return Integer value of BCD parameter (0-99), -1 on failure
926  */
bcd2Int(const unsigned char bcd)927 int bcd2Int(const unsigned char bcd)
928 {
929     int rc = -1;
930     unsigned char hi = ((bcd & 0xf0) >> 4);
931     unsigned char lo = (bcd & 0x0f);
932 
933     if ((unsigned char) 0x0a > hi)
934     {
935         rc = (int) hi * 10;
936 
937         if ((unsigned char) 0x0a > lo)
938         {
939             rc += (int) lo;
940         }
941         else
942         {
943             rc = -1;
944         }
945     }
946 
947     return (rc);
948 }
949 
950 #ifdef XXREMOVEDXX
951 // this function is not referenced anywhere
952 /*
953  * \brief Convert int into 2 digit BCD number
954  *
955  * \param int Integer value (0-99)
956  *
957  * \return 2 digit BCD equivalent (0-99), 0xff on failure
958  */
int2BCD(const unsigned int val)959 unsigned char int2BCD(const unsigned int val)
960 {
961     unsigned char rc = (unsigned char) 0xff;
962     unsigned char tens = (unsigned char)(val / 10);
963     unsigned char ones = (unsigned char)(val % 10);
964 
965     if ((unsigned char) 10 > tens)
966     {
967         rc = (tens << 4);
968 
969         if ((unsigned char) 10 > ones)
970         {
971             rc = rc | ones;
972         }
973         else
974         {
975             rc = (unsigned char) 0xff;
976         }
977     }
978 
979     return (rc);
980 }
981 #endif
982 
983 /*
984  * \brief Convert raw AGC value to calibrated level in dBm
985  *
986  * \param rig Pointer to rig struct
987  * \param rawAgc raw AGC value (0-255)
988  * \param tab Pointer to calibration table struct
989  * \param dbm Pointer to value to hold calibrated level (S9 = 0 dBm)
990  *
991  * \return RIG_OK on success, error code on failure
992  *
993  * To calculate the signal level, table values should be subtracted from
994  * the AGC voltage in turn until a negative value would result. This gives
995  * the rough level from the table position. The accuracy can be improved by
996  * proportioning the remainder into the next table step. See the following
997  * example :-
998  *
999  * A read signal strength operation returns a value of 100
1000  * Subtract cal byte 1 (64) leaves 36 level > -113dBm
1001  * Subtract cal byte 2 (10) leaves 26 level > -103dBm
1002  * Subtract cal byte 3 (10) leaves 16 level > -93dBm
1003  * Subtract cal byte 4 (12) leaves 4 level > -83dBm
1004  * Test cal byte 5 (12) - no subtraction
1005  * Fine adjustment value = (remainder) / (cal byte 5) * (level step)
1006  *                       = 4 / 12 * 10 = 3dB
1007  * Signal level = -83dBm + 3dB = -80dB
1008  *
1009  * The receiver can operate the RF attenuator automatically if the signal
1010  * level is likely to overload the RF stages. Reading the RFAGC byte (page 0,
1011  * location 49) gives the attenuation in 10dB steps. This value should be
1012  * read and added to the value calculated above.
1013  */
getCalLevel(RIG * rig,unsigned char rawAgc,int * dbm)1014 int getCalLevel(RIG *rig, unsigned char rawAgc, int *dbm)
1015 {
1016     int rc = RIG_OK;
1017     int i;
1018     int raw = (int) rawAgc;
1019     int step;
1020     unsigned char v;
1021 
1022     assert(NULL != rig);
1023     assert(NULL != dbm);
1024 
1025     rig_debug(RIG_DEBUG_VERBOSE, "%s: raw AGC %03d\n", __func__, rawAgc);
1026 
1027     for (i = 0; i < rig->state.str_cal.size; i++)
1028     {
1029         *dbm = rig->state.str_cal.table[ i ].val;
1030 
1031         rig_debug(RIG_DEBUG_VERBOSE, "%s: got cal table[ %d ] dBm value %d\n", __func__,
1032                   i, *dbm);
1033 
1034         /* if the remaining difference in the raw value is negative */
1035         if (0 > (raw - rig->state.str_cal.table[ i ].raw))
1036         {
1037             /* calculate step size */
1038             if (0 < i)
1039             {
1040                 step = rig->state.str_cal.table[ i ].val -
1041                        rig->state.str_cal.table[ i - 1 ].val;
1042             }
1043             else
1044             {
1045                 step = 20; /* HACK - try and fix minimum AGC readings */
1046             }
1047 
1048             rig_debug(RIG_DEBUG_VERBOSE, "%s: got step size %d\n", __func__, step);
1049 
1050             /* interpolate the final value */
1051             *dbm -= step; /* HACK - table seems to be off by one index */
1052             *dbm += (int)(((double) raw / (double) rig->state.str_cal.table[ i ].raw) *
1053                           (double) step);
1054 
1055             rig_debug(RIG_DEBUG_VERBOSE, "%s: interpolated dBm value %d\n", __func__, *dbm);
1056 
1057             /* we're done, stop going through the table */
1058             break;
1059         }
1060         else
1061         {
1062             /* calculate the remaining raw value */
1063             raw = raw - rig->state.str_cal.table[ i ].raw;
1064 
1065             rig_debug(RIG_DEBUG_VERBOSE, "%s: residual raw value %d\n", __func__, raw);
1066         }
1067     }
1068 
1069     /* Factor in Attenuator/preamp settings */
1070     /* 40 0x028  rxcon 3 bytes  Receiver control register mapping */
1071     rc = readByte(rig, WORKING, RXCON, &v);
1072 
1073     if (RIG_OK == rc)
1074     {
1075         if (0x80 & v)   /* byte 1 bit 7  rx_atn        Attenuator enable */
1076         {
1077             if (0xa0 & v)
1078             {
1079                 /* HACK - Settings menu on radio says Atten step is 10 dB, not 20 dB */
1080                 *dbm += 20; /* byte 1 bit 5  rx_atr        Atten : 0 = 20dB / 1 = 40dB */
1081             }
1082             else
1083             {
1084                 *dbm += 10; /* byte 1 bit 5  rx_atr        Atten : 0 = 20dB / 1 = 40dB */
1085             }
1086         }
1087 
1088         if (0x10 & v)   /* byte 1 bit 4  rx_pre        Preamplifier enable */
1089         {
1090             *dbm -= 10;
1091         }
1092 
1093         rig_debug(RIG_DEBUG_VERBOSE, "%s: RXCON 0x%02x, adjusted dBm value %d\n",
1094                   __func__, (int) v, *dbm);
1095     }
1096 
1097     /* Adjust to S9 == 0 scale */
1098     *dbm += 73; /* S9 == -73 dBm */
1099 
1100     rig_debug(RIG_DEBUG_VERBOSE, "%s: S9 adjusted dBm value %d\n", __func__, *dbm);
1101 
1102     return (rc);
1103 }
1104 
1105 /*
1106  * \brief Get bandwidth of given filter
1107  *
1108  * \param rig Pointer to rig struct
1109  * \param filter Filter number (1-6)
1110  *
1111  * \return Filter bandwidth in Hz, -1 on failure
1112  */
getFilterBW(RIG * rig,enum FILTER_e filter)1113 int getFilterBW(RIG *rig, enum FILTER_e filter)
1114 {
1115     int rc;
1116     unsigned char bw;
1117 
1118     rc = readByte(rig, BBRAM, (FL_BW + ((filter - 1) * 4)), &bw);
1119 
1120     if (RIG_OK == rc)
1121     {
1122         rc = bcd2Int(bw) * 100;
1123     }
1124     else
1125     {
1126         rig_debug(RIG_DEBUG_ERR, "%s: readByte err: %s\n", __func__, strerror(rc));
1127         return rc;
1128     }
1129 
1130     rig_debug(RIG_DEBUG_VERBOSE, "%s: filter %1d BW %5d\n", __func__, filter, rc);
1131 
1132     return (rc);
1133 }
1134 
1135 /*
1136  * /brief Convert DDS steps to frequency in Hz
1137  *
1138  * /param steps DDS count
1139  *
1140  * /return Frequency in Hz or 0 on failure
1141  */
ddsToHz(const unsigned int steps)1142 freq_t ddsToHz(const unsigned int steps)
1143 {
1144     freq_t rc = 0.0;
1145 
1146     rc = ((freq_t) steps * 44545000.0 / 16777216.0);
1147 
1148     return (rc);
1149 }
1150 
1151 /*
1152  * /brief Convert frequency in Hz to DDS steps
1153  *
1154  * /param freq Frequency in Hz
1155  *
1156  * /return DDS steps (24 bits) or 0 on failure
1157  */
hzToDDS(const freq_t freq)1158 unsigned int hzToDDS(const freq_t freq)
1159 {
1160     unsigned int rc = 0;
1161     double err[3] = { 0.0, 0.0, 0.0 };
1162 
1163     rc = (unsigned int)(freq * 16777216.0 / 44545000.0);
1164 
1165     /* calculate best DDS count based on bletcherous,
1166        irrational tuning step of 2.65508890151977539062 Hz/step
1167        (actual ratio is 44545000.0 / 16777216.0) */
1168     err[ 0 ] = fabs(freq - ddsToHz((rc - 1)));
1169     err[ 1 ] = fabs(freq - ddsToHz(rc));
1170     err[ 2 ] = fabs(freq - ddsToHz((rc + 1)));
1171 
1172     if (err[ 0 ] < err[ 1 ] && err[ 0 ] < err[ 2 ])
1173     {
1174         rc--;
1175     }
1176     else if (err[ 2 ] < err[ 1 ] && err[ 2 ] < err[ 0 ])
1177     {
1178         rc++;
1179     }
1180 
1181     rig_debug(RIG_DEBUG_VERBOSE, "%s: err[0 - 2] = %f %f %f rc 0x%08x\n",
1182               __func__, err[ 0 ], err[ 1 ], err[ 2 ], rc);
1183 
1184     return (rc);
1185 }
1186 
1187 /*
1188  * /brief Convert PBS/BFO steps to frequency in Hz
1189  *
1190  * /param steps PBS/BFO offset steps
1191  *
1192  * /return Frequency in Hz or 0 on failure
1193  *
1194  * Max +ve offset is 127, max -ve offset is 128
1195  * Min -ve offset is 255
1196  */
pbsToHz(const unsigned char steps)1197 float pbsToHz(const unsigned char steps)
1198 {
1199     freq_t rc = 0.0;
1200 
1201     /* treat steps as a 1's complement signed 8-bit number */
1202     if (128 > steps)
1203     {
1204         rc = (((float) steps * 12.5 * 44545000.0) / 16777216.0);
1205     }
1206     else
1207     {
1208         rc = (((float)(~steps & 0x7f) * -12.5 * 44545000.0) / 16777216.0);
1209     }
1210 
1211     rig_debug(RIG_DEBUG_VERBOSE, "%s: raw %d hz %f\n", __func__, steps, rc);
1212 
1213     return (rc);
1214 }
1215 
1216 #ifdef XXREMOVEDXX
1217 // this function is not referenced anywhere
1218 /*
1219  * /brief Convert PBS/BFO offset frequency in Hz to steps
1220  *
1221  * /param freq Offset frequency in Hz
1222  *
1223  * /return steps (8 bits) or 0 on failure
1224  */
hzToPBS(const float freq)1225 unsigned char hzToPBS(const float freq)
1226 {
1227     unsigned char rc;
1228     int steps;
1229 
1230     if (0 < freq)
1231     {
1232         steps = (((freq + 0.5) * 16777216.0) / (44545000.0 * 12.5));
1233     }
1234     else
1235     {
1236         steps = (((freq - 0.5) * 16777216.0) / (44545000.0 * 12.5));
1237     }
1238 
1239     rig_debug(RIG_DEBUG_VERBOSE, "%s: steps %d\n", __func__, steps);
1240 
1241     if (0 <= steps)
1242     {
1243         rc = (unsigned char)(steps & 0x7f);
1244     }
1245     else if (-128 < steps)
1246     {
1247         rc = (unsigned char)(steps + 255);
1248     }
1249     else
1250     {
1251         rc = (unsigned char) 0;
1252     }
1253 
1254     rig_debug(RIG_DEBUG_VERBOSE, "%s: hz %f rc %d\n", __func__, freq, rc);
1255 
1256     return (rc);
1257 }
1258 #endif
1259 
1260 /*
1261  * /brief Convert native Mode to Hamlib mode
1262  *
1263  * /param mode Native mode value
1264  *
1265  * /return Hamlib mode value
1266  */
modeToHamlib(const unsigned char mode)1267 rmode_t modeToHamlib(const unsigned char mode)
1268 {
1269     rmode_t rc = RIG_MODE_NONE;
1270 
1271     switch (mode)
1272     {
1273     case AM:
1274         rc = RIG_MODE_AM;
1275         break;
1276 
1277     case SAM:
1278         rc = RIG_MODE_AMS;
1279         break;
1280 
1281     case FM:
1282         rc = RIG_MODE_FM;
1283         break;
1284 
1285     case DATA:
1286         rc = RIG_MODE_RTTY;
1287         break;
1288 
1289     case CW:
1290         rc = RIG_MODE_CW;
1291         break;
1292 
1293     case LSB:
1294         rc = RIG_MODE_LSB;
1295         break;
1296 
1297     case USB:
1298         rc = RIG_MODE_USB;
1299         break;
1300 
1301     default:
1302         break;
1303     };
1304 
1305     rig_debug(RIG_DEBUG_VERBOSE, "%s: Native %s, Hamlib %s\n",
1306               __func__, rig_strrmode(mode), rig_strrmode(rc));
1307 
1308     return (rc);
1309 }
1310 
1311 /*
1312  * /brief Convert Hamlib Mode to native mode
1313  *
1314  * /param mode Hamlib mode value
1315  *
1316  * /return Native mode value
1317  */
modeToNative(const rmode_t mode)1318 unsigned char modeToNative(const rmode_t mode)
1319 {
1320     unsigned char rc = (unsigned char) MODE_NONE;
1321 
1322     switch (mode)
1323     {
1324     case RIG_MODE_AM:
1325         rc = (unsigned char) AM;
1326         break;
1327 
1328     case RIG_MODE_AMS:
1329         rc = (unsigned char) SAM;
1330         break;
1331 
1332     case RIG_MODE_FM:
1333         rc = (unsigned char) FM;
1334         break;
1335 
1336     case RIG_MODE_RTTY:
1337         rc = (unsigned char) DATA;
1338         break;
1339 
1340     case RIG_MODE_CW:
1341         rc = (unsigned char) CW;
1342         break;
1343 
1344     case RIG_MODE_LSB:
1345         rc = (unsigned char) LSB;
1346         break;
1347 
1348     case RIG_MODE_USB:
1349         rc = (unsigned char) USB;
1350         break;
1351 
1352     default:
1353         break;
1354     };
1355 
1356     rig_debug(RIG_DEBUG_VERBOSE, "%s: Hamlib %s, native %d\n",
1357               __func__, rig_strrmode(mode), rc);
1358 
1359     return (rc);
1360 }
1361 
1362 /*
1363  * /brief Convert native AGC speed to Hamlib AGC speed
1364  *
1365  * /param agc Native AGC speed value
1366  *
1367  * /return Hamlib AGC speed value
1368  */
agcToHamlib(const unsigned char agc)1369 enum agc_level_e agcToHamlib(const unsigned char agc)
1370 {
1371     enum agc_level_e rc = RIG_AGC_AUTO;
1372 
1373     switch (agc)
1374     {
1375     case AGC_FAST:
1376         rc = RIG_AGC_FAST;
1377         break;
1378 
1379     case AGC_MED:
1380         rc = RIG_AGC_MEDIUM;
1381         break;
1382 
1383     case AGC_SLOW:
1384         rc = RIG_AGC_SLOW;
1385         break;
1386 
1387     case AGC_OFF:
1388         rc = RIG_AGC_OFF;
1389         break;
1390 
1391     default:
1392         break;
1393     };
1394 
1395     rig_debug(RIG_DEBUG_VERBOSE, "%s: Native %d, Hamlib %d\n",
1396               __func__, agc, rc);
1397 
1398     return (rc);
1399 }
1400 
1401 /*
1402  * /brief Convert Hamlib AGC speed to native AGC speed
1403  *
1404  * /param agc Hamlib AGC speed value
1405  *
1406  * /return Native AGC speed value
1407  */
agcToNative(const enum agc_level_e agc)1408 unsigned char agcToNative(const enum agc_level_e agc)
1409 {
1410     unsigned char rc = (unsigned char) AGC_NONE;
1411 
1412     switch (agc)
1413     {
1414     case RIG_AGC_OFF:
1415         rc = (unsigned char) AGC_OFF;
1416         break;
1417 
1418     case RIG_AGC_FAST:
1419         rc = (unsigned char) AGC_FAST;
1420         break;
1421 
1422     case RIG_AGC_SLOW:
1423         rc = (unsigned char) AGC_SLOW;
1424         break;
1425 
1426     case RIG_AGC_MEDIUM:
1427         rc = (unsigned char) AGC_MED;
1428         break;
1429 
1430     case RIG_AGC_SUPERFAST:
1431     case RIG_AGC_USER:
1432     case RIG_AGC_AUTO:
1433     default:
1434         rc = (unsigned char) AGC_NONE;
1435         break;
1436     };
1437 
1438     rig_debug(RIG_DEBUG_VERBOSE, "%s: Hamlib %d, native %d\n",
1439               __func__, agc, rc);
1440 
1441     return (rc);
1442 }
1443 
1444 /*
1445  * /brief Get page size
1446  *
1447  * /param page Page to get size of
1448  *
1449  * /return Page size, -1 on error
1450  */
pageSize(const enum PAGE_e page)1451 int pageSize(const enum PAGE_e page)
1452 {
1453     int rc = -1;
1454 
1455     if ((WORKING <= page) && (EEPROM3 >= page))
1456     {
1457         rc = (int) AR7030_PAGE_SIZE[ page ];
1458     }
1459     else if (ROM == page)
1460     {
1461         rc = (int) AR7030_PAGE_SIZE[ page ];
1462     }
1463     else
1464     {
1465         rc = -1;
1466     }
1467 
1468     return (rc);
1469 }
1470 
1471 /*
1472  * /brief Set and execute IR controller code
1473  *
1474  * /param code IR code to execute
1475  *
1476  * \return RIG_OK on success, error code on failure
1477  */
sendIRCode(RIG * rig,enum IR_CODE_e code)1478 int sendIRCode(RIG *rig, enum IR_CODE_e code)
1479 {
1480     int rc;
1481     unsigned char v = (unsigned char) code;
1482 
1483     assert(NULL != rig);
1484 
1485     rc = writeByte(rig, WORKING, IRCODE, v);
1486 
1487     if (RIG_OK == rc)
1488     {
1489         rc = execRoutine(rig, SET_ALL);
1490 
1491         if (RIG_OK == rc)
1492         {
1493             rig_debug(RIG_DEBUG_VERBOSE, "%s: set IR code %d\n", __func__, code);
1494         }
1495     }
1496 
1497     return (rc);
1498 }
1499 
1500