2
* Kenwood TS480SAT driver
3
* originally based on Kenwood TS480SAT driver
7
* Copyright 2009, Dave Freese, W1HKJ
15
static const char TS480SATname_[] = "TS-480SAT";
17
static const char *TS480SATmodes_[] = {
18
"LSB", "USB", "CW", "FM", "AM", "FSK", "CW-R", "FSK-R", NULL};
19
static const char TS480SAT_mode_chr[] = { '1', '2', '3', '4', '5', '6', '7', '9' };
20
static const char TS480SAT_mode_type[] = { 'L', 'U', 'U', 'U', 'U', 'L', 'L', 'U' };
22
static const char *TS480SAT_empty[] = { "N/A", NULL };
24
// SL command is lo cutoff when menu 045 OFF
25
static const char *TS480SAT_lo[] = {
26
"0", "50", "100", "200", "300",
27
"400", "500", "600", "700", "800",
28
"900", "1000", NULL };
29
static const char *TS480SAT_lo_tooltip = "lo cutoff";
30
static const char *TS480SAT_btn_lo_label = "L";
32
// SH command is hi cutoff when menu 045 OFF
33
static const char *TS480SAT_hi[] = {
34
"1000", "1200", "1400", "1600", "1800",
35
"2000", "2200", "2400", "2600", "2800",
36
"3000", "3400", "4000", "5000", NULL };
37
static const char *TS480SAT_hi_tooltip = "hi cutoff";
38
static const char *TS480SAT_btn_hi_label = "H";
40
// SL command is width when menu 045 ON
41
static const char *TS480SAT_dataW[] = {
42
"50", "100", "250", "500", "1000", "1500", "2400", NULL };
43
static const char *TS480SAT_dataW_tooltip = "filter width";
44
static const char *TS480SAT_dataW_label = "W";
46
// SH command is center frequency when menu 045 ON
47
static const char *TS480SAT_dataC[] = {
48
"1000", "1500", "2210", NULL };
49
static const char *TS480SAT_dataC_tooltip = "center frequency";
50
static const char *TS480SAT_dataC_label = "C";
52
static const char *TS480SAT_AM_lo[] = {
53
"10", "100", "200", "500",
56
static const char *TS480SAT_AM_hi[] = {
57
"2500", "3000", "4000", "5000",
60
static const char *TS480SAT_CWwidths[] = {
61
"50", "80", "100", "150", "200",
62
"300", "400", "500", "600", "1000",
65
static const char *TS480SAT_CWbw[] = {
66
"FW0050;", "FW0080;", "FW0100;", "FW0150;", "FW0200;",
67
"FW0300;", "FW0400;", "FW0500;", "FW0600;", "FW1000;",
70
static const char *TS480SAT_FSKwidths[] = {
71
"250", "500", "1000", "1500", NULL};
72
static const char *TS480SAT_FSKbw[] = {
73
"FW0250;", "FW0500;", "FW1000;", "FW1500;" };
75
static GUI rig_widgets[]= {
76
{ (Fl_Widget *)btnVol, 2, 125, 50 },
77
{ (Fl_Widget *)sldrVOLUME, 54, 125, 156 },
78
{ (Fl_Widget *)sldrRFGAIN, 54, 145, 156 },
79
{ (Fl_Widget *)btnIFsh, 214, 105, 50 },
80
{ (Fl_Widget *)sldrIFSHIFT, 266, 105, 156 },
81
{ (Fl_Widget *)btnDataPort, 214, 125, 50 },
82
{ (Fl_Widget *)sldrMICGAIN, 266, 125, 156 },
83
{ (Fl_Widget *)sldrPOWER, 266, 145, 156 },
84
{ (Fl_Widget *)NULL, 0, 0, 0 }
87
void RIG_TS480SAT::initialize()
89
rig_widgets[0].W = btnVol;
90
rig_widgets[1].W = sldrVOLUME;
91
rig_widgets[2].W = sldrRFGAIN;
92
rig_widgets[3].W = btnIFsh;
93
rig_widgets[4].W = sldrIFSHIFT;
94
rig_widgets[5].W = btnDataPort;
95
rig_widgets[6].W = sldrMICGAIN;
96
rig_widgets[7].W = sldrPOWER;
98
if (progStatus.UIsize == small_ui) has_extras = false;
99
progStatus.rfgain = 100;
100
progStatus.volume = 25;
101
progStatus.power_level = 20;
102
progStatus.mic_gain = 25;
106
RIG_TS480SAT::RIG_TS480SAT() {
108
name_ = TS480SATname_;
109
modes_ = TS480SATmodes_;
110
_mode_type = TS480SAT_mode_type;
111
bandwidths_ = TS480SAT_empty;
113
dsp_lo = TS480SAT_lo;
114
lo_tooltip = TS480SAT_lo_tooltip;
115
lo_label = TS480SAT_btn_lo_label;
117
dsp_hi = TS480SAT_hi;
118
hi_tooltip = TS480SAT_hi_tooltip;
119
hi_label = TS480SAT_btn_hi_label;
121
widgets = rig_widgets;
123
comm_baudrate = BR4800;
129
comm_rtsplus = false;
130
comm_dtrplus = false;
134
B.imode = A.imode = 1;
135
B.iBW = A.iBW = 0x8A03;
136
B.freq = A.freq = 14070000;
138
can_change_alt_vfo = true;
140
has_noise_control = false;
141
has_tune_control = false;
142
has_notch_control = false;
147
has_data_port = true;
148
has_micgain_control = true;
149
has_ifshift_control = true;
150
has_rf_control = true;
151
has_swr_control = true;
152
has_alc_control = true;
153
has_power_out = true;
154
has_dsp_controls = true;
156
has_swr_control = true;
157
has_attenuator_control = true;
158
has_preamp_control = true;
159
has_mode_control = true;
160
has_bandwidth_control = true;
161
has_volume_control = true;
162
has_power_control = true;
163
has_tune_control = true;
164
has_ptt_control = true;
171
const char * RIG_TS480SAT::get_bwname_(int n, int md)
173
static char bwname[20];
175
int hi = (n >> 8) & 0x7F;
177
snprintf(bwname, sizeof(bwname), "%s/%s",
178
(md == 0 || md == 1 || md == 3) ? dsp_lo[lo] : TS480SAT_AM_lo[lo],
179
(md == 0 || md == 1 || md == 3) ? dsp_hi[hi] : TS480SAT_AM_hi[hi] );
181
snprintf(bwname, sizeof(bwname), "%s",
182
(md == 2 || md == 6) ? TS480SAT_CWwidths[n] : TS480SAT_FSKwidths[n]);
187
void RIG_TS480SAT::check_menu_45()
189
// read current switch 45 setting
191
cmd = "EX0450000;"; sendCommand(cmd);
192
int ret = waitN(11, 100, "Check menu item 45", ASC);
194
size_t p = replystr.rfind("EX045");
195
if (p != string::npos)
196
menu_45 = (replystr[p+9] == '1');
200
dsp_lo = TS480SAT_dataW;
201
lo_tooltip = TS480SAT_dataW_tooltip;
202
lo_label = TS480SAT_dataW_label;
203
dsp_hi = TS480SAT_dataC;
204
hi_tooltip = TS480SAT_dataC_tooltip;
205
hi_label = TS480SAT_dataC_label;
206
B.iBW = A.iBW = 0x8106;
208
dsp_lo = TS480SAT_lo;
209
lo_tooltip = TS480SAT_lo_tooltip;
210
lo_label = TS480SAT_btn_lo_label;
211
dsp_hi = TS480SAT_hi;
212
hi_tooltip = TS480SAT_hi_tooltip;
213
hi_label = TS480SAT_btn_hi_label;
214
B.iBW = A.iBW = 0x8A03;
218
void RIG_TS480SAT::shutdown()
222
void RIG_TS480SAT::selectA()
226
showresp(WARN, ASC, "Rx on A, Tx on A", cmd, replystr);
229
void RIG_TS480SAT::selectB()
233
showresp(WARN, ASC, "Rx on B, Tx on B", cmd, replystr);
236
void RIG_TS480SAT::set_split(bool val)
244
showresp(WARN, ASC, "Rx on B, Tx on A", cmd, replystr);
248
showresp(WARN, ASC, "Rx on B, Tx on B", cmd, replystr);
254
showresp(WARN, ASC, "Rx on A, Tx on B", cmd, replystr);
258
showresp(WARN, ASC, "Rx on A, Tx on A", cmd, replystr);
261
Fl::awake(highlight_vfo, (void *)0);
264
bool RIG_TS480SAT::can_split()
269
int RIG_TS480SAT::get_split()
277
waitN(4, 100, "get split tx vfo", ASC);
278
p = replystr.rfind(rsp);
279
if (p == string::npos) return split;
285
waitN(4, 100, "get split rx vfo", ASC);
287
p = replystr.rfind(rsp);
288
if (p == string::npos) return split;
291
split = (tx == '1' ? 2 : 0) + (rx == '1' ? 1 : 0);
296
long RIG_TS480SAT::get_vfoA ()
299
int ret = waitN(14, 100, "get vfo A", ASC);
300
if (ret < 14) return A.freq;
301
size_t p = replystr.rfind("FA");
302
if (p != string::npos && (p + 12 < replystr.length())) {
304
for (size_t n = 2; n < 13; n++)
305
f = f*10 + replystr[p+n] - '0';
311
void RIG_TS480SAT::set_vfoA (long freq)
314
cmd = "FA00000000000;";
315
for (int i = 12; i > 1; i--) {
320
showresp(WARN, ASC, "set vfo A", cmd, replystr);
323
long RIG_TS480SAT::get_vfoB ()
326
int ret = waitN(14, 100, "get vfo B", ASC);
327
if (ret < 14) return B.freq;
328
size_t p = replystr.rfind("FB");
329
if (p != string::npos && (p + 12 < replystr.length())) {
331
for (size_t n = 2; n < 13; n++)
332
f = f*10 + replystr[p+n] - '0';
338
void RIG_TS480SAT::set_vfoB (long freq)
341
cmd = "FB00000000000;";
342
for (int i = 12; i > 1; i--) {
347
showresp(WARN, ASC, "set vfo B", cmd, replystr);
350
// SM cmd 0 ... 100 (rig values 0 ... 15)
351
int RIG_TS480SAT::get_smeter()
355
int ret = waitN(8, 100, "get Smeter", ASC);
356
if (ret < 8) return 0;
358
size_t p = replystr.rfind("SM");
359
if (p != string::npos)
360
mtr = 5 * atoi(&replystr[p + 3]);
364
int RIG_TS480SAT::get_power_out()
368
int ret = waitN(8, 100, "get power", ASC);
369
if (ret < 8) return mtr;
370
size_t p = replystr.rfind("SM");
371
if (p != string::npos) {
372
mtr = 5 * atoi(&replystr[p + 3]);
373
if (mtr > 100) mtr = 100;
378
// RM cmd 0 ... 100 (rig values 0 ... 8)
379
// User report of RM; command using Send Cmd tab
380
// RM10000;RM20000;RM30000;
385
int RIG_TS480SAT::get_swr()
389
int ret = waitN(8, 100, "get SWR/ALC", ASC);
390
if (ret < 8) return (int)mtr;
391
size_t p = replystr.rfind("RM1");
392
if (p != string::npos)
393
mtr = 66 * atoi(&replystr[p + 3]) / 10;
394
p = replystr.rfind("RM3");
395
if (p != string::npos)
396
alc = 66 * atoi(&replystr[p+3]) / 10;
399
swralc_polled = true;
403
int RIG_TS480SAT::get_alc(void)
405
if (!swralc_polled) get_swr();
406
swralc_polled = false;
410
// Tranceiver PTT on/off
411
void RIG_TS480SAT::set_PTT_control(int val)
414
if (progStatus.data_port) cmd = "TX1;"; // DTS transmission using ANI input
415
else cmd = "TX0;"; // mic input
418
showresp(WARN, ASC, "set PTT", cmd, replystr);
421
int RIG_TS480SAT::set_widths(int val)
424
if (val == 0 || val == 1 || val == 3) {
425
bandwidths_ = TS480SAT_empty;
427
bw = 0x8106; // 1500 Hz 2400 wide
428
dsp_lo = TS480SAT_dataW;
429
lo_tooltip = TS480SAT_dataW_tooltip;
430
lo_label = TS480SAT_dataW_label;
431
dsp_hi = TS480SAT_dataC;
432
hi_tooltip = TS480SAT_dataC_tooltip;
433
hi_label = TS480SAT_dataC_label;
435
bw = 0x8A03; // 200 ... 3000 Hz
436
dsp_lo = TS480SAT_lo;
437
lo_tooltip = TS480SAT_lo_tooltip;
438
lo_label = TS480SAT_btn_lo_label;
439
dsp_hi = TS480SAT_hi;
440
hi_tooltip = TS480SAT_hi_tooltip;
441
hi_label = TS480SAT_btn_hi_label;
443
} else if (val == 2 || val == 6) {
444
bandwidths_ = TS480SAT_CWwidths;
445
dsp_lo = TS480SAT_empty;
446
dsp_hi = TS480SAT_empty;
448
} else if (val == 5 || val == 7) {
449
bandwidths_ = TS480SAT_FSKwidths;
450
dsp_lo = TS480SAT_empty;
451
dsp_hi = TS480SAT_empty;
453
} else { // val == 4 ==> AM
454
bandwidths_ = TS480SAT_empty;
455
dsp_lo = TS480SAT_AM_lo;
456
dsp_hi = TS480SAT_AM_hi;
462
const char **RIG_TS480SAT::bwtable(int m)
464
if (m == 0 || m == 1 || m == 3)
465
return TS480SAT_empty;
466
else if (m == 2 || m == 6)
467
return TS480SAT_CWwidths;
468
else if (m == 5 || m == 7)
469
return TS480SAT_FSKwidths;
471
return TS480SAT_empty;
474
const char **RIG_TS480SAT::lotable(int m)
476
if (m == 0 || m == 1 || m == 3)
478
else if (m == 2 || m == 6)
480
else if (m == 5 || m == 7)
482
return TS480SAT_AM_lo;
485
const char **RIG_TS480SAT::hitable(int m)
487
if (m == 0 || m == 1 || m == 3)
489
else if (m == 2 || m == 6)
491
else if (m == 5 || m == 7)
493
return TS480SAT_AM_hi;
496
void RIG_TS480SAT::set_modeA(int val)
500
cmd += TS480SAT_mode_chr[val];
503
showresp(WARN, ASC, "set mode", cmd, replystr);
504
A.iBW = set_widths(val);
507
int RIG_TS480SAT::get_modeA()
511
showresp(WARN, ASC, "get mode A", cmd, replystr);
512
size_t p = replystr.rfind("MD");
513
if (p != string::npos && (p + 2 < replystr.length())) {
514
int md = replystr[p+2];
518
A.iBW = set_widths(A.imode);
523
void RIG_TS480SAT::set_modeB(int val)
527
cmd += TS480SAT_mode_chr[val];
530
showresp(WARN, ASC, "set mode B", cmd, replystr);
531
B.iBW = set_widths(val);
534
int RIG_TS480SAT::get_modeB()
538
showresp(WARN, ASC, "get mode B", cmd, replystr);
539
size_t p = replystr.rfind("MD");
540
if (p != string::npos && (p + 2 < replystr.length())) {
541
int md = replystr[p+2];
545
B.iBW = set_widths(B.imode);
550
int RIG_TS480SAT::get_modetype(int n)
552
return _mode_type[n];
555
void RIG_TS480SAT::set_bwA(int val)
557
if (A.imode == 0 || A.imode == 1 || A.imode == 3 || A.imode == 4) {
558
if (val < 256) return;
561
cmd.append(to_decimal(A.iBW & 0xFF, 2)).append(";");
563
showresp(WARN, ASC, lo_tooltip, cmd, replystr);
565
cmd.append(to_decimal(((A.iBW >> 8) & 0x7F), 2)).append(";");
567
showresp(WARN, ASC, hi_tooltip, cmd, replystr);
569
if (val > 256) return;
570
else if (A.imode == 2 || A.imode == 6) {
572
cmd = TS480SAT_CWbw[A.iBW];
574
showresp(WARN, ASC, "set CW bw", cmd, replystr);
575
}else if (A.imode == 5 || A.imode == 7) {
577
cmd = TS480SAT_FSKbw[A.iBW];
579
showresp(WARN, ASC, "set FSK bw", cmd, replystr);
583
int RIG_TS480SAT::get_bwA()
588
bool menu45 = menu_45;
591
if (menu45 != menu_45)
592
Fl::awake(updateBandwidthControl);
594
if (A.imode == 0 || A.imode == 1 || A.imode == 3 || A.imode == 4) {
595
int lo = A.iBW & 0xFF, hi = (A.iBW >> 8) & 0x7F;
598
showresp(WARN, ASC, "get SL", cmd, replystr);
599
p = replystr.rfind("SL");
600
if (p != string::npos)
601
lo = fm_decimal(&replystr[2], 2);
604
showresp(WARN, ASC, "get SH", cmd, replystr);
605
p = replystr.rfind("SH");
606
if (p != string::npos)
607
hi = fm_decimal(&replystr[2], 2);
608
A.iBW = ((hi << 8) | (lo & 0xFF)) | 0x8000;
609
} else if (A.imode == 2 || A.imode == 6) {
612
showresp(WARN, ASC, "get FW", cmd, replystr);
613
p = replystr.rfind("FW");
614
if (p != string::npos) {
615
for (i = 0; i < 11; i++)
616
if (replystr.find(TS480SAT_CWbw[i]) == p)
621
} else if (A.imode == 5 || A.imode == 7) {
624
showresp(WARN, ASC, "get FW", cmd, replystr);
625
p = replystr.rfind("FW");
626
if (p != string::npos) {
627
for (i = 0; i < 4; i++)
628
if (replystr.find(TS480SAT_FSKbw[i]) == p)
637
void RIG_TS480SAT::set_bwB(int val)
639
if (B.imode == 0 || B.imode == 1 || B.imode == 3 || B.imode == 4) {
640
if (val < 256) return;
643
cmd.append(to_decimal(B.iBW & 0xFF, 2)).append(";");
645
showresp(WARN, ASC, lo_tooltip, cmd, replystr);
647
cmd.append(to_decimal(((B.iBW >> 8) & 0x7F), 2)).append(";");
649
showresp(WARN, ASC, hi_tooltip, cmd, replystr);
651
if (val > 256) return;
652
else if (B.imode == 2 || B.imode == 6) { // CW
654
cmd = TS480SAT_CWbw[B.iBW];
656
showresp(WARN, ASC, "set CW bw", cmd, replystr);
657
}else if (B.imode == 5 || B.imode == 7) {
659
cmd = TS480SAT_FSKbw[B.iBW];
661
showresp(WARN, ASC, "set FSK bw", cmd, replystr);
665
int RIG_TS480SAT::get_bwB()
669
bool menu45 = menu_45;
672
if (menu45 != menu_45)
673
Fl::awake(updateBandwidthControl);
675
if (B.imode == 0 || B.imode == 1 || B.imode == 3 || B.imode == 4) {
676
int lo = B.iBW & 0xFF, hi = (B.iBW >> 8) & 0x7F;
679
showresp(WARN, ASC, "get SL", cmd, replystr);
680
p = replystr.rfind("SL");
681
if (p != string::npos)
682
lo = fm_decimal(&replystr[2], 2);
685
showresp(WARN, ASC, "get SH", cmd, replystr);
686
p = replystr.rfind("SH");
687
if (p != string::npos)
688
hi = fm_decimal(&replystr[2], 2);
689
B.iBW = ((hi << 8) | (lo & 0xFF)) | 0x8000;
690
} else if (B.imode == 2 || B.imode == 6) {
693
showresp(WARN, ASC, "get FW", cmd, replystr);
694
p = replystr.rfind("FW");
695
if (p != string::npos) {
696
for (i = 0; i < 11; i++)
697
if (replystr.find(TS480SAT_CWbw[i]) == p)
702
} else if (B.imode == 5 || B.imode == 7) {
704
showresp(WARN, ASC, "get FW", cmd, replystr);
705
p = replystr.rfind("FW");
706
if (p != string::npos) {
707
for (i = 0; i < 4; i++)
708
if (replystr.find(TS480SAT_FSKbw[i]) == p)
717
int RIG_TS480SAT::adjust_bandwidth(int val)
720
if (val == 0 || val == 1 || val == 3)
724
else if (val == 2 || val == 6)
726
else if (val == 5 || val == 7)
731
int RIG_TS480SAT::def_bandwidth(int val)
733
return adjust_bandwidth(val);
736
void RIG_TS480SAT::set_volume_control(int val)
740
snprintf(szval, sizeof(szval), "%04d", val * 255 / 100);
743
LOG_WARN("%s", cmd.c_str());
747
int RIG_TS480SAT::get_volume_control()
749
int val = progStatus.volume;
751
int ret = waitN(7, 100, "get vol", ASC);
752
if (ret < 7) return val;
753
size_t p = replystr.rfind("AG");
754
if (p == string::npos) return val;
756
val = atoi(&replystr[p + 3]);
757
val = val * 100 / 255;
761
void RIG_TS480SAT::set_power_control(double val)
765
if (modeA == 4 && val > 25) val = 25; // AM mode limitation
766
snprintf(szval, sizeof(szval), "%03d", (int)val);
769
LOG_WARN("%s", cmd.c_str());
773
int RIG_TS480SAT::get_power_control()
775
int val = progStatus.power_level;
777
int ret = waitN(6, 100, "get Power control", ASC);
778
if (ret < 6) return val;
779
size_t p = replystr.rfind("PC");
780
if (p == string::npos) return val;
782
val = atoi(&replystr[p + 2]);
787
void RIG_TS480SAT::set_attenuator(int val)
789
if (val) cmd = "RA01;";
791
LOG_WARN("%s", cmd.c_str());
795
int RIG_TS480SAT::get_attenuator()
798
int ret = waitN(7, 100, "get attenuator", ASC);
799
if (ret < 7) return progStatus.attenuator;
800
size_t p = replystr.rfind("RA");
801
if (p == string::npos) return progStatus.attenuator;
802
if (replystr[p+3] == '1') return 1;
806
void RIG_TS480SAT::set_preamp(int val)
808
if (val) cmd = "PA1;";
810
LOG_WARN("%s", cmd.c_str());
814
int RIG_TS480SAT::get_preamp()
817
int ret = waitN(5, 100, "get preamp", ASC);
818
if (ret < 5) return progStatus.preamp;
819
size_t p = replystr.rfind("PA");
820
if (p == string::npos) return progStatus.preamp;
821
if (replystr[p+2] == '1') return 1;
825
void RIG_TS480SAT::tune_rig()
828
LOG_WARN("%s", cmd.c_str());
832
void RIG_TS480SAT::set_if_shift(int val)
835
if (val < 0) cmd[2] = '-';
836
cmd.append(to_decimal(abs(val),4)).append(";");
838
showresp(WARN, ASC, "set IF shift", cmd, replystr);
841
bool RIG_TS480SAT::get_if_shift(int &val)
844
waitN(8, 100, "get IF shift", ASC);
845
size_t p = replystr.rfind("IS");
846
if (p != string::npos) {
847
val = fm_decimal(&replystr[p+3], 4);
848
if (replystr[p+2] == '-') val *= -1;
851
val = progStatus.shift_val;
852
return progStatus.shift;
855
void RIG_TS480SAT::get_if_min_max_step(int &min, int &max, int &step)
857
if_shift_min = min = -1100;
858
if_shift_max = max = 1100;
859
if_shift_step = step = 10;
863
void RIG_TS480SAT::set_mic_gain(int val)
866
cmd.append(to_decimal(val,3)).append(";");
868
showresp(WARN, ASC, "set mic gain", cmd, replystr);
871
int RIG_TS480SAT::get_mic_gain()
873
int val = progStatus.mic_gain;
875
int ret = waitN(6, 100, "get mic gain", ASC);
876
if (ret < 6) return val;
877
size_t p = replystr.rfind("MG");
878
if (p != string::npos)
879
val = fm_decimal(&replystr[p+2], 3);
883
void RIG_TS480SAT::get_mic_min_max_step(int &min, int &max, int &step)
885
min = 0; max = 100; step = 1;
888
void RIG_TS480SAT::set_rf_gain(int val)
891
cmd.append(to_decimal(val,3)).append(";");
893
showresp(WARN, ASC, "set rf gain", cmd, replystr);
896
int RIG_TS480SAT::get_rf_gain()
898
int val = progStatus.rfgain;
900
int ret = waitN(6, 100, "get rf gain", ASC);
901
if (ret < 6) return val;
902
size_t p = replystr.rfind("RG");
903
if (p != string::npos)
904
val = fm_decimal(&replystr[p+2], 3);
908
void RIG_TS480SAT::get_rf_min_max_step(int &min, int &max, int &step)
910
min = 0; max = 100; step = 1;