2
* Kenwood TS480HX driver
3
* originally based on Kenwood TS480HX driver
7
* Copyright 2009, Dave Freese, W1HKJ
15
static const char TS480HXname_[] = "TS-480HX";
17
static const char *TS480HXmodes_[] = {
18
"LSB", "USB", "CW", "FM", "AM", "FSK", "CW-R", "FSK-R", NULL};
19
static const char TS480HX_mode_chr[] = { '1', '2', '3', '4', '5', '6', '7', '9' };
20
static const char TS480HX_mode_type[] = { 'L', 'U', 'U', 'U', 'U', 'L', 'L', 'U' };
22
static const char *TS480HX_empty[] = { "N/A", NULL };
24
// SL command is lo cutoff when menu 045 OFF
25
static const char *TS480HX_lo[] = {
26
"0", "50", "100", "200", "300",
27
"400", "500", "600", "700", "800",
28
"900", "1000", NULL };
29
static const char *TS480HX_lo_tooltip = "lo cutoff";
30
static const char *TS480HX_btn_lo_label = "L";
32
// SH command is hi cutoff when menu 045 OFF
33
static const char *TS480HX_hi[] = {
34
"1000", "1200", "1400", "1600", "1800",
35
"2000", "2200", "2400", "2600", "2800",
36
"3000", "3400", "4000", "5000", NULL };
37
static const char *TS480HX_hi_tooltip = "hi cutoff";
38
static const char *TS480HX_btn_hi_label = "H";
40
// SL command is width when menu 045 ON
41
static const char *TS480HX_dataW[] = {
42
"50", "100", "250", "500", "1000", "1500", "2400", NULL };
43
static const char *TS480HX_dataW_tooltip = "filter width";
44
static const char *TS480HX_dataW_label = "W";
46
// SH command is center frequency when menu 045 ON
47
static const char *TS480HX_dataC[] = {
48
"1000", "1500", "2210", NULL };
49
static const char *TS480HX_dataC_tooltip = "center frequency";
50
static const char *TS480HX_dataC_label = "C";
52
static const char *TS480HX_AM_lo[] = {
53
"10", "100", "200", "500",
56
static const char *TS480HX_AM_hi[] = {
57
"2500", "3000", "4000", "5000",
60
static const char *TS480HX_CWwidths[] = {
61
"50", "80", "100", "150", "200",
62
"300", "400", "500", "600", "1000",
65
static const char *TS480HX_CWbw[] = {
66
"FW0050;", "FW0080;", "FW0100;", "FW0150;", "FW0200;",
67
"FW0300;", "FW0400;", "FW0500;", "FW0600;", "FW1000;",
70
static const char *TS480HX_FSKwidths[] = {
71
"250", "500", "1000", "1500", NULL};
72
static const char *TS480HX_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_TS480HX::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_TS480HX::RIG_TS480HX() {
108
name_ = TS480HXname_;
109
modes_ = TS480HXmodes_;
110
_mode_type = TS480HX_mode_type;
111
bandwidths_ = TS480HX_empty;
114
lo_tooltip = TS480HX_lo_tooltip;
115
lo_label = TS480HX_btn_lo_label;
118
hi_tooltip = TS480HX_lo_tooltip;
119
hi_label = TS480HX_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
has_tune_control = false;
139
has_noise_control = false;
140
has_notch_control = false;
145
has_data_port = true;
146
has_micgain_control = true;
147
has_ifshift_control = true;
148
has_rf_control = true;
149
has_power_out = true;
150
has_dsp_controls = true;
152
has_swr_control = true;
153
has_alc_control = true;
154
has_attenuator_control = true;
155
has_preamp_control = true;
156
has_mode_control = true;
157
has_bandwidth_control = true;
158
has_volume_control = true;
159
has_power_control = true;
160
has_tune_control = true;
161
has_ptt_control = true;
168
const char * RIG_TS480HX::get_bwname_(int n, int md)
170
static char bwname[20];
172
int hi = (n >> 8) & 0x7F;
174
snprintf(bwname, sizeof(bwname), "%s/%s",
175
(md == 0 || md == 1 || md == 3) ? dsp_lo[lo] : TS480HX_AM_lo[lo],
176
(md == 0 || md == 1 || md == 3) ? dsp_hi[hi] : TS480HX_AM_hi[hi] );
178
snprintf(bwname, sizeof(bwname), "%s",
179
(md == 2 || md == 6) ? TS480HX_CWwidths[n] : TS480HX_FSKwidths[n]);
184
void RIG_TS480HX::check_menu_45()
186
// read current switch 45 setting
188
cmd = "EX0450000;"; sendCommand(cmd);
189
int ret = waitN(11, 100, "Check menu item 45", ASC);
191
size_t p = replystr.rfind("EX045");
192
if (p != string::npos)
193
menu_45 = (replystr[p+9] == '1');
197
dsp_lo = TS480HX_dataW;
198
lo_tooltip = TS480HX_dataW_tooltip;
199
lo_label = TS480HX_dataW_label;
200
dsp_hi = TS480HX_dataC;
201
hi_tooltip = TS480HX_dataC_tooltip;
202
hi_label = TS480HX_dataC_label;
203
B.iBW = A.iBW = 0x8106;
206
lo_tooltip = TS480HX_lo_tooltip;
207
lo_label = TS480HX_btn_lo_label;
209
hi_tooltip = TS480HX_hi_tooltip;
210
hi_label = TS480HX_btn_hi_label;
211
B.iBW = A.iBW = 0x8A03;
215
void RIG_TS480HX::shutdown()
219
void RIG_TS480HX::selectA()
223
showresp(WARN, ASC, "Rx on A, Tx on A", cmd, replystr);
226
void RIG_TS480HX::selectB()
230
showresp(WARN, ASC, "Rx on B, Tx on B", cmd, replystr);
233
void RIG_TS480HX::set_split(bool val)
240
showresp(WARN, ASC, "Rx on B, Tx on A", cmd, replystr);
244
showresp(WARN, ASC, "Rx on B, Tx on B", cmd, replystr);
250
showresp(WARN, ASC, "Rx on A, Tx on B", cmd, replystr);
254
showresp(WARN, ASC, "Rx on A, Tx on A", cmd, replystr);
257
Fl::awake(highlight_vfo, (void *)0);
260
bool RIG_TS480HX::can_split()
265
int RIG_TS480HX::get_split()
273
waitN(4, 100, "get split tx vfo", ASC);
274
p = replystr.rfind(rsp);
275
if (p == string::npos) return split;
281
waitN(4, 100, "get split rx vfo", ASC);
283
p = replystr.rfind(rsp);
284
if (p == string::npos) return split;
287
split = (tx == '1' ? 2 : 0) + (rx == '1' ? 1 : 0);
292
long RIG_TS480HX::get_vfoA ()
295
int ret = waitN(14, 100, "get vfo A", ASC);
296
if (ret < 14) return A.freq;
297
size_t p = replystr.rfind("FA");
298
if (p != string::npos && (p + 12 < replystr.length())) {
300
for (size_t n = 2; n < 13; n++)
301
f = f*10 + replystr[p+n] - '0';
307
void RIG_TS480HX::set_vfoA (long freq)
310
cmd = "FA00000000000;";
311
for (int i = 12; i > 1; i--) {
316
showresp(WARN, ASC, "set vfo A", cmd, replystr);
319
long RIG_TS480HX::get_vfoB ()
322
int ret = waitN(14, 100, "get vfo B", ASC);
323
if (ret < 14) return B.freq;
324
size_t p = replystr.rfind("FB");
325
if (p != string::npos && (p + 12 < replystr.length())) {
327
for (size_t n = 2; n < 13; n++)
328
f = f*10 + replystr[p+n] - '0';
334
void RIG_TS480HX::set_vfoB (long freq)
337
cmd = "FB00000000000;";
338
for (int i = 12; i > 1; i--) {
343
showresp(WARN, ASC, "set vfo B", cmd, replystr);
346
// SM cmd 0 ... 100 (rig values 0 ... 15)
347
int RIG_TS480HX::get_smeter()
351
int ret = waitN(8, 100, "get Smeter", ASC);
352
if (ret < 8) return 0;
354
size_t p = replystr.rfind("SM");
355
if (p != string::npos)
356
mtr = 5 * atoi(&replystr[p + 3]);
360
int RIG_TS480HX::get_power_out()
364
int ret = waitN(8, 100, "get power", ASC);
365
if (ret < 8) return mtr;
366
size_t p = replystr.rfind("SM");
367
if (p != string::npos) {
368
mtr = 5 * atoi(&replystr[p + 3]);
369
if (mtr > 100) mtr = 100;
374
// RM cmd 0 ... 100 (rig values 0 ... 8)
375
// User report of RM; command using Send Cmd tab
376
// RM10000;RM20000;RM30000;
381
int RIG_TS480HX::get_swr()
385
int ret = waitN(8, 100, "get SWR/ALC", ASC);
386
if (ret < 8) return (int)mtr;
387
size_t p = replystr.rfind("RM1");
388
if (p != string::npos)
389
mtr = 66 * atoi(&replystr[p + 3]) / 10;
390
p = replystr.rfind("RM3");
391
if (p != string::npos)
392
alc = 66 * atoi(&replystr[p+3]) / 10;
395
swralc_polled = true;
399
int RIG_TS480HX::get_alc(void)
401
if (!swralc_polled) get_swr();
402
swralc_polled = false;
406
// Tranceiver PTT on/off
407
void RIG_TS480HX::set_PTT_control(int val)
410
if (progStatus.data_port) cmd = "TX1;"; // DTS transmission using ANI input
411
else cmd = "TX0;"; // mic input
414
showresp(WARN, ASC, "set PTT", cmd, replystr);
417
int RIG_TS480HX::set_widths(int val)
420
if (val == 0 || val == 1 || val == 3) {
421
bandwidths_ = TS480HX_empty;
423
bw = 0x8106; // 1500 Hz 2400 wide
424
dsp_lo = TS480HX_dataW;
425
lo_tooltip = TS480HX_dataW_tooltip;
426
lo_label = TS480HX_dataW_label;
427
dsp_hi = TS480HX_dataC;
428
hi_tooltip = TS480HX_dataC_tooltip;
429
hi_label = TS480HX_dataC_label;
431
bw = 0x8A03; // 200 ... 3000 Hz
433
lo_tooltip = TS480HX_lo_tooltip;
434
lo_label = TS480HX_btn_lo_label;
436
hi_tooltip = TS480HX_hi_tooltip;
437
hi_label = TS480HX_btn_hi_label;
439
} else if (val == 2 || val == 6) {
440
bandwidths_ = TS480HX_CWwidths;
441
dsp_lo = TS480HX_empty;
442
dsp_hi = TS480HX_empty;
444
} else if (val == 5 || val == 7) {
445
bandwidths_ = TS480HX_FSKwidths;
446
dsp_lo = TS480HX_empty;
447
dsp_hi = TS480HX_empty;
449
} else { // val == 4 ==> AM
450
bandwidths_ = TS480HX_empty;
451
dsp_lo = TS480HX_AM_lo;
452
dsp_hi = TS480HX_AM_hi;
458
const char **RIG_TS480HX::bwtable(int m)
460
if (m == 0 || m == 1 || m == 3)
461
return TS480HX_empty;
462
else if (m == 2 || m == 6)
463
return TS480HX_CWwidths;
464
else if (m == 5 || m == 7)
465
return TS480HX_FSKwidths;
467
return TS480HX_empty;
470
const char **RIG_TS480HX::lotable(int m)
472
if (m == 0 || m == 1 || m == 3)
474
else if (m == 2 || m == 6)
476
else if (m == 5 || m == 7)
478
return TS480HX_AM_lo;
481
const char **RIG_TS480HX::hitable(int m)
483
if (m == 0 || m == 1 || m == 3)
485
else if (m == 2 || m == 6)
487
else if (m == 5 || m == 7)
489
return TS480HX_AM_hi;
492
void RIG_TS480HX::set_modeA(int val)
496
cmd += TS480HX_mode_chr[val];
499
showresp(WARN, ASC, "set mode", cmd, replystr);
500
A.iBW = set_widths(val);
503
int RIG_TS480HX::get_modeA()
507
showresp(WARN, ASC, "get mode A", cmd, replystr);
508
size_t p = replystr.rfind("MD");
509
if (p != string::npos && (p + 2 < replystr.length())) {
510
int md = replystr[p+2];
514
A.iBW = set_widths(A.imode);
519
void RIG_TS480HX::set_modeB(int val)
523
cmd += TS480HX_mode_chr[val];
526
showresp(WARN, ASC, "set mode B", cmd, replystr);
527
B.iBW = set_widths(val);
530
int RIG_TS480HX::get_modeB()
534
showresp(WARN, ASC, "get mode B", cmd, replystr);
535
size_t p = replystr.rfind("MD");
536
if (p != string::npos && (p + 2 < replystr.length())) {
537
int md = replystr[p+2];
541
B.iBW = set_widths(B.imode);
546
int RIG_TS480HX::get_modetype(int n)
548
return _mode_type[n];
551
void RIG_TS480HX::set_bwA(int val)
553
if (A.imode == 0 || A.imode == 1 || A.imode == 3 || A.imode == 4) {
554
if (val < 256) return;
557
cmd.append(to_decimal(A.iBW & 0xFF, 2)).append(";");
559
showresp(WARN, ASC, lo_tooltip, cmd, replystr);
561
cmd.append(to_decimal(((A.iBW >> 8) & 0x7F), 2)).append(";");
563
showresp(WARN, ASC, hi_tooltip, cmd, replystr);
565
if (val > 256) return;
566
else if (A.imode == 2 || A.imode == 6) {
568
cmd = TS480HX_CWbw[A.iBW];
570
showresp(WARN, ASC, "set CW bw", cmd, replystr);
571
}else if (A.imode == 5 || A.imode == 7) {
573
cmd = TS480HX_FSKbw[A.iBW];
575
showresp(WARN, ASC, "set FSK bw", cmd, replystr);
579
int RIG_TS480HX::get_bwA()
584
bool menu45 = menu_45;
587
if (menu45 != menu_45)
588
Fl::awake(updateBandwidthControl);
590
if (A.imode == 0 || A.imode == 1 || A.imode == 3 || A.imode == 4) {
591
int lo = A.iBW & 0xFF, hi = (A.iBW >> 8) & 0x7F;
594
showresp(WARN, ASC, "get SL", cmd, replystr);
595
p = replystr.rfind("SL");
596
if (p != string::npos)
597
lo = fm_decimal(&replystr[2], 2);
600
showresp(WARN, ASC, "get SH", cmd, replystr);
601
p = replystr.rfind("SH");
602
if (p != string::npos)
603
hi = fm_decimal(&replystr[2], 2);
604
A.iBW = ((hi << 8) | (lo & 0xFF)) | 0x8000;
605
} else if (A.imode == 2 || A.imode == 6) {
608
showresp(WARN, ASC, "get FW", cmd, replystr);
609
p = replystr.rfind("FW");
610
if (p != string::npos) {
611
for (i = 0; i < 11; i++)
612
if (replystr.find(TS480HX_CWbw[i]) == p)
617
} else if (A.imode == 5 || A.imode == 7) {
620
showresp(WARN, ASC, "get FW", cmd, replystr);
621
p = replystr.rfind("FW");
622
if (p != string::npos) {
623
for (i = 0; i < 4; i++)
624
if (replystr.find(TS480HX_FSKbw[i]) == p)
633
void RIG_TS480HX::set_bwB(int val)
635
if (B.imode == 0 || B.imode == 1 || B.imode == 3 || B.imode == 4) {
636
if (val < 256) return;
639
cmd.append(to_decimal(B.iBW & 0xFF, 2)).append(";");
641
showresp(WARN, ASC, lo_tooltip, cmd, replystr);
643
cmd.append(to_decimal(((B.iBW >> 8) & 0x7F), 2)).append(";");
645
showresp(WARN, ASC, hi_tooltip, cmd, replystr);
647
if (val > 256) return;
648
else if (B.imode == 2 || B.imode == 6) { // CW
650
cmd = TS480HX_CWbw[B.iBW];
652
showresp(WARN, ASC, "set CW bw", cmd, replystr);
653
}else if (B.imode == 5 || B.imode == 7) {
655
cmd = TS480HX_FSKbw[B.iBW];
657
showresp(WARN, ASC, "set FSK bw", cmd, replystr);
661
int RIG_TS480HX::get_bwB()
665
bool menu45 = menu_45;
668
if (menu45 != menu_45)
669
Fl::awake(updateBandwidthControl);
671
if (B.imode == 0 || B.imode == 1 || B.imode == 3 || B.imode == 4) {
672
int lo = B.iBW & 0xFF, hi = (B.iBW >> 8) & 0x7F;
675
showresp(WARN, ASC, "get SL", cmd, replystr);
676
p = replystr.rfind("SL");
677
if (p != string::npos)
678
lo = fm_decimal(&replystr[2], 2);
681
showresp(WARN, ASC, "get SH", cmd, replystr);
682
p = replystr.rfind("SH");
683
if (p != string::npos)
684
hi = fm_decimal(&replystr[2], 2);
685
B.iBW = ((hi << 8) | (lo & 0xFF)) | 0x8000;
686
} else if (B.imode == 2 || B.imode == 6) {
689
showresp(WARN, ASC, "get FW", cmd, replystr);
690
p = replystr.rfind("FW");
691
if (p != string::npos) {
692
for (i = 0; i < 11; i++)
693
if (replystr.find(TS480HX_CWbw[i]) == p)
698
} else if (B.imode == 5 || B.imode == 7) {
700
showresp(WARN, ASC, "get FW", cmd, replystr);
701
p = replystr.rfind("FW");
702
if (p != string::npos) {
703
for (i = 0; i < 4; i++)
704
if (replystr.find(TS480HX_FSKbw[i]) == p)
713
int RIG_TS480HX::adjust_bandwidth(int val)
716
if (val == 0 || val == 1 || val == 3)
720
else if (val == 2 || val == 6)
722
else if (val == 5 || val == 7)
727
int RIG_TS480HX::def_bandwidth(int val)
729
return adjust_bandwidth(val);
732
void RIG_TS480HX::set_volume_control(int val)
736
snprintf(szval, sizeof(szval), "%04d", val * 255 / 100);
740
showresp(WARN, ASC, "set vol", cmd, replystr);
743
int RIG_TS480HX::get_volume_control()
745
int val = progStatus.volume;
747
int ret = waitN(7, 100, "get vol", ASC);
748
if (ret < 7) return val;
749
size_t p = replystr.rfind("AG");
750
if (p == string::npos) return val;
752
val = atoi(&replystr[p + 3]);
753
val = val * 100 / 255;
757
void RIG_TS480HX::set_power_control(double val)
761
if (modeA == 4 && val > 50) val = 50; // AM mode limitation
762
snprintf(szval, sizeof(szval), "%03d", (int)val);
766
showresp(WARN, ASC, "set power", cmd, replystr);
769
int RIG_TS480HX::get_power_control()
771
int val = progStatus.power_level;
773
int ret = sendCommand(cmd);
774
showresp(WARN, ASC, "get power", cmd, replystr);
775
if (ret < 6) return val;
776
size_t p = replystr.rfind("PC");
777
if (p == string::npos) return val;
779
val = atoi(&replystr[p + 2]);
784
void RIG_TS480HX::set_attenuator(int val)
786
if (val) cmd = "RA01;";
788
LOG_WARN("%s", cmd.c_str());
792
int RIG_TS480HX::get_attenuator()
795
int ret = waitN(7, 100, "get attenuator", ASC);
796
if (ret < 7) return progStatus.attenuator;
797
size_t p = replystr.rfind("RA");
798
if (p == string::npos) return progStatus.attenuator;
799
if (replystr[p+3] == '1') return 1;
803
void RIG_TS480HX::set_preamp(int val)
805
if (val) cmd = "PA1;";
807
LOG_WARN("%s", cmd.c_str());
811
int RIG_TS480HX::get_preamp()
814
int ret = waitN(5, 100, "get preamp", ASC);
815
if (ret < 5) return progStatus.preamp;
816
size_t p = replystr.rfind("PA");
817
if (p == string::npos) return progStatus.preamp;
818
if (replystr[p+2] == '1') return 1;
822
void RIG_TS480HX::tune_rig()
826
showresp(WARN, ASC, "tune", cmd, replystr);
829
void RIG_TS480HX::set_if_shift(int val)
832
if (val < 0) cmd[2] = '-';
833
cmd.append(to_decimal(abs(val),4)).append(";");
835
showresp(WARN, ASC, "set IF shift", cmd, replystr);
838
bool RIG_TS480HX::get_if_shift(int &val)
841
waitN(8, 100, "get IF shift", ASC);
842
size_t p = replystr.rfind("IS");
843
if (p != string::npos) {
844
val = fm_decimal(&replystr[p+3], 4);
845
if (replystr[p+2] == '-') val *= -1;
848
val = progStatus.shift_val;
849
return progStatus.shift;
852
void RIG_TS480HX::get_if_min_max_step(int &min, int &max, int &step)
854
if_shift_min = min = -1100;
855
if_shift_max = max = 1100;
856
if_shift_step = step = 10;
860
void RIG_TS480HX::set_mic_gain(int val)
863
cmd.append(to_decimal(val,3)).append(";");
865
showresp(WARN, ASC, "set mic gain", cmd, replystr);
868
int RIG_TS480HX::get_mic_gain()
870
int val = progStatus.mic_gain;
872
int ret = waitN(6, 100, "get mic gain", ASC);
873
if (ret < 6) return val;
874
size_t p = replystr.rfind("MG");
875
if (p != string::npos)
876
val = fm_decimal(&replystr[p+2], 3);
880
void RIG_TS480HX::get_mic_min_max_step(int &min, int &max, int &step)
882
min = 0; max = 100; step = 1;
885
void RIG_TS480HX::set_rf_gain(int val)
888
cmd.append(to_decimal(val,3)).append(";");
890
showresp(WARN, ASC, "set rf gain", cmd, replystr);
893
int RIG_TS480HX::get_rf_gain()
895
int val = progStatus.rfgain;
897
int ret = waitN(6, 100, "get rf gain", ASC);
898
if (ret < 6) return val;
899
size_t p = replystr.rfind("RG");
900
if (p != string::npos)
901
val = fm_decimal(&replystr[p+2], 3);
905
void RIG_TS480HX::get_rf_min_max_step(int &min, int &max, int &step)
907
min = 0; max = 100; step = 1;