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