1 // ----------------------------------------------------------------------------
2 // rigsupport.cxx - support functions file
3 //
4 // Copyright (C) 2007-2009
5 // Dave Freese, W1HKJ
6 // Copyright (C) 2008-2009
7 // Stelios Bounanos, M0GLD
8 //
9 // This file is part of fldigi.
10 //
11 // Fldigi is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // Fldigi is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with fldigi. If not, see <http://www.gnu.org/licenses/>.
23 // ----------------------------------------------------------------------------
24
25 #include <config.h>
26
27 #include <fstream>
28 #include <sstream>
29 #include <vector>
30 #include <list>
31 #include <map>
32 #include <algorithm>
33 #include <iterator>
34 #include <cstring>
35
36 #include "rigsupport.h"
37 #include "rigxml.h"
38 #include "rigio.h"
39
40 #include "threads.h"
41 #include "main.h"
42 #include "fl_digi.h"
43 #include "trx.h"
44
45 #include "configuration.h"
46
47 #include "globals.h"
48
49 #include "debug.h"
50
51 #include "gettext.h"
52
53 extern void n3fjp_set_freq(long);
54 extern bool n3fjp_connected;
55
56 LOG_FILE_SOURCE(debug::LOG_RIGCONTROL);
57
58 using namespace std;
59
60 string windowTitle;
61
62 vector<qrg_mode_t> freqlist;
63
64 const unsigned char nfields = 5;//4;
65 int fwidths[nfields];
66 enum { max_rfcarrier, max_rmode, max_mode, max_carrier };
67
68 #if !USE_HAMLIB
69
70 typedef enum {
71 RIG_MODE_NONE = 0, /*!< '' -- None */
72 RIG_MODE_AM = (1<<0), /*!< \c AM -- Amplitude Modulation */
73 RIG_MODE_CW = (1<<1), /*!< \c CW -- CW "normal" sideband */
74 RIG_MODE_USB = (1<<2), /*!< \c USB -- Upper Side Band */
75 RIG_MODE_LSB = (1<<3), /*!< \c LSB -- Lower Side Band */
76 RIG_MODE_RTTY = (1<<4), /*!< \c RTTY -- Radio Teletype */
77 RIG_MODE_FM = (1<<5), /*!< \c FM -- "narrow" band FM */
78 RIG_MODE_WFM = (1<<6), /*!< \c WFM -- broadcast wide FM */
79 RIG_MODE_CWR = (1<<7), /*!< \c CWR -- CW "reverse" sideband */
80 RIG_MODE_RTTYR = (1<<8), /*!< \c RTTYR -- RTTY "reverse" sideband */
81 RIG_MODE_AMS = (1<<9), /*!< \c AMS -- Amplitude Modulation Synchronous */
82 RIG_MODE_PKTLSB = (1<<10),/*!< \c PKTLSB -- Packet/Digital LSB mode (dedicated port) */
83 RIG_MODE_PKTUSB = (1<<11),/*!< \c PKTUSB -- Packet/Digital USB mode (dedicated port) */
84 RIG_MODE_PKTFM = (1<<12),/*!< \c PKTFM -- Packet/Digital FM mode (dedicated port) */
85 RIG_MODE_ECSSUSB = (1<<13),/*!< \c ECSSUSB -- Exalted Carrier Single Sideband USB */
86 RIG_MODE_ECSSLSB = (1<<14),/*!< \c ECSSLSB -- Exalted Carrier Single Sideband LSB */
87 RIG_MODE_FAX = (1<<15),/*!< \c FAX -- Facsimile Mode */
88 RIG_MODE_SAM = (1<<16),/*!< \c SAM -- Synchronous AM double sideband */
89 RIG_MODE_SAL = (1<<17),/*!< \c SAL -- Synchronous AM lower sideband */
90 RIG_MODE_SAH = (1<<18),/*!< \c SAH -- Synchronous AM upper (higher) sideband */
91 RIG_MODE_DSB = (1<<19), /*!< \c DSB -- Double sideband suppressed carrier */
92 } rmode_t;
93
94 #endif
95
96 struct rmode_name_t {
97 rmode_t mode;
98 const char *name;
99 } modes[] = {
100 { RIG_MODE_NONE, "NONE" },
101 { RIG_MODE_AM, "AM" },
102 { RIG_MODE_CW, "CW" },
103 { RIG_MODE_USB, "USB" },
104 { RIG_MODE_LSB, "LSB" },
105 { RIG_MODE_RTTY, "RTTY" },
106 { RIG_MODE_FM, "FM" },
107 { RIG_MODE_WFM, "WFM" },
108 { RIG_MODE_CWR, "CWR" },
109 { RIG_MODE_RTTYR, "RTTYR" },
110 { RIG_MODE_AMS, "AMS" },
111 { RIG_MODE_PKTLSB, "PKTLSB" },
112 { RIG_MODE_PKTUSB, "PKTUSB" },
113 { RIG_MODE_PKTFM, "PKTFM" }
114 //, // C99 trailing commas in enumerations not yet in the C++ standard
115 // { RIG_MODE_ECSSUSB, "ECSSUSB" },
116 // { RIG_MODE_ECSSLSB, "ECSSLSB" },
117 // { RIG_MODE_FAX, "FAX" }
118 // the above are covered by our requirement that hamlib be >= 1.2.4
119 #if (defined(RIG_MODE_SAM) && defined(RIG_MODE_SAL) && defined(RIG_MODE_SAH))
120 , // C99 trailing commas in enumerations not yet in the C++ standard
121 { RIG_MODE_SAM, "SAM" },
122 { RIG_MODE_SAL, "SAL" },
123 { RIG_MODE_SAH, "SAH" }
124 #endif
125 };
126
127 map<string, rmode_t> mode_nums;
128 map<rmode_t, string> mode_names;
129
qso_selMode(rmode_t m)130 void qso_selMode(rmode_t m)
131 {
132 qso_opMODE->value(mode_names[m].c_str());
133 }
134
modeString(rmode_t m)135 string modeString(rmode_t m)
136 {
137 return mode_names[m].c_str();
138 }
139
initOptionMenus()140 void initOptionMenus()
141 {
142 qso_opMODE->clear();
143
144 list<MODE>::iterator MD;
145 list<MODE> *pMD = 0;
146
147 if (lmodes.empty() == false)
148 pMD = &lmodes;
149 else if (lmodeCMD.empty() == false)
150 pMD = &lmodeCMD;
151 //printf("initOptionMenus()\n");
152 if (pMD) {
153 MD = pMD->begin();
154 while (MD != pMD->end()) {
155 //printf("adding mode: %s\n", (*MD).SYMBOL.c_str());
156 qso_opMODE->add( (*MD).SYMBOL.c_str());
157 MD++;
158 }
159 qso_opMODE->activate();
160 qso_opMODE->index(0);
161 }
162 else {
163 qso_opMODE->deactivate();
164 }
165
166 qso_opBW->clear();
167 list<BW>::iterator bw;
168 list<BW> *pBW = 0;
169 if (lbws.empty() == false)
170 pBW = &lbws;
171 else if (lbwCMD.empty() == false)
172 pBW = &lbwCMD;
173
174 if (pBW) {
175 bw = pBW->begin();
176 while (bw != pBW->end()) {
177 //printf("adding BW: %s\n", (*bw).SYMBOL.c_str());
178 qso_opBW->add( (*bw).SYMBOL.c_str());
179 bw++;
180 }
181 qso_opBW->activate();
182 qso_opBW->index(0);
183 }
184 else {
185 qso_opBW->deactivate();
186 }
187 }
188
clearList()189 void clearList()
190 {
191 freqlist.clear();
192 qso_opBrowser->clear();
193 }
194
updateSelect()195 void updateSelect()
196 {
197 if (freqlist.empty())
198 return;
199 for (size_t i = 0; i < freqlist.size(); i++) {
200 qso_opBrowser->add(freqlist[i].str().c_str());
201 }
202 }
203
updateList(long rf,int freq,string rmd,trx_mode md,string usage="")204 size_t updateList(long rf, int freq, string rmd, trx_mode md, string usage = "")
205 {
206 qrg_mode_t m;
207 m.rmode = rmd;
208 m.mode = md;
209 m.rfcarrier = rf;
210 m.carrier = freq;
211 m.usage = usage;
212
213 freqlist.push_back(m);
214 sort(freqlist.begin(), freqlist.end());
215
216 vector<qrg_mode_t>::const_iterator pos = find(freqlist.begin(), freqlist.end(), m);
217 if (pos != freqlist.end())
218 return pos - freqlist.begin();
219 else
220 return 0;
221
222 }
223
addtoList(long val)224 size_t addtoList(long val)
225 {
226 qrg_mode_t m;
227
228 m.rfcarrier = val;
229
230 if (strlen(qso_opMODE->value()))
231 m.rmode = qso_opMODE->value();
232
233 if (active_modem) {
234 m.carrier = active_modem->get_freq();
235 m.mode = active_modem->get_mode();
236 }
237 return updateList(val, m.carrier, m.rmode, m.mode);
238 }
239
readFreqList()240 bool readFreqList()
241 {
242 ifstream freqfile((HomeDir + "frequencies2.txt").c_str());
243 if (!freqfile) {
244 LOG_ERROR("Could not open %s", (HomeDir + "frequencies2.txt").c_str());
245 return false;
246 }
247
248 string line;
249 qrg_mode_t m;
250 while (!getline(freqfile, line).eof()) {
251 LOG_INFO("%s", line.c_str());
252 if (line[0] == '#')
253 continue;
254 istringstream is(line);
255 is >> m;
256 freqlist.push_back(m);
257 }
258 sort(freqlist.begin(), freqlist.end());
259 updateSelect();
260
261 freqfile.close();
262
263 return freqlist.size();
264 }
265
saveFreqList()266 void saveFreqList()
267 {
268 if (freqlist.empty()) return;
269
270 ofstream freqfile((HomeDir + "frequencies2.txt").c_str());
271 if (!freqfile) {
272 LOG_ERROR("Could not open %s", (HomeDir + "frequencies2.txt").c_str());
273 return;
274 }
275 freqfile << "# rfcarrier rig_mode carrier mode usage\n";
276
277 copy( freqlist.begin(),
278 freqlist.end(),
279 ostream_iterator<qrg_mode_t>(freqfile, "\n") );
280
281 freqfile.close();
282 }
283
build_frequencies2_list()284 void build_frequencies2_list()
285 {
286 if (!freqlist.empty()) saveFreqList();
287
288 clearList();
289 // calculate the column widths
290 memset(fwidths, 0, sizeof(fwidths));
291 // these need to be a little wider than fl_width thinks
292 fwidths[max_rmode] = fwidths[max_mode] =
293 fwidths[max_carrier] = fwidths[max_rfcarrier]= 15;
294
295 fwidths[max_rfcarrier] += (int)ceil(fl_width("999999.999"));
296
297 fwidths[max_rmode] += (int)ceil(fl_width("XXXXXX"));
298
299 fwidths[max_carrier] += (int)ceil(fl_width("8888"));
300
301 // find mode with longest shortname
302 size_t s, smax = 0, mmax = 0;
303 for (size_t i = 0; i < NUM_MODES; i++) {
304 s = strlen(mode_info[i].sname);
305 if (smax < s) {
306 smax = s;
307 mmax = i;
308 }
309 }
310 fwidths[max_mode] += (int)ceil(fl_width(mode_info[mmax].sname));
311
312 if (readFreqList() == true)
313 return;
314
315 updateList (1807000L, 1000, "USB", MODE_PSK31 );
316 updateList (3505000L, 800, "USB", MODE_CW);
317 updateList (3580000L, 1000, "USB", MODE_PSK31 );
318 updateList (1000500L, 800, "USB", MODE_CW);
319 updateList (10135000L, 1000, "USB", MODE_PSK31 );
320 updateList (7005000L, 800, "USB", MODE_CW);
321 updateList (7030000L, 1000, "USB", MODE_PSK31 );
322 updateList (7070000L, 1000, "USB", MODE_PSK31 );
323 updateList (14005000L, 800, "USB", MODE_CW);
324 updateList (14070000L, 1000, "USB", MODE_PSK31 );
325 updateList (18100000L, 1000, "USB", MODE_PSK31 );
326 updateList (21005000L, 800, "USB", MODE_CW);
327 updateList (21070000L, 1000, "USB", MODE_PSK31 );
328 updateList (24920000L, 1000, "USB", MODE_PSK31 );
329 updateList (28005000L, 800, "USB", MODE_CW);
330 updateList (28120000, 1000, "USB", MODE_PSK31 );
331 updateSelect();
332
333 }
334
cb_qso_opMODE()335 int cb_qso_opMODE()
336 {
337 if (connected_to_flrig) {
338 set_flrig_mode(qso_opMODE->value());
339 return 0;
340 }
341 #if USE_HAMLIB
342 if (progdefaults.chkUSEHAMLIBis)
343 hamlib_setmode(mode_nums[qso_opMODE->value()]);
344 else
345 #endif
346 if (progdefaults.chkUSERIGCATis)
347 rigCAT_setmode(qso_opMODE->value());
348 else
349 noCAT_setmode(qso_opMODE->value());
350 return 0;
351 }
352
cb_qso_opBW()353 int cb_qso_opBW()
354 {
355 if (connected_to_flrig)
356 set_flrig_bw(qso_opBW->index(), -1);
357 else if (progdefaults.chkUSERIGCATis)
358 rigCAT_setwidth(qso_opBW->value());
359 else
360 noCAT_setwidth(qso_opBW->value());
361 return 0;
362 }
363
cb_qso_btnBW1()364 int cb_qso_btnBW1()
365 {
366 qso_btnBW1->hide();
367 qso_opBW1->hide();
368 qso_btnBW2->show();
369 qso_opBW2->show();
370 return 0;
371 }
372
cb_qso_btnBW2()373 int cb_qso_btnBW2()
374 {
375 qso_btnBW2->hide();
376 qso_opBW2->hide();
377 qso_btnBW1->show();
378 qso_opBW1->show();
379 return 0;
380 }
381
cb_qso_opBW1()382 int cb_qso_opBW1()
383 {
384 //printf("opBW1 %d:%s\n", qso_opBW1->index(), qso_opBW1->value());
385 set_flrig_bw(qso_opBW2->index(), qso_opBW1->index());
386 return 0;
387 }
388
cb_qso_opBW2()389 int cb_qso_opBW2()
390 {
391 //printf("opBW2 %d:%s\n", qso_opBW2->index(), qso_opBW2->value());
392 set_flrig_bw(qso_opBW2->index(), qso_opBW1->index());
393 return 0;
394 }
395
sendFreq(long int f)396 void sendFreq(long int f)
397 {
398 if (connected_to_flrig)
399 set_flrig_freq(f);
400 #if USE_HAMLIB
401 else if (progdefaults.chkUSEHAMLIBis)
402 hamlib_setfreq(f);
403 #endif
404 else if (progdefaults.chkUSERIGCATis)
405 rigCAT_setfreq(f);
406 else
407 noCAT_setfreq(f);
408
409 if (n3fjp_connected)
410 n3fjp_set_freq(f);
411 }
412
qso_movFreq(Fl_Widget * w,void * data)413 void qso_movFreq(Fl_Widget* w, void *data)
414 {
415 cFreqControl *fc = (cFreqControl *)w;
416 long int f;
417 long restore = reinterpret_cast<intptr_t>(data);
418 f = fc->value();
419 if (fc == qsoFreqDisp1) {
420 qsoFreqDisp2->value(f);
421 qsoFreqDisp3->value(f);
422 } else if (fc == qsoFreqDisp2) {
423 qsoFreqDisp1->value(f);
424 qsoFreqDisp3->value(f);
425 } else {
426 qsoFreqDisp1->value(f);
427 qsoFreqDisp2->value(f);
428 }
429
430 sendFreq(f);
431 if (restore == 1)
432 restoreFocus();
433 return;
434 }
435
qso_selectFreq(long int rfcarrier,int carrier)436 void qso_selectFreq(long int rfcarrier, int carrier)
437 {
438 if (rfcarrier > 0) {
439 qsoFreqDisp1->value(rfcarrier);
440 qsoFreqDisp2->value(rfcarrier);
441 qsoFreqDisp3->value(rfcarrier);
442 sendFreq(rfcarrier);
443 }
444
445 if (carrier > 0) {
446 active_modem->set_freq(carrier);
447 }
448 }
449
qso_selectFreq()450 void qso_selectFreq()
451 {
452 int n = qso_opBrowser->value();
453 if (!n) return;
454
455 n -= 1;
456 // transceiver mode
457 if (freqlist[n].rmode != "NONE") {
458 qso_opMODE->value(freqlist[n].rmode.c_str());
459 cb_qso_opMODE();
460 }
461 // transceiver frequency
462 if (freqlist[n].rfcarrier > 0) {
463 qsoFreqDisp1->value(freqlist[n].rfcarrier);
464 qsoFreqDisp2->value(freqlist[n].rfcarrier);
465 qsoFreqDisp3->value(freqlist[n].rfcarrier);
466 sendFreq(freqlist[n].rfcarrier);
467 }
468 // modem type & audio sub carrier
469 if (freqlist[n].mode != NUM_MODES) {
470 if (freqlist[n].mode != active_modem->get_mode())
471 init_modem_sync(freqlist[n].mode);
472 if (freqlist[n].carrier > 0)
473 active_modem->set_freq(freqlist[n].carrier);
474 }
475 }
476
qso_setFreq(long int f)477 void qso_setFreq(long int f)
478 {
479 // transceiver frequency
480 if (f > 0) {
481 qsoFreqDisp->value(f);
482 sendFreq(f);
483 }
484 }
485
qso_setFreq()486 void qso_setFreq()
487 {
488 int n = qso_opBrowser->value();
489 if (!n) return;
490
491 n -= 1;
492 // transceiver frequency
493 qso_setFreq(freqlist[n].rfcarrier);
494 }
495
qso_delFreq()496 void qso_delFreq()
497 {
498 int v = qso_opBrowser->value() - 1;
499
500 if (v >= 0) {
501 freqlist.erase(freqlist.begin() + v);
502 qso_opBrowser->remove(v + 1);
503 }
504 }
505
qso_addFreq()506 void qso_addFreq()
507 {
508 long freq = qsoFreqDisp->value();
509 if (freq) {
510 size_t pos = addtoList(freq);
511 qso_opBrowser->insert(pos+1, freqlist[pos].str().c_str());
512 }
513 }
514
qso_updateEntry(int i,std::string usage)515 void qso_updateEntry(int i, std::string usage)
516 {
517 int v = i - 1;
518 int sz = (int)freqlist.size();
519 if ((v >= 0) && (v < sz)) {
520 freqlist[v].usage = usage;
521 }
522 }
523
setTitle()524 void setTitle()
525 {
526 update_main_title();
527 }
528
init_Xml_RigDialog()529 bool init_Xml_RigDialog()
530 {
531 LOG_DEBUG("xml rig");
532 initOptionMenus();
533 xcvr_title = xmlrig.rigTitle;
534 setTitle();
535 return true;
536 }
537
init_NoRig_RigDialog()538 bool init_NoRig_RigDialog()
539 {
540 LOG_DEBUG("no rig");
541 qso_opBW->clear();
542 qso_opBW->add(" ");
543 qso_opBW->index(0);
544 qso_opBW->redraw();
545 qso_opBW->deactivate();
546 qso_opMODE->clear();
547
548 //printf("init_NoRig_RigDialog()\n");
549 for (size_t i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
550 //printf("adding %s\n", modes[i].name);
551 qso_opMODE->add(modes[i].name);
552 }
553 // list of LSB type modes that various xcvrs report via flrig
554 LSBmodes.clear();
555 LSBmodes.push_back("LSB");
556 LSBmodes.push_back("LSB-D");
557 LSBmodes.push_back("LSB-D1");
558 LSBmodes.push_back("LSB-D2");
559 LSBmodes.push_back("LSB-D3");
560 LSBmodes.push_back("CW");
561 LSBmodes.push_back("LCW");
562 LSBmodes.push_back("CW-N");
563 LSBmodes.push_back("CWL");
564 LSBmodes.push_back("RTTY");
565 LSBmodes.push_back("RTTY-L");
566 LSBmodes.push_back("PKTLSB");
567 LSBmodes.push_back("PKT-L");
568 LSBmodes.push_back("USER-L");
569 LSBmodes.push_back("DATA-L");
570 LSBmodes.push_back("DATA");
571 LSBmodes.push_back("D-LSB");
572
573 qso_opMODE->index(3);
574 qso_opMODE->activate();
575
576 xcvr_title.clear();
577 setTitle();
578
579 return true;
580 }
581
582 #if USE_HAMLIB
init_Hamlib_RigDialog()583 bool init_Hamlib_RigDialog()
584 {
585 LOG_DEBUG("hamlib");
586
587 qso_opBW->deactivate();
588 qso_opMODE->clear();
589
590 for (size_t i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
591 mode_nums[modes[i].name] = modes[i].mode;
592 mode_names[modes[i].mode] = modes[i].name;
593 qso_opMODE->add(modes[i].name);
594 }
595
596 xcvr_title = "Hamlib ";
597 xcvr_title.append(xcvr->getName());
598
599 setTitle();
600
601 return true;
602 }
603 #endif
604