2
* Kenwood TS870S driver
3
* Based on the TS870S driver by Dave Freese.
6
* Copyright 2009, Dave Freese, W1HKJ
7
* Changes for the TS-870S March 2012, Dave Baxter, G0WBX
12
* Autonotch control:- (SSB Only on the 870S) (TS-2000)
13
* Noise Reduction control:- (IC-7700)
14
* Extra controls for speach compressor etc:- (IC-9100 (and others))
15
* Misc controls auto rig on/off with flrig startup/quit:- (FT-450/950) (PS0; PS1;)
16
* Check Autotune action, and any 'busy' status.
23
static const char TS870Sname_[] = "TS-870S";
25
// mode array Index Values :- 0 1 2 3 4 5 6 7
26
static const char *TS870Smodes_[] = { "LSB", "USB", "CW", "FM", "AM", "FSK", "CW-R", "FSK-R", NULL};
27
static const char TS870S_mode_chr[] = { '1', '2', '3', '4', '5', '6', '7', '9' };
28
static const char TS870S_mode_type[] = { 'L', 'U', 'U', 'U', 'U', 'L', 'L', 'U' };
30
//----------------------------------------------------------------------
31
static const char *TS870S_empty[] = { "N/A", NULL };
33
//----------------------------------------------------------------------
34
static const char *TS870S_SSB_lo[] = { // MD1; and MD2;
35
"0", "50", "100", "200", "300", // Available settings (Hz)
36
"400", "500", "600", "800", "1000", NULL };
38
static const char *TS870S_CAT_ssb_lo[] = { // Corresponding commands.
39
"FW0000;", "FW0005;", "FW0010;", "FW0020;", "FW0030;",
40
"FW0040;", "FW0050;", "FW0060;", "FW0080;", "FW0100;", NULL };
42
static const char *TS870S_SSB_lo_tooltip = "lo cutoff";
43
static const char *TS870S_SSB_btn_lo_label = "L";
46
static const char *TS870S_SSB_hi[] = { // MD1; and MD2;
47
"1400", "1600", "1800", "2000", "2200", "2400", // Available settings (Hz)
48
"2600", "2800", "3000", "3400", "4600", "6000", NULL };
50
static const char *TS870S_CAT_ssb_hi[] = { // Corresponding commands.
51
"IS 1400;", "IS 1600;", "IS 1800;", "IS 2000;", "IS 2200;", "IS 2400;",
52
"IS 2600;", "IS 2800;", "IS 3000;", "IS 3400;", "IS 4600;", "IS 6000;", NULL };
54
static const char *TS870S_SSB_hi_tooltip = "hi cutoff";
55
static const char *TS870S_SSB_btn_hi_label = "H";
57
//----------------------------------------------------------------------
58
static const char *TS870S_AM_lo[] = { // Available values...
59
"0", "100", "200", "500", NULL };
61
static const char *TS870S_CAT_am_lo[] = { // ... Corresponding commands.
62
"FW0000;", "FW0010;", "FW0020;", "FW0050;", NULL};
64
static const char *TS870S_AM_lo_tooltip = "lo cutoff";
65
static const char *TS870S_AM_btn_lo_label = "L";
67
static const char *TS870S_AM_hi[] = {
68
"2500", "3000", "4000", "5000", "6000", "7000", NULL };
70
static const char *TS870S_CAT_am_hi[] = {
71
"IS 2500;", "IS 3000;", "IS 4000;", "IS 5000;", "IS 6000;", "IS 7000;", NULL};
73
static const char *TS870S_AM_hi_tooltip = "hi cutoff";
74
static const char *TS870S_AM_btn_hi_label = "H";
76
//----------------------------------------------------------------------
77
static const char *TS870S_CWwidths[] = { // Available CW bandwidths
78
"50", "100", "200", "400", "600", "1000", NULL};
80
static const char *TS870S_CWbw[] = { // Corresponding commands.
81
"FW0005;", "FW0010;", "FW0020;", "FW0040;", "FW0060;", "FW0100;", NULL};
83
//----------------------------------------------------------------------
84
static const char *TS870S_FSKwidths[] = { // Available FSK bandwidths
85
"250", "500", "1000", "1500", NULL};
87
static const char *TS870S_FSKbw[] = { // Corresponding commands.
88
"FW0025;", "FW0050;", "FW0100;", "FW0150;", NULL };
90
//----------------------------------------------------------------------
91
static const char *TS870S_FMwidths[] = { // Available FM bandwidths
92
"5000", "6000", "8000", "10000", "12000", "14000", NULL};
94
static const char *TS870S_FMbw[] = { // Corresponding commands.
95
"FW0500;", "FW0600;", "FW0800;", "FW1000;", "FW1200;", "FW1400;", NULL };
97
//----------------------------------------------------------------------
99
static GUI rig_widgets[]= {
100
{ (Fl_Widget *)btnVol, 2, 125, 50 },
101
{ (Fl_Widget *)sldrVOLUME, 54, 125, 156 },
102
{ (Fl_Widget *)btnIFsh, 214, 105, 50 },
103
{ (Fl_Widget *)sldrIFSHIFT, 266, 105, 156 },
104
{ (Fl_Widget *)sldrMICGAIN, 266, 125, 156 },
105
{ (Fl_Widget *)sldrPOWER, 54, 145, 368 },
106
{ (Fl_Widget *)NULL, 0, 0, 0 }
109
//----------------------------------------------------------------------
110
void RIG_TS870S::initialize()
112
rig_widgets[0].W = btnVol;
113
rig_widgets[1].W = sldrVOLUME;
114
rig_widgets[2].W = btnIFsh;
115
rig_widgets[3].W = sldrIFSHIFT;
116
rig_widgets[4].W = sldrMICGAIN;
117
rig_widgets[5].W = sldrPOWER;
120
// cmd = "AC 00;"; sendCommand(cmd); // ATU Off.
121
cmd = "EX0270000;"; sendCommand(cmd); // TX Enable. wbx2
128
// add code here for shutting down the transceiver ...
129
void RIG_TS870S::shutdown()
133
//----------------------------------------------------------------------
134
RIG_TS870S::RIG_TS870S() {
137
modes_ = TS870Smodes_;
138
bandwidths_ = TS870S_empty;
140
dsp_lo = TS870S_SSB_lo;
141
lo_tooltip = TS870S_SSB_lo_tooltip;
142
lo_label = TS870S_SSB_btn_lo_label;
144
dsp_hi = TS870S_SSB_hi;
145
hi_tooltip = TS870S_SSB_hi_tooltip;
146
hi_label = TS870S_SSB_btn_hi_label;
148
widgets = rig_widgets;
150
comm_baudrate = BR57600;
156
comm_rtsplus = false;
157
comm_dtrplus = false;
158
comm_catptt = false; // default to safe
159
comm_rtsptt = false; // ditto (used for hardware handshake)
160
comm_dtrptt = false; // ditto
163
B.imode = A.imode = 1; // USB
164
B.iBW = A.iBW = 0x8704; // hi=2800Hz .. lo=300Hz
165
B.freq = A.freq = 14070000;
166
can_change_alt_vfo = true;
170
has_micgain_control =
172
has_ifshift_control =
173
has_swr_control = false;
181
has_micgain_control =
182
has_volume_control = // see 'read_volume()' in support.cxx
183
has_power_control = true;
185
has_tune_control = false; // disabled for now
187
has_attenuator_control = true;
189
has_preamp_control = false;
192
has_bandwidth_control =
194
has_ifshift_control = // See 'update_ifshift' in support.cxx
196
has_ptt_control = true;
203
//----------------------------------------------------------------------
204
const char * RIG_TS870S::get_bwname_(int n, int md)
205
{ // md is an index value, NOT a "mode" designator itself.
206
// n also is an index value, used to reference the name in the array.
208
// This uses "ternary" methods, in the form of...
209
// (boolean test) ? (do if true) : (do if false);
210
// http://www.teach-me-c.com/blog/c-ternary-operator
212
static char bwname[20];
214
if (n > 256) { // hi/lo cutt off bw setting mode.
215
int hi = (n >> 8) & 0x7F; // hi byte (not MSB)
216
int lo = n & 0xFF; // lo byte
217
snprintf(bwname, sizeof(bwname), "%s/%s",
218
(md == 0 || md == 1) ? TS870S_SSB_lo[lo] : // SSB lo
219
(md == 4) ? TS870S_AM_lo[lo] : "N/A", // AM lo
220
(md == 0 || md == 1) ? TS870S_SSB_hi[hi] : // SSB hi
221
(md == 4) ? TS870S_AM_hi[hi] : "N/A" ); // AM hi
223
} else { // plain vanilla single bandwidth mode.
224
snprintf(bwname, sizeof(bwname), "%s",
225
(md == 2 || md == 6) ? TS870S_CWwidths[n] : // CW or CW-R
226
(md == 5 || md == 7) ? TS870S_FSKwidths[n]: // FSK or FSK-R
227
(md == 3 ) ? TS870S_FMwidths[n] : "N/A" ); // FM
232
//----------------------------------------------------------------------
233
void RIG_TS870S::selectA()
237
showresp(WARN, ASC, "Rx/Tx A", cmd, replystr);
241
//----------------------------------------------------------------------
242
void RIG_TS870S::selectB()
246
showresp(WARN, ASC, "Rx/Tx B", cmd, replystr);
250
//----------------------------------------------------------------------
251
// revision is similar to TS950S code
252
//----------------------------------------------------------------------
253
void RIG_TS870S::set_split(bool val)
255
// find out which VFO (or if Memory) is in use for RX.
257
cmd = "FR;"; sendCommand(cmd);
258
showresp(WARN, ASC, "RX-VFO?", cmd, replystr);
259
int ret = waitN(4, 100, "get VFO for split", ASC);
260
// if incomplete data, change nothing.
263
size_t p = replystr.rfind("FR");
264
// if bad data, change nothing.
265
if (p == string::npos) return;
267
// '0' = VFO-A, '1' = VFO-B, '2' = Memory.
268
switch (replystr[p+2]) {
269
case '0' : useB = false; break;
270
case '1' : useB = true; break;
272
default : return; // do nothing the xcvr is in memory mode
280
showresp(WARN, ASC, "Rx on B, Tx on A", cmd, replystr);
284
showresp(WARN, ASC, "Rx on B, Tx on B", cmd, replystr);
290
showresp(WARN, ASC, "Rx on A, Tx on B", cmd, replystr);
294
showresp(WARN, ASC, "Rx on A, Tx on A", cmd, replystr);
297
Fl::awake(highlight_vfo, (void *)0);
300
//----------------------------------------------------------------------
301
// This works for the 950S ... you can can revert to use your
302
// IF byte 32 test if this does not work on the 870S
303
//----------------------------------------------------------------------
304
int RIG_TS870S::get_split()
312
waitN(4, 100, "get split tx vfo", ASC);
313
p = replystr.rfind(rsp);
314
if (p == string::npos) return split;
320
waitN(4, 100, "get split rx vfo", ASC);
322
p = replystr.rfind(rsp);
323
if (p == string::npos) return split;
326
split = (tx == '1' ? 2 : 0) + (rx == '1' ? 1 : 0);
331
//----------------------------------------------------------------------
332
long RIG_TS870S::get_vfoA ()
335
int ret = waitN(14, 100, "get vfoA", ASC);
337
if (ret < 14) return A.freq;
338
size_t p = replystr.rfind("FA");
339
if (p == string::npos) return A.freq;
343
for (size_t n = 12; n > 1; n--) {
344
f += (replystr[p + n] - '0') * mul;
351
//----------------------------------------------------------------------
352
void RIG_TS870S::set_vfoA (long freq)
355
cmd = "FA00000000000;";
356
for (int i = 12; i > 1; i--) {
361
showresp(WARN, ASC, "set vfo A", cmd, replystr);
364
//----------------------------------------------------------------------
365
long RIG_TS870S::get_vfoB ()
368
int ret = waitN(14, 100, "get vfoB", ASC);
370
if (ret < 14) return B.freq;
371
size_t p = replystr.rfind("FB");
372
if (p == string::npos) return B.freq;
376
for (size_t n = 12; n > 1; n--) {
377
f += (replystr[p + n] - '0') * mul;
385
//----------------------------------------------------------------------
386
void RIG_TS870S::set_vfoB (long freq)
389
cmd = "FB00000000000;";
390
for (int i = 12; i > 1; i--) {
395
showresp(WARN, ASC, "set vfo B", cmd, replystr);
398
//----------------------------------------------------------------------
399
/* int RIG_TS870S::get_smeter() {
402
int ret = waitN(8, 100, "get smeter", ASC);
404
if (ret < 7) return 0;
405
size_t p = replystr.find("SM");
406
if (p == string::npos) return 0;
409
mtr = atoi(&replystr[p + 2]);
412
if (mtr > 100) mtr = 100;
416
//----------------------------------------------------------------------
417
int RIG_TS870S::get_smeter() { // scales correctly now 2012-02-24
419
int ret = sendCommand(cmd);
420
showresp(WARN, ASC, "S meter", cmd, replystr);
421
if (ret < 7) return 0;
422
size_t p = replystr.rfind("SM");
423
if (p == string::npos) return -1;
426
int mtr = atoi(&replystr[p + 2]);
427
mtr = (mtr * 100) / 30; //wbx
431
//----------------------------------------------------------------------
432
int RIG_TS870S::get_power_out()
433
{ // Shares same command as the 'S' meter reading.
436
int ret = sendCommand(cmd);
437
showresp(WARN, ASC, "Output Power", cmd, replystr);
438
if (ret < 7) return mtr;
439
size_t p = replystr.rfind("SM");
440
if (p == string::npos) return mtr;
443
mtr = atoi(&replystr[p + 2]);
444
mtr = (mtr * 100) / 30; //wbx
445
if (mtr > 100) mtr = 100; // but with a power limit!
448
// The power meter scale is not the same as Flrig's default.
449
// a change is needed, one day. wbx2
452
//----------------------------------------------------------------------
453
// Transceiver power level
454
void RIG_TS870S::set_power_control(double val)
458
for (int i = 4; i > 1; i--) {
462
sendCommand(cmd, 0); // 010 .. 100
465
//----------------------------------------------------------------------
466
int RIG_TS870S::get_power_control()
469
int ret = waitN(6, 100, "get pwr ctrl", ASC);
471
if (ret < 6) return 0;
472
size_t p = replystr.rfind("PC");
473
if (p == string::npos) return 0;
477
mtr = atoi(&replystr[p + 2]);
482
//----------------------------------------------------------------------
483
// Volume control return (rig sends back 0 .. 255)
484
int RIG_TS870S::get_volume_control()
486
cmd = "AG;"; // reply data is 'AGnnn;' nnn = 000 .. 255 wbx
488
int ret = sendCommand(cmd);
489
showresp(WARN, ASC, "get vol ctrl", cmd, replystr);
491
// int ret = waitN(7, 100, "get vol ctrl", ASC);
493
if (ret < 6) return 0;
494
size_t p = replystr.rfind("AG");
495
if (p == string::npos) return 0;
497
replystr[p + 5] = 0; // change the ';' into a 'null'
498
int val = atoi(&replystr[p + 2]);
499
return (int)(val / 2.55); // we only want 0 .. 100
502
//----------------------------------------------------------------------
503
void RIG_TS870S::set_volume_control(int val) // 0 .. 100
505
int ivol = (int)(val * 2.55); // 0 .. 255
507
for (int i = 4; i > 1; i--) {
514
//----------------------------------------------------------------------
515
// Tranceiver PTT on/off
518
* NOTE! If you use these CAT commands TX and RX, then when in Transmit
519
* the TS-870S *ONLY* takes audio from the front panel Mic socket.
520
* If you need to use the audio going in the rear Acc socket, you MUST
521
* use a hard wired PTT to the Acc socket. THEN it will take audio from
522
* there, and blank the mic.
523
* To do that, in the Config/Xcvr Select menu, use one of the Hardware PTT options.
524
* Just so it has been said...
527
void RIG_TS870S::set_PTT_control(int val)
529
if (val) cmd = "TX;";
534
//----------------------------------------------------------------------
535
// Play with the autotuner // disabled for now wbx
536
void RIG_TS870S::tune_rig()
539
// sendCommand(cmd, 0);
541
// this might take a while!
544
//----------------------------------------------------------------------
545
// the TS-870 actually has 4 attenuator settings.
546
// RA00; = Off, RA01; = 6dB, RA02; = 12dB, RA03; = 18dB wbx
547
void RIG_TS870S::set_attenuator(int val) {
549
if (att_level == 0) { // If attenuator level = 0 (off)
550
att_level = 1; // then turn it on, at 6dB
551
cmd = "RA01;"; // this is the command...
552
atten_label("Att 6", true); // show it in the button...
554
else if (att_level == 1) { // If attenuator level = 1 (6dB)
555
att_level = 2; // then make it 12dB
557
atten_label("Att 12", true);
559
else if (att_level == 2) { // if it's 12dB
560
att_level = 3; // go to 18dB
562
atten_label("Att 18", true);
564
else if (att_level == 3) { // If it's 18dB
565
att_level = 0; // Loop back to none.
567
atten_label("Att", false);
571
showresp(WARN, ASC, "set Att", cmd, replystr);
574
//----------------------------------------------------------------------
575
// Modified to read and show the actual radio setting, in the button.
576
int RIG_TS870S::get_attenuator() {
578
int ret = sendCommand(cmd);
579
showresp(WARN, ASC, "get Att", cmd, replystr);
580
if (ret < 5) return att_on;
581
size_t p = replystr.rfind("RA");
582
if (p == string::npos) return att_on;
584
if (replystr[p + 2] == '0' && replystr[p + 3] == '0') {
585
att_on = 0; // Attenuator is OFF
586
att_level = 0; // remember it...
587
atten_label("Att", false); // show it...
589
else if (replystr[p + 2] == '0' && replystr[p + 3] == '1') {
590
att_on = 1; // Attenuator is ON, 6dB
591
att_level = 1; // remember the level
592
atten_label("Att 6", true); // show it...
594
else if (replystr[p + 2] == '0' && replystr[p + 3] == '2') {
595
att_on = 1; // .. still ON, 12dB
596
att_level = 2; // remember this level
597
atten_label("Att 12", true); // show it.
599
else if (replystr[p + 2] == '0' && replystr[p + 3] == '3') {
600
att_on = 1; // .. still ON 18dB
601
att_level = 3; // remember...
602
atten_label("Att 18", true); // show this too..
605
return att_on; // let the rest of the world know.
608
//----------------------------------------------------------------------
609
bool RIG_TS870S::get_TS870Sid() {
611
int ret = sendCommand(cmd);
612
showresp(WARN, ASC, "Id", cmd, replystr);
613
if (ret < 6) return false;
614
size_t p = replystr.rfind("ID"); // String "ID015;"
615
if (p == string::npos) return false; // Bytes 012345
616
if (replystr[p + 2] == '0' && // wbx2
617
replystr[p + 3] == '1' &&
618
replystr[p + 4] == '5') return true; // wbx
622
//======================================================================
624
//======================================================================
625
void RIG_TS870S::set_modeA(int val)
627
active_mode = A.imode = val;
629
cmd += TS870S_mode_chr[val];
632
showresp(WARN, ASC, "set mode A", cmd, replystr);
637
//----------------------------------------------------------------------
638
int RIG_TS870S::get_modeA()
642
int ret = waitN(4, 100, "get mode A", ASC);
644
if (ret < 4) return A.imode;
645
size_t p = replystr.rfind("MD");
646
if (p == string::npos) return A.imode;
648
switch (replystr[p + 2]) {
649
case '1' : md = tsLSB; break;
650
case '2' : md = tsUSB; break;
651
case '3' : md = tsCW; break;
652
case '4' : md = tsFM; break;
653
case '5' : md = tsAM; break;
654
case '6' : md = tsFSK; break;
655
case '7' : md = tsCWR; break;
656
case '9' : md = tsFSKR; break;
657
default : md = A.imode;
661
active_mode = A.imode = md;
667
//----------------------------------------------------------------------
668
void RIG_TS870S::set_modeB(int val)
670
active_mode = B.imode = val;
672
cmd += TS870S_mode_chr[val];
675
showresp(WARN, ASC, "set mode B", cmd, replystr);
680
//----------------------------------------------------------------------
681
int RIG_TS870S::get_modeB()
685
int ret = waitN(4, 100, "get mode B", ASC);
687
if (ret < 4) return B.imode;
688
size_t p = replystr.rfind("MD");
689
if (p == string::npos) return B.imode;
691
switch (replystr[p + 2]) {
692
case '1' : md = tsLSB; break;
693
case '2' : md = tsUSB; break;
694
case '3' : md = tsCW; break;
695
case '4' : md = tsFM; break;
696
case '5' : md = tsAM; break;
697
case '6' : md = tsFSK; break;
698
case '7' : md = tsCWR; break;
699
case '9' : md = tsFSKR; break;
700
default : md = B.imode;
704
active_mode = B.imode = md;
711
//======================================================================
712
// Bandpass filter commands
713
//======================================================================
714
// Comes here when user changes mode, among other things..
715
int RIG_TS870S::set_widths(int val) // val is from the mode list index, as selected by the user.
719
if (val == tsLSB || val == tsUSB ) { // SSB modes
720
bandwidths_ = TS870S_empty;
721
dsp_lo = TS870S_SSB_lo;
722
dsp_hi = TS870S_SSB_hi;
723
lo_tooltip = TS870S_SSB_lo_tooltip;
724
lo_label = TS870S_SSB_btn_lo_label;
725
hi_tooltip = TS870S_SSB_hi_tooltip;
726
hi_label = TS870S_SSB_btn_hi_label;
727
bw = 0x8704; // 300 ... 2800 Hz
730
else if (val == tsCW || val == tsCWR) { // CW modes
731
bandwidths_ = TS870S_CWwidths;
732
dsp_lo = TS870S_empty;
733
dsp_hi = TS870S_empty;
737
else if (val == tsFSK || val == tsFSKR) { // FSK modes
738
bandwidths_ = TS870S_FSKwidths;
739
dsp_lo = TS870S_empty;
740
dsp_hi = TS870S_empty;
744
else if (val == tsAM) { // val == 5 ==> AM mode
745
bandwidths_ = TS870S_empty;
746
dsp_lo = TS870S_AM_lo;
747
dsp_hi = TS870S_AM_hi;
748
lo_tooltip = TS870S_AM_lo_tooltip;
749
lo_label = TS870S_AM_btn_lo_label;
750
hi_tooltip = TS870S_AM_hi_tooltip;
751
hi_label = TS870S_AM_btn_hi_label;
752
bw = 0x8401; // 100Hz .. 6000Hz
755
// FM mode BW selection.
756
else if (val == tsFM) { // FM mode
757
bandwidths_ = TS870S_FMwidths; // load the dropdown with our list
758
dsp_lo = TS870S_empty;
759
dsp_hi = TS870S_empty;
766
//----------------------------------------------------------------------
767
const char **RIG_TS870S::bwtable(int m)
769
if (m == tsLSB || m == tsUSB || m == tsAM)
770
return NULL; // these modes have lo and hi settings.
772
else if (m == tsCW || m == tsCWR)
773
return TS870S_CWwidths;
775
else if (m == tsFSK || m == tsFSKR)
776
return TS870S_FSKwidths;
779
return TS870S_FMwidths;
785
const char **RIG_TS870S::lotable(int m)
787
if (m == tsLSB || m == tsUSB || m == tsAM)
788
return TS870S_SSB_lo; // these modes have lo and hi settings.
790
else if (m == tsCW || m == tsCWR)
793
else if (m == tsFSK || m == tsFSKR)
803
const char **RIG_TS870S::hitable(int m)
805
if (m == tsLSB || m == tsUSB || m == tsAM)
806
return TS870S_SSB_hi; // these modes have lo and hi settings.
808
else if (m == tsCW || m == tsCWR)
811
else if (m == tsFSK || m == tsFSKR)
821
//----------------------------------------------------------------------
822
int RIG_TS870S::adjust_bandwidth(int val)
824
if (val == tsLSB || val == tsUSB )
825
return 0x8704; // 2800Hz .. 300Hz
827
else if (val == tsCW || val == tsCWR)
830
else if (val == tsFSK || val == tsFSKR)
833
else if (val == tsFM)
836
// else if (val == tsAM)
837
return 0x8401; // 6000Hz .. 100Hz
840
//----------------------------------------------------------------------
841
int RIG_TS870S::def_bandwidth(int val)
843
return adjust_bandwidth(val);
846
//----------------------------------------------------------------------
847
void RIG_TS870S::set_bwA(int val)
850
if (A.imode == tsLSB || A.imode == tsUSB ) {
851
if (val < 256) return; // not hi/lo setting
854
cmd = TS870S_CAT_ssb_lo[A.iBW & 0x7F];
856
showresp(WARN, ASC, "set lower", cmd, replystr);
858
cmd = TS870S_CAT_ssb_hi[(A.iBW >> 8) & 0x7F];
860
showresp(WARN, ASC, "set upper", cmd, replystr);
866
if (A.imode == tsAM) {
867
if (val < 256) return; // not hi/lo setting
870
cmd = TS870S_CAT_am_lo[A.iBW & 0x7F];
872
showresp(WARN, ASC, "set lower", cmd, replystr);
874
cmd = TS870S_CAT_am_hi[(A.iBW >> 8) & 0x7F];
876
showresp(WARN, ASC, "set upper", cmd, replystr);
880
if (val > 256) return;
883
if (A.imode == tsCW || A.imode == tsCWR) {
885
cmd = TS870S_CWbw[A.iBW];
887
showresp(WARN, ASC, "set CW bw", cmd, replystr);
892
if (A.imode == tsFSK || A.imode == tsFSKR) {
894
cmd = TS870S_FSKbw[A.iBW];
896
showresp(WARN, ASC, "set FSK bw", cmd, replystr);
901
if (A.imode == tsFM) {
903
cmd = TS870S_FMbw[A.iBW];
905
showresp(WARN, ASC, "set FM bw", cmd, replystr);
910
//----------------------------------------------------------------------
911
void RIG_TS870S::set_bwB(int val)
913
if (B.imode == tsLSB || B.imode == tsUSB ) {
914
if (val < 256) return;
917
cmd = TS870S_CAT_ssb_lo[B.iBW & 0x7F];
919
showresp(WARN, ASC, "set lower", cmd, replystr);
921
cmd = TS870S_CAT_ssb_hi[(B.iBW >> 8) & 0x7F];
923
showresp(WARN, ASC, "set upper", cmd, replystr);
928
if (B.imode == tsAM) {
929
if (val < 256) return;
932
cmd = TS870S_CAT_am_lo[B.iBW & 0x7F]; // corrected wbx2
934
showresp(WARN, ASC, "set lower", cmd, replystr);
936
cmd = TS870S_CAT_am_hi[(B.iBW >> 8) & 0x7F]; // corrected wbx2
938
showresp(WARN, ASC, "set upper", cmd, replystr);
943
if (val > 256) return;
945
if (B.imode == tsCW || B.imode == tsCWR) {
947
cmd = TS870S_CWbw[B.iBW];
949
showresp(WARN, ASC, "set CW bw", cmd, replystr);
953
if (B.imode == tsFSK || B.imode == tsFSKR) {
955
cmd = TS870S_FSKbw[B.iBW];
957
showresp(WARN, ASC, "set FSK bw", cmd, replystr);
961
if (A.imode == tsFM) {
963
cmd = TS870S_FMbw[A.iBW];
965
showresp(WARN, ASC, "set FM bw", cmd, replystr);
971
//----------------------------------------------------------------------
972
int RIG_TS870S::get_bwA() {
977
if (A.imode == tsFM) { // FM mode.
978
cmd = "FW;"; // 'Filter Width' query
979
waitN(7, 100, "get CW width", ASC);
980
p = replystr.rfind("FW");
982
if (p != string::npos) { // If 'FW' found then scan the known responces to find out what we got.
983
for (i = 0; TS870S_FMbw[i] != NULL; i++) // bump array index counter, till string match or end.
984
if (replystr.find(TS870S_FMbw[i]) == p) break; // Found returned data, in string array.
986
if (TS870S_FMbw[i] != NULL) A.iBW = i; // if we didn't hit the end, return the array index value.
987
else A.iBW = 1; // Default.
991
else if (A.imode == tsCW || A.imode == tsCWR) { // CW modes.
992
cmd = "FW;"; // 'Filter Width' query
993
waitN(7, 100, "get CW width", ASC);
994
p = replystr.rfind("FW");
996
if (p != string::npos) { // If 'FW' found then scan the known responces to find out what we got.
997
for (i = 0; TS870S_CWbw[i] != NULL; i++) // bump array index counter, till string match or end.
998
if (replystr.find(TS870S_CWbw[i]) == p) break; // Found returned data, in string array.
1000
if (TS870S_CWbw[i] != NULL) A.iBW = i; // if we didn't hit the end, return the array index value.
1001
else A.iBW = 1; // Default.
1005
else if (A.imode == tsFSK || A.imode == tsFSKR ) { // FSK modes.
1007
waitN(7, 100, "get FSK width", ASC);
1008
p = replystr.rfind("FW");
1010
if (p != string::npos) { // If 'FW' found then scan the known responces to find out what we got.
1011
for (i = 0; TS870S_FSKbw[i] != NULL; i++) // bump array index counter, till string match or end.
1012
if (replystr.find(TS870S_FSKbw[i]) == p) break; // Found returned data, in string array.
1014
if (TS870S_FSKbw[i] != NULL) A.iBW = i; // if we didn't hit the end, return the array index value.
1015
else A.iBW = 1; // Default.
1020
else if (A.imode == tsAM) { // AM mode only
1022
int lo = A.iBW & 0x7F, hi = (A.iBW >> 8) & 0x7F;
1023
// High byte is hi cutoff index (not MSB though.) Low byte is lo cuttoff index.
1025
cmd = "FW;"; // Read Low cuttoff. Returns a two digit code as 'FLxxxx;' in 10Hz increments.
1026
waitN(5, 100, "get lower", ASC);
1027
p = replystr.rfind("FW");
1029
if (p != string::npos) { // If 'FW' found then scan the known responces to find out what we got.
1030
for (i = 0; TS870S_CAT_am_lo[i] != NULL; i++) // bump array index counter, till string match or end.
1031
if (replystr.find(TS870S_CAT_am_lo[i]) == p) break; // Found returned data, in string array.
1033
if (TS870S_CAT_am_lo[i] != NULL) lo = i; // if we didn't hit the end, return the array index value.
1034
else lo = 1; // Default.
1038
waitN(5, 100, "get upper", ASC);
1039
p = replystr.rfind("IS ");
1041
if (p != string::npos) {
1042
for (i = 0; TS870S_CAT_am_hi[i] != NULL; i++) // bump array index counter, till string match or end.
1043
if (replystr.find(TS870S_CAT_am_hi[i]) == p) break; // Found returned data, in string array.
1045
if (TS870S_CAT_am_hi[i] != NULL) hi = i; // if we didn't hit the end, return the array index value.
1046
else hi = 1; // Default.
1048
A.iBW = ((hi << 8) | (lo & 0x7F)) | 0x8000;
1049
// Shift hi index up 8 bits into High Byte, then concatntat it with the Low byte, into one 16 bit value.
1053
else if (A.imode == tsLSB || A.imode == tsUSB ) { // SSB (upper and lower)
1055
int lo = A.iBW & 0x7F, hi = (A.iBW >> 8) & 0x7F; // Same trick as above...
1057
cmd = "FW;"; // Read Low cuttoff. Returns a two digit code as 'FLxxxx;' in 10Hz increments.
1058
waitN(5, 100, "get lower", ASC);
1059
p = replystr.rfind("FW");
1061
if (p != string::npos) { // If 'FW' found then scan the known responces to find out what we got.
1062
for (i = 0; TS870S_CAT_ssb_lo[i] != NULL; i++) // bump array index counter, till string match or end.
1063
if (replystr.find(TS870S_CAT_ssb_lo[i]) == p) break; // Found returned data, in string array.
1065
if (TS870S_CAT_ssb_lo[i] != NULL) lo = i; // if we didn't hit the end, return the array index value.
1066
else lo = 1; // Default.
1070
waitN(5, 100, "get upper", ASC);
1071
p = replystr.rfind("IS ");
1073
if (p != string::npos) {
1074
for (i = 0; TS870S_CAT_ssb_hi[i] != NULL; i++) // bump array index counter, till string match or end.
1075
if (replystr.find(TS870S_CAT_ssb_hi[i]) == p) break; // Found returned data, in string array.
1077
if (TS870S_CAT_ssb_hi[i] != NULL) hi = i; // if we didn't hit the end, return the array index value.
1078
else hi = 1; // Default.
1080
A.iBW = ((hi << 8) | (lo & 0x7F)) | 0x8000;
1085
//----------------------------------------------------------------------
1086
int RIG_TS870S::get_bwB()
1091
if (B.imode == tsFM) {
1092
cmd = "FW;"; // 'Filter Width' query
1093
waitN(7, 100, "get CW width", ASC);
1094
p = replystr.rfind("FW");
1096
if (p != string::npos) { // If 'FW' found then scan the known responces to find out what we got.
1097
for (i = 0; TS870S_FMbw[i] != NULL; i++) // bump array index counter, till string match or end.
1098
if (replystr.find(TS870S_FMbw[i]) == p) break; // Found returned data, in string array.
1100
if (TS870S_FMbw[i] != NULL) B.iBW = i; // if we didn't hit the end, return the array index value.
1101
else B.iBW = 1; // Default.
1105
else if (B.imode == tsCW || B.imode == tsCWR) { // CW modes.
1106
cmd = "FW;"; // 'Filter Width' query
1107
waitN(7, 100, "get CW width", ASC);
1108
p = replystr.rfind("FW");
1110
if (p != string::npos) { // If 'FW' found then scan the known responces to find out what we got.
1111
for (i = 0; TS870S_CWbw[i] != NULL; i++) // bump array index counter, till string match or end.
1112
if (replystr.find(TS870S_CWbw[i]) == p) break; // Found returned data, in string array.
1114
if (TS870S_CWbw[i] != NULL) B.iBW = i; // if we didn't hit the end, return the array index value.
1115
else B.iBW = 1; // Default.
1119
else if (B.imode == tsFSK || B.imode == tsFSKR) { // FSK modes.
1121
waitN(7, 100, "get FSK width", ASC);
1122
p = replystr.rfind("FW");
1124
if (p != string::npos) { // If 'FW' found then scan the known responces to find out what we got.
1125
for (i = 0; TS870S_FSKbw[i] != NULL; i++) // bumb array index counter, till string match or end.
1126
if (replystr.find(TS870S_FSKbw[i]) == p) break; // Found returned data, in string array.
1128
if (TS870S_FSKbw[i] != NULL) B.iBW = i; // if we didn't hit the end, return the array index value.
1129
else B.iBW = 1; // Default.
1133
else if (B.imode == tsAM) { // AM mode only
1135
int lo = B.iBW & 0x7F, hi = (B.iBW >> 8) & 0x7F;
1137
cmd = "FW;"; // Read Low cuttoff. Returns a two digit code as 'FLxxxx;' in 10Hz increments.
1138
waitN(5, 100, "get lower", ASC);
1139
p = replystr.rfind("FW");
1141
if (p != string::npos) { // If 'FW' found then scan the known responces to find out what we got.
1142
for (i = 0; TS870S_CAT_am_lo[i] != NULL; i++) // bump array index counter, till string match or end.
1143
if (replystr.find(TS870S_CAT_am_lo[i]) == p) break; // Found returned data, in string array.
1145
if (TS870S_CAT_am_lo[i] != NULL) lo = i; // if we didn't hit the end, return the array index value.
1146
else lo = 1; // Default.
1150
waitN(5, 100, "get upper", ASC);
1151
p = replystr.rfind("IS ");
1153
if (p != string::npos) {
1154
for (i = 0; TS870S_CAT_am_hi[i] != NULL; i++) // bump array index counter, till string match or end.
1155
if (replystr.find(TS870S_CAT_am_hi[i]) == p) break; // Found returned data, in string array.
1157
if (TS870S_CAT_am_hi[i] != NULL) hi = i; // if we didn't hit the end, return the array index value.
1158
else hi = 1; // Default.
1160
B.iBW = ((hi << 8) | (lo & 0x7F)) | 0x8000;
1164
else if (B.imode == tsLSB || B.imode == tsUSB ) { // SSB (Upper and lower)
1166
int lo = B.iBW & 0x7F, hi = (B.iBW >> 8) & 0x7F;
1168
cmd = "FW;"; // Read Low cuttoff. Returns a two digit code as 'FLxxxx;' in 10Hz increments.
1169
waitN(5, 100, "get lower", ASC);
1170
p = replystr.rfind("FW");
1172
if (p != string::npos) { // If 'FW' found then scan the known responces to find out what we got.
1173
for (i = 0; TS870S_CAT_ssb_lo[i] != NULL; i++) // bump array index counter, till string match or end.
1174
if (replystr.find(TS870S_CAT_ssb_lo[i]) == p) break; // Found returned data, in string array.
1176
if (TS870S_CAT_ssb_lo[i] != NULL) lo = i; // if we didn't hit the end, return the array index value.
1177
else lo = 1; // Default.
1181
waitN(5, 100, "get upper", ASC);
1182
p = replystr.rfind("IS ");
1184
if (p != string::npos) {
1185
for (i = 0; TS870S_CAT_ssb_hi[i] != NULL; i++) // bump array index counter, till string match or end.
1186
if (replystr.find(TS870S_CAT_ssb_hi[i]) == p) break; // Found returned data, in string array.
1188
if (TS870S_CAT_ssb_hi[i] != NULL) hi = i; // if we didn't hit the end, return the array index value.
1189
else hi = 1; // Default.
1191
B.iBW = ((hi << 8) | (lo & 0x7F)) | 0x8000;
1196
//----------------------------------------------------------------------
1197
int RIG_TS870S::get_modetype(int n)
1199
return TS870S_mode_type[n];
1202
//----------------------------------------------------------------------
1204
void RIG_TS870S::set_mic_gain(int val)
1206
int imic = (int)(val * 2.55); // 0 .. 255
1208
for (int i = 3; i > 0; i--) {
1209
cmd[1+i] += imic % 10;
1212
sendCommand(cmd, 0);
1215
//----------------------------------------------------------------------
1216
int RIG_TS870S::get_mic_gain()
1220
int ret = waitN(6, 100, "get mic ctrl", ASC);
1223
size_t p = replystr.rfind("MG");
1224
if (p == string::npos) return val;
1225
replystr[p + 5] = 0;
1226
val = atoi(&replystr[p + 2]);
1228
return (int)(val / 2.55); // we only want 0 .. 100
1231
//----------------------------------------------------------------------
1232
void RIG_TS870S::get_mic_min_max_step(int &min, int &max, int &step)
1239
//----------------------------------------------------------------------
1240
void RIG_TS870S::set_noise(bool val)
1247
showresp(WARN, ASC, "set NB", cmd, replystr);
1250
int RIG_TS870S::get_noise()
1253
int ret = sendCommand(cmd);
1254
showresp(WARN, ASC, "get NB", cmd, replystr);
1255
if (ret < 4) return 0;
1256
size_t p = replystr.rfind("NB");
1257
if (p == string::npos) return 0;
1259
return (replystr[p + 2] == '1'); // true if 1
1262
//======================================================================
1263
// IF shift command only available if the transceiver is in the CW mode
1264
// step size is 50 Hz
1265
//======================================================================
1266
// See also, the code in support.cxx
1267
// setMode and setModeControl, calling 'checkTS870S'
1269
void RIG_TS870S::set_if_shift(int val)
1271
if (active_mode == tsCW || active_mode == tsCWR) { // cw modes
1272
progStatus.shift_val = val;
1274
cmd.append(to_decimal(abs(val),4)).append(";");
1276
showresp(WARN, ASC, "set IF shift", cmd, replystr);
1280
//----------------------------------------------------------------------
1281
bool RIG_TS870S::get_if_shift(int &val)
1283
if (active_mode == tsCW || active_mode == tsCWR) { // cw modes
1285
waitN(8, 100, "get IF shift", ASC);
1286
size_t p = replystr.rfind("IS");
1287
if (p != string::npos) {
1288
val = fm_decimal(&replystr[p+3], 4);
1290
val = progStatus.shift_val;
1293
val = progStatus.shift_val;
1297
//----------------------------------------------------------------------
1298
void RIG_TS870S::get_if_min_max_step(int &min, int &max, int &step)
1300
if_shift_min = min = 400;
1301
if_shift_max = max = 1000;
1302
if_shift_step = step = 50;
1306
//----------------------------------------------------------------------
1307
void RIG_TS870S::set_notch(bool on, int val)
1311
sendCommand(cmd, 0);
1316
cmd[6] = '1'; // notch ON
1317
sendCommand(cmd, 0);
1321
cmd[3] = '1'; // manual NOTCH position
1322
// set notch value offset by 200, ie: 001 -> 400
1323
val = (-val / 9) + 200;
1324
if (val < 1) val = 1;
1325
if (val > 400) val = 400;
1326
for (int i = 3; i > 0; i--) {
1327
cmd[3 + i] += val % 10;
1330
sendCommand(cmd, 0);
1333
//----------------------------------------------------------------------
1335
bool RIG_TS870S::get_notch(int &val)
1338
// bool ison = false;
1340
// int ret = sendCommand(cmd);
1344
//----------------------------------------------------------------------
1345
void RIG_TS870S::get_notch_min_max_step(int &min, int &max, int &step)
1352
//----------------------------------------------------------------------
1354
//----------------------------------------------------------------------