1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2014, 2020
3 // Michael Black W9MDB
4 // David Freese, W1HKJ
5 //
6 // This file is part of flrig.
7 //
8 // flrig is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3 of the License, or
11 // (at your option) any later version.
12 //
13 // flrig is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // aunsigned long int with this program. If not, see <http://www.gnu.org/licenses/>.
20 // ----------------------------------------------------------------------------
21
22 #include "PowerSDR.h"
23 #include "support.h"
24 #include <sstream>
25
26 static const char PowerSDRname_[] = "PowerSDR";
27
28 static const char *PowerSDRmodes_[] = {
29 "LSB", "USB", "DSB", "CWL", "CWU", "FM", "AM", "DIGU", "SPEC", "DIGL", "SAM", "DRM", NULL};
30
31 static const char *PowerSDR_mode_chr[] = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", NULL };
32 static const char PowerSDR_mode_type[] = { 'L', 'U', 'U', 'L', 'U', 'U', 'U', 'U', 'U', 'L', 'U', 'U' };
33
34 static const char *PowerSDR_empty[] = { NULL, NULL };
35 //------------------------------------------------------------------------
36 static const char *PowerSDR_USBwidths[] = {
37 "1000", "1800", "2100", "2400", "2700",
38 "2900", "3300", "3800", "4400", "5000",
39 "Var1", "Var2", "Wideband", NULL };
40 static const char *PowerSDR_CAT_USB[] = {
41 "ZZFI09;", "ZZFI08;", "ZZFI07;", "ZZFI06;", "ZZFI05;",
42 "ZZFI04;", "ZZFI03;", "ZZFI02;", "ZZFI01;", "ZZFI00;",
43 "ZZFI10;", "ZZFI11;", "ZZFI12;", NULL };
44 //static const char *PowerSDR_SH_tooltip = "hi cut";
45 //static const char *PowerSDR_SSB_btn_SH_label = "H";
46 //------------------------------------------------------------------------
47 static const char *PowerSDR_WIDEwidths[] = {
48 "Wideband" };
49 //static const char *PowerSDR_CAT_WIDE[] = {
50 //"ZZFI12;" };
51 //------------------------------------------------------------------------
52 static const char *PowerSDR_DIGwidths[] = {
53 "75", "150", "300", "600", "800",
54 "1000", "1500", "2000", "2500", "3000",
55 "Var1", "Var2", NULL };
56 static const char *PowerSDR_CAT_DIG[] = {
57 "ZZFI09;", "ZZFI08;", "ZZFI07;", "ZZFI06;", "ZZFI05;",
58 "ZZFI04;", "ZZFI03;", "ZZFI02;", "ZZFI01;", "ZZFI00;",
59 "ZZFI10;", "ZZFI11;", NULL };
60 //------------------------------------------------------------------------------
61 static const char *PowerSDR_AMwidths[] = {
62 "2400", "2900", "3100", "4000" "5200",
63 "6600", "8000", "10000", "12000", "16000",
64 "Var1", "Var2", NULL };
65 static const char *PowerSDR_CAT_AM[] = {
66 "ZZFI09;", "ZZFI08;", "ZZFI07;", "ZZFI06;", "ZZFI05;",
67 "ZZFI04;", "ZZFI03;", "ZZFI02", "ZZFI01;", "ZZFI00;",
68 "ZZFI10;", "ZZFI11;", NULL };
69 //------------------------------------------------------------------------------
70 static const char *PowerSDR_CWwidths[] = {
71 "25", "50", "100", "150", "250",
72 "400", "500", "600", "800", "1000",
73 "Var1", "Var2", NULL};
74 static const char *PowerSDR_CAT_CW[] = {
75 "ZZFI09;", "ZZFI08;", "ZZFI07;", "ZZFI06;", "ZZFI05;",
76 "ZZFI04;", "ZZFI03;", "ZZFI02;", "ZZFI01;", "ZZFI00;",
77 "ZZFI10;", "ZZFI11", NULL };
78 //------------------------------------------------------------------------------
79
80 static GUI rig_widgets[]= {
81 { (Fl_Widget *)btnVol, 2, 125, 50 }, // 0
82 { (Fl_Widget *)sldrVOLUME, 54, 125, 156 }, // 1
83 { (Fl_Widget *)sldrRFGAIN, 54, 145, 156 }, // 2
84 { (Fl_Widget *)btnIFsh, 214, 105, 50 }, // 3
85 { (Fl_Widget *)sldrIFSHIFT, 266, 105, 156 }, // 4
86 { (Fl_Widget *)btnNotch, 214, 125, 50 }, // 5
87 { (Fl_Widget *)sldrNOTCH, 266, 125, 156 }, // 6
88 { (Fl_Widget *)sldrSQUELCH, 266, 145, 156 }, // 7
89 { (Fl_Widget *)sldrMICGAIN, 266, 165, 156 }, // 8
90 { (Fl_Widget *)sldrPOWER, 54, 165, 368 }, // 9
91 { (Fl_Widget *)NULL, 0, 0, 0 }
92 };
93
94 // mid range on loudness
95 static string menu012 = "EX01200004";
96
initialize()97 void RIG_PowerSDR::initialize()
98 {
99 rig_widgets[0].W = btnVol;
100 rig_widgets[1].W = sldrVOLUME;
101 rig_widgets[2].W = sldrRFGAIN;
102 rig_widgets[3].W = btnIFsh;
103 rig_widgets[4].W = sldrIFSHIFT;
104 rig_widgets[5].W = btnNotch;
105 rig_widgets[6].W = sldrNOTCH;
106 rig_widgets[7].W = sldrSQUELCH;
107 rig_widgets[8].W = sldrMICGAIN;
108 rig_widgets[9].W = sldrPOWER;
109
110 menu012.clear();
111 cmd = "EX0120000;"; // read menu 012 state
112 //might return something like EX01200004;
113
114 if (wait_char(';', 11, 100, "read ex 012", ASC) == 11)
115 menu012 = replystr;
116
117 // disable beeps before resetting front panel display to SWR
118 cmd = "EX01200000;";
119 sendCommand(cmd);
120 sett("No beeps");
121 select_swr();
122
123 // restore state of xcvr beeps
124 // cmd = menu012;
125 // sendCommand(cmd);
126
127 // get current noise reduction values for NR1 and NR2
128 string current_nr;
129 cmd = "NR;";
130 if (wait_char(';', 4, 100, "read current NR", ASC) == 4)
131 current_nr = replystr;
132 gett("get NR");
133 cmd = "RL;";
134 if (wait_char(';', 5, 100, "GET noise reduction val", ASC) == 5) {
135 size_t p = replystr.rfind("RL");
136 if (p != string::npos)
137 _nrval1 = atoi(&replystr[p+2]);
138 }
139
140 // restore xcvr setting for NR
141 cmd = current_nr;
142 sendCommand(cmd);
143 }
144
shutdown()145 void RIG_PowerSDR::shutdown()
146 {
147 // restore state of xcvr beeps
148 if (menu012.empty()) return;
149 cmd = menu012;
150 sendCommand(cmd);
151 sett("restore beeps");
152 }
153
154 static bool is_tuning = false;
155
RIG_PowerSDR()156 RIG_PowerSDR::RIG_PowerSDR() {
157 // base class values
158 name_ = PowerSDRname_;
159 modes_ = PowerSDRmodes_;
160 bandwidths_ = PowerSDR_empty;
161
162 //dsp_SL = PowerSDR_SL;
163 //SL_tooltip = PowerSDR_SL_tooltip;
164 //SL_label = PowerSDR_SSB_btn_SL_label;
165
166 //dsp_SH = PowerSDR_SH;
167 //SH_tooltip = PowerSDR_SH_tooltip;
168 //SH_label = PowerSDR_SSB_btn_SH_label;
169
170 widgets = rig_widgets;
171
172 comm_baudrate = BR4800;
173 stopbits = 2;
174 comm_retries = 2;
175 comm_wait = 5;
176 comm_timeout = 50;
177 comm_rtscts = true;
178 comm_rtsplus = false;
179 comm_dtrplus = false;
180 comm_catptt = true;
181 comm_rtsptt = false;
182 comm_dtrptt = false;
183 B.imode = A.imode = 1;
184 B.iBW = A.iBW = 0x8803;
185 B.freq = A.freq = 14070000;
186 can_change_alt_vfo = true;
187
188 //has_dsp_controls = true;
189 has_power_out = true;
190 has_swr_control = true;
191 has_alc_control =
192 has_split =
193 has_split_AB =
194 has_rf_control =
195 has_notch_control =
196 has_auto_notch =
197 has_ifshift_control =
198 has_smeter =
199 has_noise_reduction = true;
200 has_noise_reduction_control =
201 has_noise_control =
202 has_micgain_control =
203 has_volume_control =
204 has_power_control =
205 has_tune_control =
206 has_preamp_control =
207 has_mode_control =
208 has_bandwidth_control =
209 has_sql_control =
210 has_ptt_control =
211 has_extras = true;
212
213 rxona = true;
214
215 precision = 1;
216 ndigits = 9;
217
218 att_level = 0;
219 preamp_level = 0;
220 _noise_reduction_level = 0;
221 _nrval1 = 2;
222 _nrval2 = 4;
223
224 is_tuning = false;
225 }
226
227
get_bwname_(int n,int md)228 const char * RIG_PowerSDR::get_bwname_(int n, int md)
229 {
230 static char bwname[20];
231 stringstream str;
232 str << "n=" << n << ", md=" << md;
233 trace(2, __func__, str.str().c_str());
234 if (md == USB || md == LSB) {
235 snprintf(bwname, sizeof(bwname), "%s", PowerSDR_USBwidths[n]);
236 }
237 else if (md == FM || md == DRM || md == SPEC) {
238 snprintf(bwname, sizeof(bwname), "%s", PowerSDR_WIDEwidths[n]);
239 }
240 else if (md == DIGU || md == DIGL) {
241 snprintf(bwname, sizeof(bwname), "%s", PowerSDR_DIGwidths[n]);
242 }
243 else if (md == CWU || md == CWL) {
244 snprintf(bwname, sizeof(bwname), "%s", PowerSDR_CWwidths[n]);
245 } else {
246 snprintf(bwname, sizeof(bwname), "%s", PowerSDR_AMwidths[n]);
247 }
248 return bwname;
249 }
250
get_smeter()251 int RIG_PowerSDR::get_smeter()
252 {
253 int smtr = 0;
254 if (rxona)
255 cmd = "ZZSM0;";
256 else
257 cmd = "ZZSM1;";
258 int w = wait_char(';', 9, 100, "get smeter", ASC);
259 if (w == 9) {
260 size_t p = replystr.rfind("SM");
261 if (p != string::npos) {
262 smtr = fm_decimal(replystr.substr(p+3),3);
263 smtr = -54 + smtr/(256.0/100.0); // in S-Units
264 smtr = (smtr + 54);
265 }
266 }
267 gett("smeter");
268 return smtr;
269 }
270
271 // Transceiver power level
set_power_control(double val)272 void RIG_PowerSDR::set_power_control(double val)
273 {
274 int ival = (int)val;
275 cmd = "PC";
276 cmd.append(to_decimal(ival, 3)).append(";");
277 sendCommand(cmd);
278 showresp(WARN, ASC, "set pwr ctrl", cmd, "");
279 sett("pwr control");
280 }
281
get_power_out()282 int RIG_PowerSDR::get_power_out()
283 {
284 int mtr = 0;
285
286 cmd = "ZZRM5;";
287 if (wait_char(';', 8, 100, "get power", ASC) < 8) return mtr;
288 sscanf(&replystr[0],"ZZRM5%d", &mtr);
289
290 return mtr;
291 }
292
293
get_power_control()294 int RIG_PowerSDR::get_power_control()
295 {
296 int pctrl = 0;
297 cmd = "PC;";
298 if (wait_char(';', 6, 100, "get pout", ASC) == 6) {
299 size_t p = replystr.rfind("PC");
300 if (p != string::npos) {
301 pctrl = fm_decimal(replystr.substr(p+2), 3);
302 }
303 }
304 gett("power control");
305 return pctrl;
306 }
307
308 struct meterpair {float mtr; float val;};
309
310 static meterpair swr_tbl[] = {
311 { 1, 0 },
312 { 1.5, 12.5 },
313 { 2, 25 },
314 { 3, 50 },
315 { 20, 100 }
316 };
317
get_swr()318 int RIG_PowerSDR::get_swr()
319 {
320 double mtr = 0;
321
322 cmd = "ZZRM8;";
323 if (wait_char(';', 8, 100, "get SWR", ASC) < 8) return (int)mtr;
324 if(sscanf(&replystr[0], "ZZRM8%lf", &mtr)!=1)
325 {
326 return 0;
327 }
328 size_t i = 0;
329 for (i = 0; i < sizeof(swr_tbl) / sizeof(meterpair) - 1; i++)
330 if (mtr >= swr_tbl[i].mtr && mtr < swr_tbl[i+1].mtr)
331 break;
332 if (mtr > 19) mtr = 19;
333 mtr = (int)round(swr_tbl[i].val +
334 (swr_tbl[i+1].val - swr_tbl[i].val)*(mtr - swr_tbl[i].mtr)/(swr_tbl[i+1].mtr - swr_tbl[i].mtr));
335 if (mtr > 100) mtr = 100;
336
337 return mtr;
338 }
339
get_alc()340 int RIG_PowerSDR::get_alc()
341 {
342 double alc = 0;
343 cmd = "ZZRM4;";
344 if (wait_char(';', 8, 100, "get ALC", ASC) < 8) return (int)alc;
345 if (sscanf(&replystr[0], "ZZRM4%lf", &alc) != 1) alc=0;
346 return alc;
347 }
348
set_preamp(int val)349 void RIG_PowerSDR::set_preamp(int val)
350 {
351 preamp_level = val;
352 if (val) cmd = "ZZPA1;";
353 else cmd = "ZZPA0;";
354 sendCommand(cmd);
355 showresp(WARN, ASC, "set PRE", cmd, "");
356 sett("preamp");
357 }
358
get_preamp()359 int RIG_PowerSDR::get_preamp()
360 {
361 cmd = "ZZPA;";
362 stringstream str;
363 str << "ZZPA #1";
364 trace(2, __func__, str.str().c_str());
365 sendCommand(cmd);
366 if (wait_char(';', 6, 100, "get PRE", ASC) != 6) {
367 size_t p = replystr.rfind("PA");
368 str << "ZZPA #2 replystr=" << replystr << ", p=" << p;
369 trace(2, "get_preamp", replystr.c_str());
370 if (p != string::npos && (p+2 < replystr.length())) {
371 if (replystr[p+2] == '1')
372 preamp_level = 1;
373 else
374 preamp_level = 0;
375 }
376 }
377 else preamp_level = 0;
378 gett("preamp");
379 return preamp_level;
380 }
381
set_widths(int val)382 int RIG_PowerSDR::set_widths(int val)
383 {
384 int bw = get_bwA();
385 stringstream str;
386 str << bw;
387 trace(2, "set_widths bw=", str.str().c_str());
388 switch (val) {
389 case LSB: case USB:
390 bandwidths_ = PowerSDR_USBwidths;
391 dsp_SL = PowerSDR_empty;
392 dsp_SH = PowerSDR_empty;
393 //dsp_SL = PowerSDR_SL;
394 //SL_tooltip = PowerSDR_SL_tooltip;
395 //SL_label = PowerSDR_SSB_btn_SL_label;
396 //dsp_SH = PowerSDR_SH;
397 //SH_tooltip = PowerSDR_SH_tooltip;
398 //SH_label = PowerSDR_SSB_btn_SH_label;
399 //bw = 0;
400 break;
401 case DIGU: case DIGL:
402 bandwidths_ = PowerSDR_DIGwidths;
403 dsp_SL = PowerSDR_empty;
404 dsp_SH = PowerSDR_empty;
405 //bw = 9;
406 break;
407 case FM: case SPEC: case DRM:
408 bandwidths_ = PowerSDR_WIDEwidths;
409 dsp_SL = PowerSDR_empty;
410 dsp_SH = PowerSDR_empty;
411 //bw = 0;
412 break;
413 case CWL: case CWU:
414 bandwidths_ = PowerSDR_CWwidths;
415 dsp_SL = PowerSDR_empty;
416 dsp_SH = PowerSDR_empty;
417 //bw = 7;
418 break;
419 case AM: case SAM: case DSB: default:
420 bandwidths_ = PowerSDR_AMwidths;
421 dsp_SL = PowerSDR_empty;
422 dsp_SH = PowerSDR_empty;
423 //bw = 12;
424 break;
425 }
426 return bw;
427 }
428
bwtable(int val)429 const char **RIG_PowerSDR::bwtable(int val)
430 {
431 if (val == LSB || val == USB)
432 return PowerSDR_USBwidths;
433 else if (val == FM || val == DRM || val == SPEC)
434 return PowerSDR_WIDEwidths;
435 else if (val == DIGU || val == DIGL)
436 return PowerSDR_DIGwidths;
437 else if (val == CWU || val == CWL)
438 return PowerSDR_CWwidths;
439 else if (val == AM || val == SAM || val == DSB)
440 return PowerSDR_AMwidths;
441 return NULL;
442 }
443
444 #if 0
445 const char **RIG_PowerSDR::lotable(int val)
446 {
447 if (val == LSB || val == USB || val == FM || val == DRM || val == SPEC)
448 return PowerSDR_USBwidths;
449 else if (val == DIGU || val == DIGL)
450 return PowerSDR_DIGwidths;
451 else if (val == AM || val == SAM || val == DSB)
452 return PowerSDR_AMwidths;
453 return NULL;
454 }
455
456 const char **RIG_PowerSDR::hitable(int val)
457 {
458 if (val == LSB || val == USB || val == FM || val == DRM || val == SPEC)
459 return PowerSDR_USBwidths;
460 else if (val == DIGU || val == DIGL)
461 return PowerSDR_DIGwidths;
462 else if (val == CWU || val == CWL)
463 return PowerSDR_CWwidths;
464 else if (val == AM || val == SAM || val == DSB)
465 return PowerSDR_AMwidths;
466 return NULL;
467 }
468 #endif
469
set_modeA(int val)470 void RIG_PowerSDR::set_modeA(int val)
471 {
472 if (val >= (int)(sizeof(PowerSDR_mode_chr)/sizeof(*PowerSDR_mode_chr))) return;
473 _currmode = A.imode = val;
474 cmd = "ZZMD";
475 cmd += PowerSDR_mode_chr[val];
476 cmd += ';';
477 sendCommand(cmd);
478 showresp(WARN, ASC, "set mode", cmd, "");
479 sett("modeA");
480 A.iBW = set_widths(val);
481 vfoA.iBW = A.iBW;
482 }
483
get_modeA()484 int RIG_PowerSDR::get_modeA()
485 {
486 if (tuning()) return A.imode;
487 cmd = "ZZMD;";
488 int ww = wait_char(';', 7, 100, "get mode A", 7);
489 if (ww == 7) {
490 size_t p = replystr.rfind("MD");
491 if (p != string::npos) {
492 int md;
493 sscanf(&replystr[p+2],"%d",&md);
494
495 A.imode = md;
496 A.iBW = set_widths(A.imode);
497 }
498 }
499 _currmode = A.imode;
500 gett("modeA");
501 return A.imode;
502 }
503
504
set_modeB(int val)505 void RIG_PowerSDR::set_modeB(int val)
506 {
507 if (val >= (int)(sizeof(PowerSDR_mode_chr)/sizeof(*PowerSDR_mode_chr))) return;
508 _currmode = B.imode = val;
509 cmd = "MD";
510 cmd += PowerSDR_mode_chr[val];
511 cmd += ';';
512 sendCommand(cmd);
513 showresp(WARN, ASC, "set mode B", cmd, "");
514 sett("modeB");
515 MilliSleep(100); // give rig a chance to change width
516 B.iBW = set_widths(val);
517 vfoB.iBW = B.iBW;
518 }
519
get_modeB()520 int RIG_PowerSDR::get_modeB()
521 {
522 if (tuning()) return B.imode;
523 cmd = "ZZMD;";
524 if (wait_char(';', 4, 100, "get mode B", ASC) == 7) {
525 size_t p = replystr.rfind("MD");
526 if (p != string::npos) {
527 int md=0;
528 sscanf(&replystr[p+2],"%d",&md);
529 B.imode = md;
530 B.iBW = set_widths(B.imode);
531 }
532 }
533 _currmode = B.imode;
534 gett("modeB");
535 return B.imode;
536 }
537
adjust_bandwidth(int val)538 int RIG_PowerSDR::adjust_bandwidth(int val)
539 {
540 int bw = 0;
541 bw = 0;
542 if (val == CWU || val == CWL)
543 bw = 7;
544 return bw;
545 }
546
def_bandwidth(int val)547 int RIG_PowerSDR::def_bandwidth(int val)
548 {
549 return adjust_bandwidth(val);
550 }
551
set_bwA(int val)552 void RIG_PowerSDR::set_bwA(int val)
553 {
554 stringstream str;
555 if (A.imode == FM || A.imode == DRM || A.imode == SPEC) return; // mode is fixed
556 else if (A.imode == LSB || A.imode == USB) {
557 A.iBW = val;
558 if (val >= (int)(sizeof(PowerSDR_CAT_USB)/sizeof(*PowerSDR_CAT_USB))) return;
559 cmd = PowerSDR_CAT_USB[val];
560 sendCommand(cmd);
561 showresp(WARN, ASC, "set_bwA USB", cmd, "");
562 sett("bwA USB");
563 }
564 else if (A.imode == DIGU || A.imode == DIGL) {
565 A.iBW = val;
566 stringstream str;
567 str << "val =" << val ;
568 trace(2, __func__, str.str().c_str());
569 if (val >= (int)(sizeof(PowerSDR_CAT_DIG)/sizeof(*PowerSDR_CAT_DIG))) return;
570 cmd = PowerSDR_CAT_DIG[val];
571 sendCommand(cmd);
572 showresp(WARN, ASC, "set_bwA DIG", cmd, "");
573 sett("bwA DIG");
574 }
575 else if (A.imode == CWU || A.imode == CWL) {
576 A.iBW = val;
577 if (val >= (int)(sizeof(PowerSDR_CAT_CW)/sizeof(*PowerSDR_CAT_CW))) return;
578 cmd = PowerSDR_CAT_CW[val];
579 sendCommand(cmd);
580 showresp(WARN, ASC, "set_bwA CW", cmd, "");
581 sett("bwA CW");
582 }
583 else if (A.imode == AM || A.imode == SAM || A.imode == DSB) {
584 A.iBW = val;
585 if (val >= (int)(sizeof(PowerSDR_CAT_AM)/sizeof(*PowerSDR_CAT_AM))) return;
586 cmd = PowerSDR_CAT_AM[val];
587 sendCommand(cmd);
588 showresp(WARN, ASC, "set_bwA AM", cmd, "");
589 sett("bwA AM");
590 }
591 }
592
get_bwA()593 int RIG_PowerSDR::get_bwA()
594 {
595 size_t i = 0;
596 size_t p;
597 stringstream str;
598 str << "get_bwA" ;
599 A.iBW = 0;
600 trace(2, __func__, str.str().c_str());
601 if (A.imode == FM || A.imode == DRM || A.imode == SPEC) {
602 A.iBW = 0;
603 gett("get_bwA Wideband");
604 }
605 else if (A.imode == LSB || A.imode == USB) {
606 cmd = "ZZFI;";
607 if (wait_char(';', 7, 100, "get ZZFI", ASC) == 7) {
608 p = replystr.rfind("ZZFI");
609 if (p != string::npos) {
610 for (i = 0; PowerSDR_CAT_USB[i] != NULL; i++)
611 {
612 if (replystr.find(PowerSDR_CAT_USB[i]) == p)
613 break;
614 }
615 A.iBW = i;
616 }
617 }
618 gett("get_bwA USB");
619 }
620 else if (A.imode == CWL || A.imode == CWU) {
621 cmd = "ZZFI;";
622 if (wait_char(';', 7, 100, "get ZZFI", ASC) == 7) {
623 p = replystr.rfind("ZZFI");
624 if (p != string::npos) {
625 for (i = 0; PowerSDR_CAT_CW[i] != NULL; i++)
626 if (replystr.find(PowerSDR_CAT_CW[i]) == p)
627 break;
628 A.iBW = i;
629 }
630 }
631 gett("get_bwA CW");
632 }
633 else if (A.imode == DIGU || A.imode == DIGL) {
634 cmd = "ZZFI;";
635 if (wait_char(';', 7, 100, "get ZZFI", ASC) == 7) {
636 for (i = 0; PowerSDR_CAT_DIG[i] != NULL; i++) {
637 if (replystr.compare(PowerSDR_CAT_DIG[i]) == 0) {
638 break;
639 }
640 }
641 A.iBW = i;
642 }
643 gett("get_bwA DIG");
644 }
645 else if (A.imode == AM || A.imode == SAM || A.imode == DSB) {
646 cmd = "ZZFI;";
647 if (wait_char(';', 7, 100, "get ZZFI", ASC) == 7) {
648 p = replystr.rfind("ZZFI");
649 if (p != string::npos) {
650 for (i = 0; PowerSDR_CAT_AM[i] != NULL; i++)
651 if (replystr.find(PowerSDR_CAT_AM[i]) == p)
652 break;
653 A.iBW = i;
654 }
655 }
656 gett("get_bwA AM");
657 }
658 vfoA.iBW = A.iBW;
659 progStatus.iBW_A = A.iBW;
660 return A.iBW;
661 }
662
set_bwB(int val)663 void RIG_PowerSDR::set_bwB(int val)
664 {
665 set_bwA(val);
666 B.iBW = val;
667 stringstream str;
668 str << "B.iBW = " << B.iBW;
669 trace(2, __func__, str.str().c_str());
670 return;
671 }
672
get_bwB()673 int RIG_PowerSDR::get_bwB() // same as A
674 {
675 B.iBW = get_bwA();
676 stringstream str;
677 str << "B.iBW = " << B.iBW;
678 trace(2, __func__, str.str().c_str());
679 progStatus.iBW_B = B.iBW;
680 return B.iBW;
681 }
682
get_modetype(int n)683 int RIG_PowerSDR::get_modetype(int n)
684 {
685 if (n >= (int)(sizeof(PowerSDR_mode_type)/sizeof(*PowerSDR_mode_type))) return 0;
686 return PowerSDR_mode_type[n];
687 }
688
get_if_min_max_step(int & min,int & max,int & step)689 void RIG_PowerSDR::get_if_min_max_step(int &min, int &max, int &step)
690 {
691 if_shift_min = min = 400;
692 if_shift_max = max = 1000;
693 if_shift_step = step = 50;
694 if_shift_mid = 700;
695 }
696
set_notch(bool on,int val)697 void RIG_PowerSDR::set_notch(bool on, int val)
698 {
699 if (on) {
700 cmd = "BC2;"; // set manual notch
701 sendCommand(cmd);
702 showresp(WARN, ASC, "set notch on", cmd, "");
703 sett("notch ON");
704 cmd = "BP";
705 // val = round((val - 220) / 50);
706 val = round((val - 200) / 50);
707 cmd.append(to_decimal(val, 3)).append(";");
708 sendCommand(cmd);
709 showresp(WARN, ASC, "set notch val", cmd, "");
710 sett("notch val");
711 } else {
712 cmd = "BC0;"; // no notch action
713 sendCommand(cmd);
714 showresp(WARN, ASC, "set notch off", cmd, "");
715 sett("notch OFF");
716 }
717 }
718
get_notch(int & val)719 bool RIG_PowerSDR::get_notch(int &val)
720 {
721 bool ison = false;
722 cmd = "BC;";
723 if (wait_char(';', 4, 100, "get notch on/off", ASC) == 4) {
724 size_t p = replystr.rfind("BC");
725 if (p != string::npos) {
726 if (replystr[p+2] == '2') {
727 ison = true;
728 cmd = "BP;";
729 if (wait_char(';', 6, 100, "get notch val", ASC) == 6) {
730 gett("notch val");
731 p = replystr.rfind("BP");
732 if (p != string::npos)
733 val = 200 + 50 * fm_decimal(replystr.substr(p+2),3);
734 }
735 }
736 }
737 }
738 gett("notch on/off");
739 return (ison);
740 }
741
get_notch_min_max_step(int & min,int & max,int & step)742 void RIG_PowerSDR::get_notch_min_max_step(int &min, int &max, int &step)
743 {
744 min = 200;
745 max = 3350;
746 step = 50;
747 }
748
set_auto_notch(int v)749 void RIG_PowerSDR::set_auto_notch(int v)
750 {
751 cmd = v ? "NT1;" : "NT0;";
752 sendCommand(cmd);
753 showresp(WARN, ASC, "set auto notch", cmd, "");
754 sett("auto notch");
755 }
756
get_auto_notch()757 int RIG_PowerSDR::get_auto_notch()
758 {
759 int anotch = 0;
760 cmd = "NT;";
761 if (wait_char(';', 4, 100, "get auto notch", ASC) == 4) {
762 size_t p = replystr.rfind("NT");
763 if (p != string::npos) {
764 anotch = (replystr[p+2] == '1');
765 }
766 }
767 gett("auto notch");
768 return anotch;
769 }
770
set_noise_reduction(int val)771 void RIG_PowerSDR::set_noise_reduction(int val)
772 {
773 if (val == -1) {
774 return;
775 }
776 _noise_reduction_level = val;
777 if (_noise_reduction_level == 0) {
778 nr_label("ZZNR0", false);
779 } else if (_noise_reduction_level == 1) {
780 nr_label("ZZNR1", true);
781 } else {
782 nr_label("???", true);
783 return;
784 }
785 cmd.assign("ZZNR");
786 cmd += '0' + _noise_reduction_level;
787 cmd += ';';
788 sendCommand (cmd);
789 showresp(WARN, ASC, "SET noise reduction", cmd, "");
790 sett("noise reduction");
791 }
792
get_noise_reduction()793 int RIG_PowerSDR::get_noise_reduction()
794 {
795 cmd = rsp = "ZZNR";
796 cmd.append(";");
797 if (wait_char(';', 4, 100, "GET noise reduction", ASC) == 6) {
798 size_t p = replystr.rfind(rsp);
799 if (p == string::npos) return _noise_reduction_level;
800 _noise_reduction_level = replystr[p+4] - '0';
801 }
802
803 if (_noise_reduction_level == 1) {
804 nr_label("NR", true);
805 } else if (_noise_reduction_level == 2) {
806 nr_label("NR2", true);
807 } else {
808 nr_label("NR", false);
809 }
810 gett("nr level");
811 return _noise_reduction_level;
812 }
813
set_noise_reduction_val(int val)814 void RIG_PowerSDR::set_noise_reduction_val(int val)
815 {
816 if (_noise_reduction_level == 0) return;
817 if (_noise_reduction_level == 1) _nrval1 = val;
818 else _nrval2 = val;
819
820 cmd.assign("NR").append(to_decimal(val, 2)).append(";");
821 sendCommand(cmd);
822 showresp(WARN, ASC, "SET_noise_reduction_val", cmd, "");
823 sett("noise reduction val");
824 }
825
get_noise_reduction_val()826 int RIG_PowerSDR::get_noise_reduction_val()
827 {
828 int nrval = 0;
829 if (_noise_reduction_level == 0) return 0;
830 int val = progStatus.noise_reduction_val;
831 cmd = rsp = "ZZNR";
832 cmd.append(";");
833 if (wait_char(';', 5, 100, "GET noise reduction val", ASC) == 5) {
834 size_t p = replystr.rfind(rsp);
835 if (p == string::npos) {
836 nrval = (_noise_reduction_level == 1 ? _nrval1 : _nrval2);
837 return nrval;
838 }
839 val = atoi(&replystr[p+2]);
840 }
841 gett("noise reduction val");
842
843 if (_noise_reduction_level == 1) _nrval1 = val;
844 else _nrval2 = val;
845
846 return val;
847 }
848
tune_rig(int val)849 void RIG_PowerSDR::tune_rig(int val)
850 {
851
852 stringstream str;
853 str << "val=" << val;
854 trace(2, __func__, str.str().c_str());
855 switch (val) {
856 case 0:
857 cmd = "ZZTU0;";
858 break;
859 case 1:
860 case 2:
861 cmd = "ZZTU1;";
862 break;
863 }
864 sendCommand(cmd);
865 showresp(WARN, ASC, "tune rig", cmd, replystr);
866 sett("tune_rig");
867 }
868
get_tune()869 int RIG_PowerSDR::get_tune()
870 {
871 cmd = rsp = "ZZTU";
872 cmd += ';';
873 waitN(5, 100, "get tune", ASC);
874
875 rig_trace(2, "get_tuner status()", replystr.c_str());
876
877 size_t p = replystr.rfind(rsp);
878 if (p == string::npos) return 0;
879 int val = replystr[p+4] - '0';
880 return val;
881 }
882
883