1 // ----------------------------------------------------------------------------
2 // fmt_dialog.cxx -- fmt modem
3 //
4 // Copyright (C) 2020
5 // Dave Freese, W1HKJ
6 //
7 // This file is part of fldigi.
8 //
9 // Fldigi is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // Fldigi is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with fldigi. If not, see <http://www.gnu.org/licenses/>.
21 // ----------------------------------------------------------------------------
22
23 #include <iostream>
24
25 #include <FL/Fl_Box.H>
26
27 #include "configuration.h"
28 #include "confdialog.h"
29 #include "gettext.h"
30 #include "fmt_dialog.h"
31 #include "fmt.h"
32 #include "fl_digi.h"
33 #include "modem.h"
34 #include "status.h"
35
36 plot_xy *fmt_plot = (plot_xy *)0;
37
38 Fl_Group *ref_group = (Fl_Group *)0;
39 Fl_Light_Button *btn_ref_enable = (Fl_Light_Button *)0;
40 Fl_Button *btn_ref_up = (Fl_Button *)0;
41 Fl_Counter *cnt_ref_freq = (Fl_Counter *)0;
42 Fl_Button *btn_ref_dn = (Fl_Button *)0;
43 Fl_Button *btn_ref_reset = (Fl_Button *)0;
44 Fl_Button *btn_ref_clear = (Fl_Button *)0;
45 Fl_Output *fmt_ref_val = (Fl_Output *)0;
46 Fl_Output *fmt_ref_db = (Fl_Output *)0;
47 Fl_Box *ref_color = (Fl_Box *)0;
48
49 Fl_Group *unk_group = (Fl_Group *)0;
50 Fl_Light_Button *btn_unk_enable = (Fl_Light_Button *)0;
51 Fl_Button *btn_unk_up = (Fl_Button *)0;
52 Fl_Counter *cnt_unk_freq = (Fl_Counter *)0;
53 Fl_Button *btn_unk_dn = (Fl_Button *)0;
54 Fl_Button *btn_unk_reset = (Fl_Button *)0;
55 Fl_Button *btn_unk_clear = (Fl_Button *)0;
56 Fl_Output *fmt_unk_val = (Fl_Output *)0;
57 Fl_Output *fmt_unk_db = (Fl_Output *)0;
58 Fl_Box *unk_color = (Fl_Box *)0;
59
60 Fl_Light_Button *btn_fmt_record = (Fl_Light_Button *)0;
61 Fl_Box *box_fmt_recording = (Fl_Box *)0;
62
63 Fl_ListBox *fmt_rec_interval = (Fl_ListBox *)0;
64 Fl_ListBox *fmt_scale = (Fl_ListBox *)0;
65 Fl_ListBox *fmt_cntr_minutes = (Fl_ListBox *)0;
66
67 static const char *legend_p100 =
68 "-.010|-.008|-.006|-.004|-.002|0|.002|.004|.006|.008|.010";
69 static const char *legend_p50 =
70 "-0.05|-0.04|-0.03|-0.02|-0.01|0|0.01|0.02|0.03|0.04|0.05";
71 static const char *legend_p10 =
72 "-.10|-.08|-.06|-.04|-.02|0|.02|.04|.06|.08|.10";
73 static const char *legend_p25 =
74 "-0.25|-0.2|-0.15|-0.10|-0.05|0|0.05|0.10|0.15|0.20|0.25";
75 static const char *legend_p5 =
76 "-0.5|-0.4|-0.3|-0.2|-0.1|0|0.1|0.2|0.3|0.4|0.5";
77 static const char *legend_1p =
78 "-1.0|-0.8|-0.6|-0.4|-0.2|0|0.2|0.4|0.6|0.8|1.0";
79 static const char *legend_2p =
80 "-2.0|-1.5|-1.0|-0.5|0|0.5|1.0|1.5|2.0";
81 static const char *legend_4p =
82 "-4.0|-3.5|-3.0|-2.5|-2.0|-1.5|-1.0|-0.5|0|0.5|1.0|1.5|2.0|2.5|3.0|3.5|4.0";
83 static const char *legend_5p =
84 "5.0|-4.0|-3.0|-2.0|-1.0|0|1.0|2.0|3.0|4.0|5.0";
85 static const char *legend_10p =
86 "-10.0|-8.0|-6.0|-4.0|-2.0|0|2.0|4.0|6.0|8.0|10.0";
87
88 static const char *legend_5 = " |4|3|2|1| |";
89 static const char *legend_15 = " |14|13|12|11|10|9|8|7|6|5|4|3|2|1| |";
90 static const char *legend_30 = " |28|26|24|22|20|18|16|14|12|10|8|6|4|2| |";
91 static const char *legend_60 = " |55|50|45|40|35|30|25|20|15|10|5| |";
92 static const char *legend_120 = " |110|100|90|80|70|60|50|40|30|20|10| |";
93
94 static int seconds[5] = {300, 900, 1800, 3600, 7200};
95
cb_unk_up(void *)96 void cb_unk_up(void *)
97 {
98 double f = cnt_unk_freq->value () + 10;
99 if (f > 3000) f = 3000;
100 cnt_unk_freq->value (f);
101 cnt_unk_freq->callback ();
102 }
103
cb_unk_dn(void *)104 void cb_unk_dn(void *)
105 {
106 double f = cnt_unk_freq->value () - 10;
107 if (f < 100) f = 100;
108 cnt_unk_freq->value (f);
109 cnt_unk_freq->callback ();
110 }
111
cb_ref_up(void *)112 void cb_ref_up(void *)
113 {
114 double f = cnt_ref_freq->value () + 10;
115 if (f > 3000) f = 3000;
116 cnt_ref_freq->value (f);
117 cnt_ref_freq->callback ();
118 }
119
cb_ref_dn(void *)120 void cb_ref_dn(void *)
121 {
122 double f = cnt_ref_freq->value () - 10;
123 if (f < 100) f = 100;
124 cnt_ref_freq->value (f);
125 cnt_ref_freq->callback ();
126 }
127
cb_btn_fmt_record(void *)128 void cb_btn_fmt_record(void *)
129 {
130 write_recs = btn_fmt_record->value();
131 }
132
cb_btn_unk_enable(void *)133 void cb_btn_unk_enable(void *)
134 {
135 set_unk_freq(NULL);
136 record_unk = btn_unk_enable->value();
137 }
138
cb_btn_ref_enable(void *)139 void cb_btn_ref_enable(void *)
140 {
141 set_ref_freq(NULL);
142 record_ref = btn_ref_enable->value();
143 }
144
fmt_rec_interval_cb(void *)145 void fmt_rec_interval_cb(void *)
146 {
147 progStatus.FMT_rec_interval = fmt_rec_interval->index();
148 }
149
fmt_set_x_scale()150 void fmt_set_x_scale()
151 {
152 int minutes = 0;
153 int markers = 0;
154 const char *legend = NULL;
155
156 switch (progStatus.FMT_minutes) {
157 case 4: minutes = 120; markers = 12; legend = legend_120; break;
158 case 3: minutes = 60; markers = 12; legend = legend_60; break;
159 case 2: minutes = 30; markers = 15; legend = legend_30; break;
160 case 1: minutes = 15; markers = 15; legend = legend_15; break;
161 case 0:
162 default:
163 minutes = 5; markers = 5; legend = legend_5;
164 }
165 fmt_plot->x_scale (MAX_DATA_PTS - 60 * minutes, MAX_DATA_PTS, markers);
166 fmt_plot->set_x_legend (legend);
167 fmt_plot->thick_lines(progdefaults.FMT_thick_lines);
168 fmt_plot->plot_over_axis(progdefaults.FMT_plot_over_axis);
169 fmt_plot->redraw();
170 }
171
fmt_set_y_scale()172 void fmt_set_y_scale()
173 {
174 switch (progStatus.FMT_trk_scale) {
175
176 case 0 :
177 fmt_plot->y_scale(-0.01, 0.01, 10);
178 fmt_plot->set_y_legend(legend_p100);
179 break;
180 case 1 :
181 fmt_plot->y_scale(-0.05, .05, 10);
182 fmt_plot->set_y_legend(legend_p50);
183 break;
184 case 2 :
185 fmt_plot->y_scale(-0.10, 0.10, 10);
186 fmt_plot->set_y_legend(legend_p10);
187 break;
188 case 3 :
189 fmt_plot->y_scale(-0.25, .25, 10);
190 fmt_plot->set_y_legend(legend_p25);
191 break;
192 case 4 :
193 fmt_plot->y_scale(-0.5, .5, 10);
194 fmt_plot->set_y_legend(legend_p5);
195 break;
196 case 5 :
197 fmt_plot->y_scale(-1.0, 1.0, 10);
198 fmt_plot->set_y_legend(legend_1p);
199 break;
200 case 6 :
201 fmt_plot->y_scale(-2.0, 2.0, 8);
202 fmt_plot->set_y_legend(legend_2p);
203 break;
204 case 7 :
205 fmt_plot->y_scale(-4.0, 4.0, 16);
206 fmt_plot->set_y_legend(legend_4p);
207 break;
208 case 8 :
209 fmt_plot->y_scale(-5.0, 5.0, 10);
210 fmt_plot->set_y_legend(legend_5p);
211 break;
212 case 9 :
213 fmt_plot->y_scale(-10.0, 10.0, 10);
214 fmt_plot->set_y_legend(legend_10p);
215 break;
216 default:
217 fmt_plot->y_scale(-1.0, 1.0, 10);
218 fmt_plot->set_y_legend(legend_1p);
219 break;
220 }
221 fmt_plot->redraw();
222 }
223
fmt_scale_cb(void *)224 void fmt_scale_cb(void *)
225 {
226 progStatus.FMT_trk_scale = fmt_scale->index();
227 fmt_set_y_scale();
228 }
229
fmt_cntr_minutes_cb(void *)230 void fmt_cntr_minutes_cb(void *)
231 {
232 progStatus.FMT_minutes = fmt_cntr_minutes->index();
233 fmt_set_x_scale();
234 }
235
fmt_panel(int X,int Y,int W,int H)236 Fl_Group* fmt_panel(int X, int Y, int W, int H) {
237 Fl_Group* grp = new Fl_Group(X, Y, W, H);
238
239 int grp_height = 24;
240
241 fmt_plot = new plot_xy (
242 grp->x() + 2, grp->y() + 2,
243 grp->w() - 4, grp->h() - 4- 2 * grp_height, "");
244
245 fmt_plot->reverse_x(progdefaults.FMT_reverse);
246 fmt_plot->bk_color (progdefaults.FMT_background);
247 fmt_plot->line_color_1 (progdefaults.FMT_unk_color);
248 fmt_plot->line_color_2 (progdefaults.FMT_ref_color);
249 fmt_plot->axis_color (progdefaults.FMT_axis_color);
250 fmt_plot->legend_color (progdefaults.FMT_legend_color);
251 fmt_set_x_scale ();
252 fmt_set_y_scale ();
253 fmt_plot->show_1(false);
254 fmt_plot->show_2(false);
255
256 ref_group = new Fl_Group(
257 fmt_plot->x(), fmt_plot->y() + fmt_plot->h(),
258 fmt_plot->w(), 24);
259 ref_group->box(FL_ENGRAVED_BOX);
260
261 btn_unk_enable = new Fl_Light_Button(
262 ref_group->x() + 2, ref_group->y() + 2,
263 50, 20, "Unk'");
264 btn_unk_enable->selection_color(progdefaults.default_btn_color);
265 btn_unk_enable->callback((Fl_Callback *)cb_btn_unk_enable);
266
267 unk_color = new Fl_Box(
268 btn_unk_enable->x() + btn_unk_enable->w() + 2, btn_unk_enable->y() + 4,
269 12, 12, "");
270 unk_color->box(FL_DOWN_BOX);
271 unk_color->color(progdefaults.FMT_unk_color);
272
273 btn_unk_dn = new Fl_Button(
274 unk_color->x() + unk_color->w() + 2, btn_unk_enable->y(),
275 20, 20, "@|<");
276 btn_unk_dn->callback((Fl_Callback*)cb_unk_dn);
277
278 cnt_unk_freq = new Fl_Counter(
279 btn_unk_dn->x() + btn_unk_dn->w(), btn_unk_dn->y(),
280 120, 20, "");
281 cnt_unk_freq->minimum(100);
282 cnt_unk_freq->maximum(4000);
283 cnt_unk_freq->step(0.1);
284 cnt_unk_freq->lstep(1.0);
285 cnt_unk_freq->value(progStatus.FMT_unk_freq);
286 cnt_unk_freq->callback((Fl_Callback*)set_unk_freq);
287
288 btn_unk_up = new Fl_Button(
289 cnt_unk_freq->x() + cnt_unk_freq->w(), cnt_unk_freq->y(),
290 20, 20, "@>|");
291 btn_unk_up->callback((Fl_Callback*)cb_unk_up);
292
293 btn_unk_reset = new Fl_Button(
294 btn_unk_up->x() + btn_unk_up->w() + 2, btn_unk_up->y(),
295 50, 20, "Reset");
296 btn_unk_reset->callback((Fl_Callback*)cb_unk_reset);
297 btn_unk_reset->tooltip("Reset unknown frequency");
298
299 fmt_unk_val = new Fl_Output(
300 btn_unk_reset->x() + btn_unk_reset->w() + 4, btn_unk_enable->y(),
301 110, 20, "");
302 fmt_unk_val->value(0);
303
304 fmt_unk_db = new Fl_Output(
305 fmt_unk_val->x() + fmt_unk_val->w() + 6, btn_unk_enable->y(),
306 50, 20, "");
307 fmt_unk_db->value("");
308 fmt_unk_db->tooltip("amplitude in dBvp");
309
310 btn_unk_clear = new Fl_Button(
311 fmt_unk_db->x() + fmt_unk_db->w() + 6, fmt_unk_val->y(),
312 60, 20, "Clear");
313 btn_unk_clear->callback((Fl_Callback*)cb_unk_clear);
314 btn_unk_clear->tooltip("Clear unknown plot");
315
316 Fl_Group *dmy1 = new Fl_Group(
317 btn_unk_clear->x() + btn_unk_clear->w(), btn_unk_clear->y(),
318 1, btn_unk_clear->h());
319 dmy1->box(FL_FLAT_BOX);
320 dmy1->end();
321
322 btn_fmt_record = new Fl_Light_Button(
323 ref_group->x() + ref_group->w() - 84, dmy1->y(),
324 80, 20, "Record");
325 btn_fmt_record->callback((Fl_Callback *)cb_btn_fmt_record);
326
327 box_fmt_recording = new Fl_Box(
328 btn_fmt_record->x() - 20, btn_fmt_record->y() + 4,
329 12, 12, "");
330 box_fmt_recording->box(FL_DOWN_BOX);
331 box_fmt_recording->color(FL_WHITE);
332
333 fmt_rec_interval = new Fl_ListBox(
334 box_fmt_recording->x() - 110, btn_fmt_record->y(),
335 85, 20, "Interval");
336 fmt_rec_interval->align(FL_ALIGN_LEFT);
337 fmt_rec_interval->add("0.10 sec");
338 fmt_rec_interval->add("0.25 sec");
339 fmt_rec_interval->add("0.50 sec");
340 fmt_rec_interval->add("1.0 sec");
341 fmt_rec_interval->add("2.0 sec");
342 fmt_rec_interval->add("5.0 sec");
343 fmt_rec_interval->add("10.0 sec");
344 fmt_rec_interval->color(FL_WHITE);
345 fmt_rec_interval->index(progStatus.FMT_rec_interval);
346 fmt_rec_interval->callback((Fl_Callback *)fmt_rec_interval_cb);
347 fmt_rec_interval->tooltip(_("Record update every NN seconds"));
348
349 ref_group->end();
350 ref_group->resizable(dmy1);
351
352
353 unk_group = new Fl_Group(
354 ref_group->x(), ref_group->y() + ref_group->h(),
355 ref_group->w(), grp_height);
356 unk_group->box(FL_ENGRAVED_BOX);
357
358 btn_ref_enable = new Fl_Light_Button(
359 unk_group->x() + 2, unk_group->y() + 2,
360 50, 20, "Ref'");
361 btn_ref_enable->selection_color(progdefaults.default_btn_color);
362 btn_ref_enable->callback((Fl_Callback *)cb_btn_ref_enable);
363
364 ref_color = new Fl_Box(
365 btn_ref_enable->x() + btn_ref_enable->w() + 2, btn_ref_enable->y() + 4,
366 12, 12, "");
367 ref_color->box(FL_DOWN_BOX);
368 ref_color->color(progdefaults.FMT_ref_color);
369
370 btn_ref_dn = new Fl_Button(
371 unk_color->x() + unk_color->w() + 2, btn_ref_enable->y(),
372 20, 20, "@|<");
373 btn_ref_dn->callback((Fl_Callback*)cb_ref_dn);
374
375 cnt_ref_freq = new Fl_Counter(
376 cnt_unk_freq->x(), btn_ref_dn->y(),
377 120, 20, "");
378 cnt_ref_freq->minimum(100);
379 cnt_ref_freq->maximum(4000);
380 cnt_ref_freq->step(0.1);
381 cnt_ref_freq->lstep(1.0);
382 cnt_ref_freq->value(progStatus.FMT_ref_freq);
383 cnt_ref_freq->callback((Fl_Callback*)set_ref_freq);
384
385 btn_ref_up = new Fl_Button(
386 btn_unk_up->x(), cnt_ref_freq->y(),
387 20, 20, "@>|");
388 btn_ref_up->callback((Fl_Callback*)cb_ref_up);
389
390 btn_ref_reset = new Fl_Button(
391 btn_ref_up->x() + btn_ref_up->w() + 2, btn_ref_up->y(),
392 50, 20, "Reset");
393 btn_ref_reset->callback((Fl_Callback*)cb_ref_reset);
394 btn_ref_reset->tooltip("Reset unknown tracking frequency");
395
396 fmt_ref_val = new Fl_Output(
397 btn_ref_reset->x() + btn_ref_reset->w() + 2, btn_ref_reset->y(),
398 110, 20, "");
399 fmt_ref_val->value("");
400
401 fmt_ref_db = new Fl_Output(
402 fmt_unk_db->x(), fmt_ref_val->y(),
403 50, 20, "");
404 fmt_ref_db->value("");
405 fmt_ref_db->tooltip("amplitude in dBvp");
406
407 btn_ref_clear = new Fl_Button(
408 btn_unk_clear->x(), fmt_ref_val->y(),
409 60, 20, "Clear");
410 btn_ref_clear->callback((Fl_Callback*)cb_ref_clear);
411 btn_ref_clear->tooltip("Clear reference plot");
412
413 Fl_Group *dmy2 = new Fl_Group(
414 btn_ref_clear->x() + btn_ref_clear->w(), btn_ref_clear->y(),
415 1, btn_ref_clear->h());
416 dmy2->box(FL_FLAT_BOX);
417 dmy2->end();
418
419 fmt_scale = new Fl_ListBox(
420 unk_group->x() + unk_group->w() - 84, dmy2->y(),
421 80, 20, "Scale");
422 fmt_scale->align(FL_ALIGN_LEFT);
423 fmt_scale->add("+/- .01");
424 fmt_scale->add("+/- .05");
425 fmt_scale->add("+/- .10");
426 fmt_scale->add("+/- .25");
427 fmt_scale->add("+/- .5");
428 fmt_scale->add("+/- 1");
429 fmt_scale->add("+/- 2");
430 fmt_scale->add("+/- 4");
431 fmt_scale->add("+/- 5");
432 fmt_scale->add("-/- 10");
433 fmt_scale->color(FL_WHITE);
434 fmt_scale->index(progStatus.FMT_trk_scale);
435 fmt_scale->callback((Fl_Callback *)fmt_scale_cb);
436 fmt_scale->tooltip(_("Vertical scale of tracks"));
437
438 fmt_cntr_minutes = new Fl_ListBox(
439 fmt_scale->x() - 130, fmt_scale->y(),
440 85, 20, "T-scale");
441 fmt_cntr_minutes->align(FL_ALIGN_LEFT);
442 fmt_cntr_minutes->add("5 min");
443 fmt_cntr_minutes->add("15 min");
444 fmt_cntr_minutes->add("30 min");
445 fmt_cntr_minutes->add("60 min");
446 fmt_cntr_minutes->add("120 min");
447 fmt_cntr_minutes->color(FL_WHITE);
448 fmt_cntr_minutes->index(progStatus.FMT_minutes);
449 fmt_cntr_minutes->callback((Fl_Callback *)fmt_cntr_minutes_cb);
450 fmt_cntr_minutes->tooltip(_("Time scale span in minutes"));
451
452 unk_group->end();
453 unk_group->resizable(dmy2);
454
455 grp->end();
456 grp->resizable (fmt_plot);
457
458 return grp;
459 }
460
put_unk_value(const char * msg)461 void put_unk_value (const char *msg)
462 {
463 fmt_unk_val->value (msg);
464 }
465
put_ref_value(const char * msg)466 void put_ref_value (const char *msg)
467 {
468 fmt_ref_val->value (msg);
469 }
470
put_unk_amp(const char * msg)471 void put_unk_amp (const char *msg)
472 {
473 fmt_unk_db->value (msg);
474 }
475
put_ref_amp(const char * msg)476 void put_ref_amp (const char *msg)
477 {
478 fmt_ref_db->value (msg);
479 }
480
set_ref_freq(void *)481 void set_ref_freq (void *) {
482 progStatus.FMT_ref_freq = cnt_ref_freq->value();
483 wf->draw_fmt_marker();
484 active_modem->reset_reference();
485 }
486
set_unk_freq(void *)487 void set_unk_freq (void *) {
488 progStatus.FMT_unk_freq = cnt_unk_freq->value();
489 wf->draw_fmt_marker();
490 active_modem->reset_unknown();
491 }
492
set_unk_freq_value(double f)493 void set_unk_freq_value(double f)
494 {
495 cnt_unk_freq->value(f);
496 progStatus.FMT_unk_freq = f;
497 wf->draw_fmt_marker();
498 active_modem->reset_unknown();
499 }
500
set_ref_freq_value(double f)501 void set_ref_freq_value(double f)
502 {
503 cnt_ref_freq->value(f);
504 progStatus.FMT_ref_freq = f;
505 wf->draw_fmt_marker();
506 active_modem->reset_reference();
507 }
508
cb_unk_reset(void *)509 void cb_unk_reset (void *) {
510 active_modem->reset_unknown();
511 }
512
cb_unk_clear(void *)513 void cb_unk_clear (void *) {
514 fmt_modem->clear_unk_pipe();
515 fmt_plot->data_1(NULL, 0);
516 fmt_plot->redraw();
517 }
518
cb_ref_reset(void *)519 void cb_ref_reset (void *) {
520 active_modem->reset_reference();
521 }
522
cb_ref_clear(void *)523 void cb_ref_clear (void *) {
524 fmt_modem->clear_ref_pipe();
525 fmt_plot->data_2(NULL, 0);
526 fmt_plot->redraw();
527 }
528
set_fmt_scope()529 void set_fmt_scope()
530 {
531 guard_lock datalock (&scope_mutex);
532
533 int num_pts = seconds[progStatus.FMT_minutes];
534
535 fmt_plot->data_1 (&fmt_modem->unk_pipe[MAX_DATA_PTS - num_pts], num_pts);
536 fmt_plot->data_2 (&fmt_modem->ref_pipe[MAX_DATA_PTS - num_pts], num_pts);
537
538 fmt_plot->redraw();
539
540 }
541
clear_ref_scope()542 void clear_ref_scope()
543 {
544 fmt_plot->data_2 (&fmt_modem->ref_pipe[MAX_DATA_PTS], MAX_DATA_PTS);
545 fmt_plot->redraw();
546 Fl::flush();
547 }
548
clear_unk_scope()549 void clear_unk_scope()
550 {
551 fmt_plot->data_1 (&fmt_modem->ref_pipe[MAX_DATA_PTS], MAX_DATA_PTS);
552 fmt_plot->redraw();
553 Fl::flush();
554 }
555
556