1 // Copyright (c) <2012> <Leif Asbrink>
2 //
3 // Permission is hereby granted, free of charge, to any person
4 // obtaining a copy of this software and associated documentation
5 // files (the "Software"), to deal in the Software without restriction,
6 // including without limitation the rights to use, copy, modify,
7 // merge, publish, distribute, sublicense, and/or sell copies of
8 // the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
22
23
24 #define YBO 8
25 #define YWF 4
26
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include "globdef.h"
30 #include "uidef.h"
31 #include "fft1def.h"
32 #include "fft2def.h"
33 #include "screendef.h"
34 #include "seldef.h"
35 #include "graphcal.h"
36 #include "vernr.h"
37 #include "sigdef.h"
38 #include "rusage.h"
39 #include "thrdef.h"
40
41 int wide_graph_scro;
42 int wg_old_y1;
43 int wg_old_y2;
44 int wg_old_x1;
45 int wg_old_x2;
46
make_wg_fqlimits(void)47 void make_wg_fqlimits(void)
48 {
49 wg_lowest_freq=0.000001*wg_first_frequency+0.1*frequency_scale_offset;
50 wg_highest_freq=wg_lowest_freq+0.000001*wg.xpoints*fft1_hz_per_point;
51 }
52
wg_check_mix1(int i0)53 float wg_check_mix1(int i0)
54 {
55 int i,k;
56 float t1;
57 i=mouse_x;
58 if(i<wg_first_xpixel)i=wg_first_xpixel;
59 if(i>wg_last_xpixel)i=wg_last_xpixel;
60 t1=wg_first_frequency+(float)(i-wg_first_xpixel)*wg_hz_per_pixel;
61 if(t1 < mix1_lowest_fq)t1=mix1_lowest_fq;
62 if(t1 > mix1_highest_fq)t1=mix1_highest_fq;
63 k=0;
64 for(i=i0; i<genparm[MIX1_NO_OF_CHANNELS]; i++)
65 {
66 if( fabs(t1-mix1_selfreq[i]) < 3*wg_hz_per_pixel)
67 {
68 new_mix1_curx[i]=-1;
69 k++;
70 mix1_selfreq[i]=-1;
71 mix1_point[i]=-1;
72 }
73 }
74 if(k>0 && i0==0)return -(float)BIG;
75 return t1;
76 }
77
78
wide_graph_selfreq(void)79 void wide_graph_selfreq(void)
80 {
81 int post;
82 float t1;
83 new_mix1_curx[0]=-1;
84 t1=wg_check_mix1(1);
85 post=make_new_signal(0, t1);
86 if(post)
87 {
88 sc[SC_FREQ_READOUT]++;
89 if(genparm[SECOND_FFT_ENABLE] != 0)sc[SC_HG_FQ_SCALE]++;
90 if(genparm[AFC_ENABLE]==0)sc[SC_BG_FQ_SCALE]++;
91 }
92 if(leftpressed != BUTTON_RELEASED)
93 {
94 if(post)lir_set_event(EVENT_SCREEN);
95 return;
96 }
97 if(post)
98 {
99 if(genparm[AFC_ENABLE]!=0)sc[SC_BG_FQ_SCALE]++;
100 lir_set_event(EVENT_SCREEN);
101 }
102 leftpressed=BUTTON_IDLE;
103 baseb_reset_counter++;
104 mouse_active_flag=0;
105 }
106
add_mix1_cursor(int num)107 void add_mix1_cursor(int num)
108 {
109 if(mix1_selfreq[num]<wg_first_frequency)
110 {
111 new_mix1_curx[num]=(int)wg_first_frequency;
112 return;
113 }
114 new_mix1_curx[num]=(int)(0.5F+(float)wg_first_xpixel+
115 (mix1_selfreq[num]-wg_first_frequency)/wg_hz_per_pixel);
116 if(new_mix1_curx[num] > wg_last_xpixel)
117 {
118 new_mix1_curx[num]=wg_last_xpixel;
119 }
120 }
121
make_new_signal(int i,float t1)122 int make_new_signal(int i,float t1)
123 {
124 int retcod;
125 if(mix1_selfreq[i]==t1)
126 {
127 retcod=FALSE;
128 }
129 else
130 {
131 retcod=TRUE;
132 mix1_selfreq[i]=t1;
133 }
134 mix1_point[i]=-1;
135 add_mix1_cursor(i);
136 return retcod;
137 }
138
step_rx_frequency(int direction)139 void step_rx_frequency(int direction)
140 {
141 float t1, t2;
142 int m;
143 if(mix1_selfreq[0] < 0 || ag.mode_control != 0)return;
144 if(genparm[AFC_ENABLE]==0 || rx_mode >= MODE_SSB)
145 {
146 m=1<<bg.wheel_stepn;
147 t1=mix1_selfreq[0];
148 t2=(float)direction*((float)m/fftx_points_per_hz)/256;
149 t1+=t2;
150 if(t1<=mix1_lowest_fq)return;
151 if(t1>=mix1_highest_fq)return;
152 unconditional_hide_mouse();
153 switch (bg.horiz_arrow_mode)
154 {
155 case 0:
156 mix1_selfreq[0]=t1;
157 add_mix1_cursor(0);
158 sc[SC_SHOW_CENTER_FQ]++;
159 break;
160
161 case 1:
162 mix1_selfreq[0]=t1;
163 add_mix1_cursor(0);
164 sc[SC_SHOW_CENTER_FQ]++;
165 clear_bfo();
166 bg.bfo_freq-=t2;
167 make_bfo();
168 break;
169
170 case 2:
171 clear_bfo();
172 bg.bfo_freq-=t2;
173 make_bfo();
174 break;
175 }
176 }
177 }
178
179
mouse_continue_wide_graph_rightpressed(void)180 void mouse_continue_wide_graph_rightpressed(void)
181 {
182 int iymax;
183 int jw, iy, i, ix,color;
184 int maxpos, maxval, total;
185 float t1;
186 #define MAX_OCCURANCES 3*MAX_COLOR_SCALE
187 int occurances[MAX_OCCURANCES];
188 int last_valid;
189 last_valid=0;
190 if(rightpressed != BUTTON_RELEASED)return;
191 switch (mouse_active_flag-1)
192 {
193 case WG_WATERF_ZERO:
194 if(recent_time-wg_waterf_zero_time > 1)
195 {
196 for(i=0; i<MAX_OCCURANCES; i++)occurances[i]=0;
197 wg_waterf_zero_time=current_time();
198 iy=wg_waterf_y;
199 iymax=wg_waterf_y+wg_waterf_lines-wg_waterf_yinc;
200 jw=wg_waterf_ptr2;
201 while(iy < iymax)
202 {
203 i=wg_first_xpixel;
204 ix=0;
205 while(ix<wg_xpixels && i<screen_width)
206 {
207 color=(int)(MAX_COLOR_SCALE+wg_waterf_cfac*
208 ((float)wg_waterf[jw+ix]-(float)wg_waterf_czer));
209 ix++;
210 if(color<0)
211 {
212 color=0;
213 }
214 else
215 {
216 if(color >= MAX_OCCURANCES)color=MAX_OCCURANCES-1;
217 }
218 occurances[color]++;
219 if(color != 0)last_valid=occurances[0];
220 i++;
221 }
222 iy++;
223 jw+=wg_xpixels;
224 if(jw > wg_waterf_size-wg_xpixels-1)jw=0;
225 }
226 if(last_valid == 0)last_valid=1;
227 occurances[0]=last_valid;
228 maxpos=-1;
229 maxval=0;
230 total=0;
231 for(i=0; i<MAX_OCCURANCES-2; i++)
232 {
233 if(occurances[i]>maxval)
234 {
235 maxval=occurances[i];
236 maxpos=i;
237 }
238 total+=occurances[i];
239 }
240 if(maxpos==-1 || maxpos== 3)break;
241 if(occurances[MAX_OCCURANCES-1] > 1.5*total)
242 {
243 maxpos=MAX_COLOR_SCALE-1;
244 }
245 if(maxpos == 0)
246 {
247 // The waterfall is black.
248 wg.waterfall_db_zero-=0.01F*(float)MAX_COLOR_SCALE/wg_waterf_cfac;
249 }
250 else
251 {
252 if(maxpos == MAX_COLOR_SCALE-1)
253 {
254 // The waterfall is white.
255 wg.waterfall_db_zero+=0.01F*(float)MAX_COLOR_SCALE/wg_waterf_cfac;
256 }
257 else
258 {
259 wg.waterfall_db_zero+=.01F*(float)(maxpos-MAX_COLOR_SCALE-3)/
260 wg_waterf_cfac;
261 }
262 }
263 make_modepar_file(GRAPHTYPE_WG);
264 sc[SC_WG_WATERF_REDRAW]++;
265 }
266 break;
267
268 case WG_FREQ_ADJUSTMENT_MODE:
269 t1=0.000001F*(float)
270 (mouse_x-(wg_last_xpixel+wg_first_xpixel)/2)*wg_hz_per_pixel;
271 make_wg_fqlimits();
272 wg_lowest_freq+=t1;
273 wg_highest_freq+=t1;
274 t1=0.1F*(float)frequency_scale_offset;
275 if(wg_lowest_freq < t1)
276 {
277 wg_highest_freq+=t1-wg_lowest_freq;
278 wg_lowest_freq+=t1-wg_lowest_freq;;
279 }
280 t1+=(float)(0.000001F*(float)(fft1_size-1)*(float)fft1_hz_per_point);
281 if(wg_highest_freq > t1)
282 {
283 wg_lowest_freq+=wg_highest_freq-t1;
284 wg_highest_freq+=wg_highest_freq-t1;
285 }
286 wg_freq_adjustment_mode=2;
287 wg_old_y1=wg.ytop;
288 wg_old_y2=wg.ybottom;
289 wg_old_x1=wg.xleft;
290 wg_old_x2=wg.xright;
291 make_wide_graph(TRUE);
292 sc[SC_WG_WATERF_REDRAW]++;
293 break;
294
295 default:
296 break;
297 }
298 rightpressed=BUTTON_IDLE;
299 mouse_task=-1;
300 wg_waterf_zero_time=0;
301 mouse_active_flag=0;
302 }
303
wide_graph_add_signal(void)304 void wide_graph_add_signal(void)
305 {
306 float t1;
307 int i;
308 int event_no;
309 // The user made a click on the right mouse button.
310 for(event_no=0; event_no<MAX_WGBUTT; event_no++)
311 {
312 if( wgbutt[event_no].x1 <= mouse_x &&
313 wgbutt[event_no].x2 >= mouse_x &&
314 wgbutt[event_no].y1 <= mouse_y &&
315 wgbutt[event_no].y2 >= mouse_y)
316 {
317 wg_old_y1=wg.ytop;
318 wg_old_y2=wg.ybottom;
319 wg_old_x1=wg.xleft;
320 wg_old_x2=wg.xright;
321 mouse_active_flag=1+event_no;
322 current_mouse_activity=mouse_continue_wide_graph_rightpressed;
323 return;
324 }
325 }
326 // If the mouse is on the frequency scale, shift the
327 // range of frequencies that we display.
328 // Add or remove a receive signal.
329 // We arrive here when the mouse right button is pressed.
330 // mix1_selfreq[0] is the frequency we process and send to the loudspeaker.
331 // The other frequencies are translated from CW to ASCII and placed on
332 // the screen (hopefully, some time...).
333 // If we are within +/- 3 pixels from a frequency that is already selected
334 // we deselect it.
335 if(rightpressed==BUTTON_RELEASED)
336 {
337 t1=wg_check_mix1(0);
338 if(t1 <0)
339 {
340 sc[SC_FREQ_READOUT]++;
341 baseb_reset_counter++;
342 if( ((unsigned int)ui.network_flag & NET_RX_INPUT) != 0)
343 {
344 net_send_slaves_freq();
345 }
346 goto addx;
347 }
348 for(i=1; i<genparm[MIX1_NO_OF_CHANNELS]; i++)
349 {
350 if(mix1_selfreq[i]<0)
351 {
352 make_new_signal(i,t1);
353 goto addx;
354 }
355 }
356 addx:;
357 if(rightpressed==BUTTON_RELEASED)
358 {
359 sc[SC_SHOW_FFT1]++;
360 rightpressed=BUTTON_IDLE;
361 mouse_task=-1;
362 }
363 }
364 }
365
make_wg_waterf_cfac(void)366 void make_wg_waterf_cfac(void)
367 {
368 wg_waterf_cfac=wg.waterfall_db_gain*0.01F;
369 wg_waterf_czer=100*(wg.waterfall_db_zero+WATERFALL_SCALE_ZERO);
370 }
371
372
check_wg_fft_avgnum(void)373 void check_wg_fft_avgnum(void)
374 {
375 // fft1 average power spectra are used to display the full dynamic
376 // range spectrum.
377 // In case fft2 is not enabled they are also used for the waterfall graph
378 // and for AFC (if enabled)
379 // Average power spectra are time consuming to calculate so several
380 // different ways are used depending on the needs.
381 // wg.fft_avg1num 1 to MAX_FFT1_AVG1
382 // fft1_sumsq=sum over avg1num spectra.
383 // wg.spek_avgnum = number of spectra for main spectrum
384 // wg.spek_avgnum=wg.fft_avg1num*wg_fft_avg2num;
385 // On entry here wg.fft_avg1num is determined by the user.
386 // change wg.spek_avgnum if necessary
387 // calculate the new avg2num
388 // In case neither AFC nor fft2 is enabled, make sure the averaging
389 // selected for the waterfall graph is a multiple of wg.fft_avg1num.
390 if(wg.fft_avg1num<1)wg.fft_avg1num=1;
391 if(wg.fft_avg1num>MAX_FFT1_AVG1)wg.fft_avg1num=MAX_FFT1_AVG1;
392 if(wg.spek_avgnum<wg.fft_avg1num)wg.spek_avgnum=wg.fft_avg1num;
393 wg_fft_avg2num=(wg.spek_avgnum+wg.fft_avg1num/2)/wg.fft_avg1num;
394 if(wg_fft_avg2num >= max_fft1_sumsq)wg_fft_avg2num=max_fft1_sumsq-1;
395 wg.spek_avgnum=wg.fft_avg1num*wg_fft_avg2num;
396 while(wg.spek_avgnum >= 99999)
397 {
398 wg_fft_avg2num--;
399 wg.spek_avgnum=wg.fft_avg1num*wg_fft_avg2num;
400 }
401 if( genparm[SECOND_FFT_ENABLE] == 0 )
402 {
403 if(wg.waterfall_avgnum<wg.fft_avg1num)wg.waterfall_avgnum=wg.fft_avg1num;
404 wg.waterfall_avgnum=(wg.waterfall_avgnum+wg.fft_avg1num/2)/wg.fft_avg1num;
405 wg.waterfall_avgnum*=wg.fft_avg1num;
406 }
407 }
408
wg_error(char * txt,int line)409 void wg_error(char *txt,int line)
410 {
411 int i;
412 i=0;
413 while(txt[i]!=0)i++;
414 settextcolor(15);
415 i=wg.xright/text_width-4-i;
416 if(i<=wg.xleft/text_width)i=wg.xleft/text_width+1;
417 lir_text(i,wg.ybottom/text_height-2-line,txt);
418 settextcolor(7);
419 }
420
421
decrease_wg_pixels_per_points(void)422 void decrease_wg_pixels_per_points(void)
423 {
424 if(wg_xpixels < 128)return;
425 if(wg.pixels_per_xpoint != 0)
426 {
427 wg.pixels_per_xpoint/=2;
428 if(wg.pixels_per_xpoint > 0)
429 {
430 wg.xpoints=wg_xpixels/wg.pixels_per_xpoint;
431 }
432 else
433 {
434 wg.pixels_per_xpoint=0;
435 wg.xpoints_per_pixel=2;
436 wg.xpoints=wg_xpixels*2;
437 }
438 }
439 else
440 {
441 if(genparm[SECOND_FFT_ENABLE] == 0)
442 {
443 wg.xpoints_per_pixel++;
444 wg.xpoints=wg_xpixels*wg.xpoints_per_pixel;
445 }
446 else
447 {
448 wg.xpoints_per_pixel*=2;
449 wg.xpoints=wg_xpixels*wg.xpoints_per_pixel;
450 }
451 }
452 }
453
help_on_wide_graph(void)454 void help_on_wide_graph(void)
455 {
456 int msg_no;
457 int event_no;
458 // Set msg to select a frequency in case it is not button or border
459 msg_no=340;
460 // First find out is we are on a button or border line.
461 for(event_no=0; event_no<MAX_WGBUTT; event_no++)
462 {
463 if( wgbutt[event_no].x1 <= mouse_x &&
464 wgbutt[event_no].x2 >= mouse_x &&
465 wgbutt[event_no].y1 <= mouse_y &&
466 wgbutt[event_no].y2 >= mouse_y)
467 {
468 switch (event_no)
469 {
470 case WG_TOP:
471 case WG_BORDER:
472 case WG_BOTTOM:
473 case WG_LEFT:
474 case WG_RIGHT:
475 msg_no=100;
476 break;
477
478 case WG_YSCALE_EXPAND:
479 msg_no=3;
480 break;
481
482 case WG_YSCALE_CONTRACT:
483 msg_no=4;
484 break;
485
486 case WG_YZERO_DECREASE:
487 msg_no=5;
488 break;
489
490 case WG_YZERO_INCREASE:
491 msg_no=6;
492 break;
493
494 case WG_FQMIN_DECREASE:
495 msg_no=7;
496 break;
497
498 case WG_FQMIN_INCREASE:
499 msg_no=8;
500 break;
501
502 case WG_FQMAX_DECREASE:
503 msg_no=9;
504 break;
505
506 case WG_FQMAX_INCREASE:
507 msg_no=10;
508 break;
509
510 case WG_SPUR_TOGGLE:
511 msg_no=316;
512 break;
513
514 case WG_AVG1NUM:
515 if(genparm[SECOND_FFT_ENABLE]==0)
516 {
517 msg_no=11;
518 }
519 else
520 {
521 msg_no=12;
522 }
523 break;
524
525 case WG_FFT1_AVGNUM:
526 if(genparm[SECOND_FFT_ENABLE] == 0)
527 {
528 msg_no=58;
529 }
530 else
531 {
532 msg_no=59;
533 }
534 break;
535
536 case WG_WATERF_AVGNUM:
537 if(genparm[SECOND_FFT_ENABLE] == 0)
538 {
539 msg_no=60;
540 }
541 else
542 {
543 msg_no=61;
544 }
545 break;
546
547 case WG_WATERF_ZERO:
548 if(genparm[SECOND_FFT_ENABLE] == 0)
549 {
550 msg_no=64;
551 }
552 else
553 {
554 msg_no=65;
555 }
556 break;
557
558 case WG_WATERF_GAIN:
559 if(genparm[SECOND_FFT_ENABLE] == 0)
560 {
561 msg_no=66;
562 }
563 else
564 {
565 msg_no=67;
566 }
567 break;
568
569 case WG_FREQ_ADJUSTMENT_MODE:
570 msg_no=323;
571 break;
572
573 case WG_LOWEST_FREQ:
574 msg_no=324;
575 break;
576
577 case WG_HIGHEST_FREQ:
578 msg_no=325;
579 break;
580 }
581 }
582 }
583 help_message(msg_no);
584 }
585
change_fft1avgnum(void)586 void change_fft1avgnum(void)
587 {
588 wg.spek_avgnum=numinput_int_data;
589 check_wg_fft_avgnum();
590 change_fft1_flag=TRUE;
591 make_wg_yfac();
592 make_modepar_file(GRAPHTYPE_WG);
593 sc[SC_WG_BUTTONS]++;
594 }
595
change_waterfall_avgnum(void)596 void change_waterfall_avgnum(void)
597 {
598 wg.waterfall_avgnum=numinput_int_data;
599 if(wg.waterfall_avgnum < 1)
600 {
601 wg.waterfall_avgnum=1;
602 }
603 if(genparm[SECOND_FFT_ENABLE] == 0) check_wg_fft_avgnum();
604 make_wg_yfac();
605 make_modepar_file(GRAPHTYPE_WG);
606 sc[SC_WG_BUTTONS]++;
607 }
608
change_wg_waterfall_zero(void)609 void change_wg_waterfall_zero(void)
610 {
611 wg.waterfall_db_zero=numinput_float_data;
612 make_modepar_file(GRAPHTYPE_WG);
613 sc[SC_WG_WATERF_REDRAW]++;
614 }
615
change_wg_waterfall_gain(void)616 void change_wg_waterfall_gain(void)
617 {
618 wg.waterfall_db_gain=numinput_float_data;
619 if(wg.waterfall_db_gain <0.01F)wg.waterfall_db_gain=0.01F;
620 make_modepar_file(GRAPHTYPE_WG);
621 sc[SC_WG_WATERF_REDRAW]++;
622 }
623
624
change_wg_lowest_freq(void)625 void change_wg_lowest_freq(void)
626 {
627 float t1, t2;
628 t1=(float)(0.1*frequency_scale_offset);
629 t2=t1+(float)(0.000001*(fft1_size-4)*fft1_hz_per_point);
630 wg_lowest_freq=numinput_float_data;
631 if(wg_lowest_freq > t2)wg_lowest_freq=t2;
632 if(wg_lowest_freq < t1)wg_lowest_freq=t1;
633 make_modepar_file(GRAPHTYPE_WG);
634 sc[SC_WG_WATERF_REDRAW]++;
635 }
636
change_wg_highest_freq(void)637 void change_wg_highest_freq(void)
638 {
639 float t1, t2;
640 t1=(float)(0.1*frequency_scale_offset+0.000004*fft1_hz_per_point);
641 t2=t1+0.000001F*(float)(fft1_size-4)*fft1_hz_per_point;
642 wg_highest_freq=numinput_float_data;
643 if(wg_highest_freq > t2)wg_highest_freq=t2;
644 if(wg_highest_freq < t1)wg_highest_freq=t1;
645 make_modepar_file(GRAPHTYPE_WG);
646 sc[SC_WG_WATERF_REDRAW]++;
647 }
648
mouse_continue_wide_graph(void)649 void mouse_continue_wide_graph(void)
650 {
651 int j, old_xpoints;
652 switch (mouse_active_flag-1)
653 {
654 case WG_TOP:
655 if(wg.ytop!=mouse_y)
656 {
657 pause_screen_and_hide_mouse();
658 dual_graph_borders((void*)&wg,0);
659 wg.ytop=mouse_y;
660 j=wg.yborder-text_height-YBO;
661 if(wg.ytop > j)wg.ytop=j;
662 if(wg_old_y1 > wg.ytop)wg_old_y1=wg.ytop;
663 dual_graph_borders((void*)&wg,15);
664 resume_thread(THREAD_SCREEN);
665 }
666 break;
667
668 case WG_BORDER:
669 if(wg.yborder!=mouse_y)
670 {
671 pause_screen_and_hide_mouse();
672 dual_graph_borders((void*)&wg,0);
673 wg.yborder=mouse_y;
674 j=wg.ytop+text_height+YBO;
675 if(wg.yborder < j)wg.yborder=j;
676 j=wg.ybottom-2*text_height;
677 if(wg.yborder > j)wg.yborder=j;
678 dual_graph_borders((void*)&wg,15);
679 resume_thread(THREAD_SCREEN);
680 }
681 break;
682
683 case WG_BOTTOM:
684 if(wg.ybottom!=mouse_y)
685 {
686 pause_screen_and_hide_mouse();
687 dual_graph_borders((void*)&wg,0);
688 wg.ybottom=mouse_y;
689 j=wg.yborder+2*text_height;
690 if(wg.ybottom < j)wg.ybottom=j;
691 if(wg_old_y2 < wg.ybottom)wg_old_y2=wg.ybottom;
692 dual_graph_borders((void*)&wg,15);
693 resume_thread(THREAD_SCREEN);
694 }
695 break;
696
697 case WG_LEFT:
698 if(wg.xleft!=mouse_x)
699 {
700 pause_screen_and_hide_mouse();
701 dual_graph_borders((void*)&wg,0);
702 wg.xleft=mouse_x;
703 j=wg.xright-32-6*text_width;
704 if(wg.xleft > j)wg.xleft=j;
705 if(wg_old_x1 > wg.xleft)wg_old_x1=wg.xleft;
706 dual_graph_borders((void*)&wg,15);
707 resume_thread(THREAD_SCREEN);
708 }
709 break;
710
711 case WG_RIGHT:
712 if(wg.xright!=mouse_x)
713 {
714 pause_screen_and_hide_mouse();
715 dual_graph_borders((void*)&wg,0);
716 wg.xright=mouse_x;
717 j=wg.xleft+32+6*text_width;
718 if(wg.xright < j)wg.xright=j;
719 if(wg_old_x2 < wg.xright)wg_old_x2=wg.xright;
720 dual_graph_borders((void*)&wg,15);
721 resume_thread(THREAD_SCREEN);
722 }
723 break;
724
725 default:
726 goto await_release;
727 }
728 if(leftpressed == BUTTON_RELEASED)goto finish;
729 return;
730 await_release:;
731 if(leftpressed != BUTTON_RELEASED) return;
732 switch (mouse_active_flag-1)
733 {
734 case WG_YSCALE_EXPAND:
735 wg.yrange=wg.yrange/(float)pow(wg.yrange,.2);
736 break;
737
738 case WG_YSCALE_CONTRACT:
739 wg.yrange=wg.yrange*(float)pow(wg.yrange,.18);
740 break;
741
742 case WG_YZERO_DECREASE:
743 wg.yzero=wg.yzero/(float)pow(wg.yrange,.2);
744 break;
745
746 case WG_YZERO_INCREASE:
747 wg.yzero=(float)(wg.yzero*pow(wg.yrange,.18));
748 break;
749
750 case WG_FQMIN_DECREASE:
751 old_xpoints=wg.xpoints;
752 decrease_wg_pixels_per_points();
753 wg.first_xpoint-=wg.xpoints-old_xpoints;
754 break;
755
756 case WG_FQMIN_INCREASE:
757 old_xpoints=wg.xpoints;
758 increase_wg_pixels_per_points();
759 wg.first_xpoint-=wg.xpoints-old_xpoints;
760 break;
761
762 case WG_FQMAX_DECREASE:
763 old_xpoints=wg.xpoints;
764 increase_wg_pixels_per_points();
765 break;
766
767 case WG_FQMAX_INCREASE:
768 old_xpoints=wg.xpoints;
769 decrease_wg_pixels_per_points();
770 break;
771
772 case WG_AVG1NUM:
773 wg.fft_avg1num++;
774 if(wg.fft_avg1num > MAX_FFT1_AVG1)wg.fft_avg1num=1;
775 check_wg_fft_avgnum();
776 sc[SC_WG_BUTTONS]++;
777 break;
778
779 case WG_FFT1_AVGNUM:
780 mouse_active_flag=1;
781 numinput_xpix=wgbutt[WG_FFT1_AVGNUM].x1+text_width/2-1;
782 numinput_ypix=wgbutt[WG_FFT1_AVGNUM].y1+2;
783 numinput_chars=5;
784 erase_numinput_txt();
785 numinput_flag=FIXED_INT_PARM;
786 par_from_keyboard_routine=change_fft1avgnum;
787 return;
788
789 case WG_WATERF_AVGNUM:
790 mouse_active_flag=1;
791 numinput_xpix=wgbutt[WG_WATERF_AVGNUM].x1+text_width/2-1;
792 numinput_ypix=wgbutt[WG_WATERF_AVGNUM].y1+2;
793 numinput_chars=4;
794 erase_numinput_txt();
795 numinput_flag=FIXED_INT_PARM;
796 par_from_keyboard_routine=change_waterfall_avgnum;
797 return;
798
799 case WG_WATERF_ZERO:
800 mouse_active_flag=1;
801 numinput_xpix=wgbutt[WG_WATERF_ZERO].x1+text_width/2-1;
802 numinput_ypix=wgbutt[WG_WATERF_ZERO].y1+2;
803 numinput_chars=5;
804 erase_numinput_txt();
805 numinput_flag=FIXED_FLOAT_PARM;
806 par_from_keyboard_routine=change_wg_waterfall_zero;
807 return;
808
809 case WG_WATERF_GAIN:
810 mouse_active_flag=1;
811 numinput_xpix=wgbutt[WG_WATERF_GAIN].x1+text_width/2-1;
812 numinput_ypix=wgbutt[WG_WATERF_GAIN].y1+2;
813 numinput_chars=4;
814 erase_numinput_txt();
815 numinput_flag=FIXED_FLOAT_PARM;
816 par_from_keyboard_routine=change_wg_waterfall_gain;
817 return;
818
819 case WG_SPUR_TOGGLE:
820 wg.spur_inhibit^=1;
821 wg.spur_inhibit&=1;
822 if(wg.spur_inhibit == 1)spurcancel_flag++;
823 leftpressed=BUTTON_IDLE;
824 mouse_active_flag=0;
825 make_modepar_file(GRAPHTYPE_WG);
826 sc[SC_WG_WATERF_REDRAW]++;
827 return;
828
829 case WG_FREQ_ADJUSTMENT_MODE:
830 wg_freq_adjustment_mode++;
831 if(wg_freq_adjustment_mode < 2)
832 {
833 make_wg_fqlimits();
834 }
835 break;
836
837 case WG_LOWEST_FREQ:
838 mouse_active_flag=1;
839 numinput_xpix=wgbutt[WG_LOWEST_FREQ].x1+text_width/2-1;
840 numinput_ypix=wgbutt[WG_LOWEST_FREQ].y1+2;
841 numinput_chars=(wgbutt[WG_LOWEST_FREQ].x2 -
842 wgbutt[WG_LOWEST_FREQ].x1)/text_width-1;
843 erase_numinput_txt();
844 numinput_flag=FIXED_FLOAT_PARM;
845 par_from_keyboard_routine=change_wg_lowest_freq;
846 return;
847
848 case WG_HIGHEST_FREQ:
849 mouse_active_flag=1;
850 numinput_xpix=wgbutt[WG_HIGHEST_FREQ].x1+text_width/2-1;
851 numinput_ypix=wgbutt[WG_HIGHEST_FREQ].y1+2;
852 numinput_chars=(wgbutt[WG_HIGHEST_FREQ].x2 -
853 wgbutt[WG_HIGHEST_FREQ].x1)/text_width-1;
854 erase_numinput_txt();
855 numinput_flag=FIXED_FLOAT_PARM;
856 par_from_keyboard_routine=change_wg_highest_freq;
857 return;
858 }
859 finish:;
860 leftpressed=BUTTON_IDLE;
861 mouse_active_flag=0;
862 make_wide_graph(TRUE);
863 }
864
mouse_on_wide_graph(void)865 void mouse_on_wide_graph(void)
866 {
867 int event_no;
868 // First find out if we are on a button or border line.
869 for(event_no=0; event_no<MAX_WGBUTT; event_no++)
870 {
871 if( wgbutt[event_no].x1 <= mouse_x &&
872 wgbutt[event_no].x2 >= mouse_x &&
873 wgbutt[event_no].y1 <= mouse_y &&
874 wgbutt[event_no].y2 >= mouse_y)
875 {
876 wg_old_y1=wg.ytop;
877 wg_old_y2=wg.ybottom;
878 wg_old_x1=wg.xleft;
879 wg_old_x2=wg.xright;
880 mouse_active_flag=1+event_no;
881 current_mouse_activity=mouse_continue_wide_graph;
882 return;
883 }
884 }
885 if(rx_mode != MODE_TXTEST && rx_mode != MODE_RADAR)
886 {
887 // Not button or border.
888 // Select a frequency.
889 current_mouse_activity=wide_graph_selfreq;
890 }
891 else
892 {
893 current_mouse_activity=mouse_nothing;
894 }
895 mouse_active_flag=1;
896 }
897
898
make_wg_yfac(void)899 void make_wg_yfac(void)
900 {
901 float t1;
902 int i;
903 wg_yfac_power=1/(4*(float)wg.spek_avgnum*wg.yzero*wg.yzero);
904 // If waterfall is generated from fft1 we set the zero point here.
905 t1=(float)FFT1_WATERFALL_ZERO/(float)wg.waterfall_avgnum;
906 if(wg.xpoints_per_pixel > 1)
907 {
908 wg_yfac_power/=(float)wg.xpoints_per_pixel*(float)wg.xpoints_per_pixel;
909 t1*=(float)ui.rx_rf_channels;
910 }
911 if(genparm[SECOND_FFT_ENABLE] != 0)
912 {
913 // The constant here sets the zero point for the waterfall graph
914 // generated by fft2.
915 t1=(float)(FFT2_WATERFALL_ZERO)/((float)fft2_size*(float)fft1_size);
916 t1/=(float)sqrt((float)(wg.waterfall_avgnum));
917 if(fft_cntrl[FFT2_CURMODE].mmx != 0)
918 {
919 t1*=(float)(2<<(2*(genparm[SECOND_FFT_ATT_N])));
920 }
921 t1*=(float)(1<<(2*genparm[FIRST_BCKFFT_ATT_N]));
922 t1*=(float)(1 + 1/(0.5+genparm[FIRST_FFT_SINPOW]));
923 t1*=(float)(ui.rx_rf_channels*ui.rx_rf_channels);
924 }
925 // Straighten out the waterfall graph until the -10dB point is reached
926 for(i=0; i<fft1_size; i++)
927 {
928 if(fft1_desired[i] > 0.3162278)
929 {
930 wg_waterf_yfac[i]=t1/(float)pow(fft1_desired[i],2.0);
931 }
932 else
933 {
934 wg_waterf_yfac[i]=t1*10;
935 }
936 }
937 wg_waterf_yfac[0]=t1;
938 wg_waterf_yfac[fft1_size-1]=t1;
939 wg_yfac_log=10/wg_db_per_pixel;
940 }
941
new_fft1_averages(int ptr,int ia,int ib)942 void new_fft1_averages(int ptr, int ia, int ib)
943 {
944 int i,m,p0;
945 change_fft1_flag=FALSE;
946 if(lir_status==LIR_POWTIM)return;
947 // Make fft1_slowsum from scratch over the specified interval
948 // We have power spectra in fft1_sumsq and we want to take
949 // the sum over the latest wg.fft_avg2num of them.
950 if(ia<0)lirerr(521233);
951 if(ib<ia)lirerr(521234);
952 if(ib>=fft1_size)lirerr(521235);
953 p0=(ptr-(wg_fft_avg2num-1)*fft1_size+fft1_sumsq_bufsize)
954 &fft1_sumsq_mask;
955 for(i=ia; i<=ib; i++)
956 {
957 fft1_slowsum[i]=fft1_sumsq[p0+i]+0.0000001F;
958 }
959 p0=(p0+fft1_size)&fft1_sumsq_mask;
960 for(m=1; m<wg_fft_avg2num; m++)
961 {
962 for(i=ia; i<=ib; i++)fft1_slowsum[i]+=fft1_sumsq[p0+i];
963 p0=(p0+fft1_size)&fft1_sumsq_mask;
964 }
965 if(fft1_correlation_flag)
966 {
967 p0=(ptr-(wg_fft_avg2num-1)*fft1_size+fft1_sumsq_bufsize)
968 &fft1_sumsq_mask;
969 for(i=ia; i<=ib; i++)
970 {
971 fft1_slowcorr[2*i ]=fft1_corrsum[2*(p0+i) ];
972 fft1_slowcorr[2*i+1]=fft1_corrsum[2*(p0+i)+1];
973 }
974 p0=(p0+fft1_size)&fft1_sumsq_mask;
975 for(m=1; m<wg_fft_avg2num; m++)
976 {
977 for(i=ia; i<=ib; i++)
978 {
979 fft1_slowcorr[2*i ]+=fft1_corrsum[2*(p0+i) ];
980 fft1_slowcorr[2*i+1]+=fft1_corrsum[2*(p0+i)+1];
981 }
982 p0=(p0+fft1_size)&fft1_sumsq_mask;
983 }
984 }
985 }
986
increase_wg_pixels_per_points(void)987 void increase_wg_pixels_per_points(void)
988 {
989 if(wg.pixels_per_xpoint != 0)
990 {
991 wg.pixels_per_xpoint*=2;
992 wg.xpoints=wg_xpixels/wg.pixels_per_xpoint;
993 wg.xpoints_per_pixel=0;
994 }
995 else
996 {
997 wg.xpoints_per_pixel--;
998 wg.xpoints=wg_xpixels*wg.xpoints_per_pixel;
999 if(wg.xpoints_per_pixel == 1)
1000 {
1001 wg.pixels_per_xpoint=1;
1002 wg.xpoints=wg_xpixels;
1003 }
1004 else
1005 {
1006 wg.pixels_per_xpoint=0;
1007 }
1008 }
1009 }
1010
make_wide_graph(int clear_old)1011 void make_wide_graph(int clear_old)
1012 {
1013 char s[80];
1014 int i, j, k;
1015 int old_xpix;
1016 int hgwat_xpoints;
1017 float t2;
1018 int ypixels;
1019 float t1;
1020 double db_scalestep, scale_value;
1021 float scale_y;
1022 int scale_decimals;
1023 float scale_rnd;
1024 pause_thread(THREAD_SCREEN);
1025 if(clear_old)
1026 {
1027 hide_mouse(wg_old_x1,wg_old_x2,wg_old_y1,wg_old_y2);
1028 lir_fillbox(wg_old_x1,wg_old_y1,wg_old_x2-wg_old_x1+1,
1029 wg_old_y2-wg_old_y1+1,0);
1030 }
1031 // If there is another window open, make sure we stay away from it
1032 current_graph_minh=YBO+3*text_height;
1033 current_graph_minw=32+6*text_width;
1034 check_graph_placement(&wg);
1035 clear_button(wgbutt, MAX_WGBUTT);
1036 hide_mouse(wg.xleft,wg.xright,wg.ytop,wg.ybottom);
1037 if(wg.ybottom-wg.ytop<3*text_height+YBO)
1038 {
1039 wg.yborder=(wg.ybottom+wg.ytop)/2;
1040 }
1041 else
1042 {
1043 if(wg.yborder < wg.ytop+text_height+YBO)wg.yborder=wg.ytop+text_height+YBO;
1044 if(wg.yborder > wg.ybottom-2*text_height)wg.yborder=wg.ybottom-2*text_height;
1045 }
1046 wg_waterf_lines=wg.yborder-wg.ytop-text_height-YWF;
1047 wg_waterf_y1=wg.ytop+text_height+YWF+1;
1048 wg_waterf_y2=wg_waterf_y1+2+wg_waterf_lines/16;
1049 if(wg_waterf_y2 > wg_waterf_y1+wg_waterf_lines-1)
1050 wg_waterf_y2=wg_waterf_y1+wg_waterf_lines-1;
1051 wg_waterf_y=wg_waterf_y2;
1052 if(wg_waterf_y2 > wg.yborder-1)wg_waterf_y2=wg.yborder-1;
1053 wg_waterf_yinc=wg_waterf_y2-wg_waterf_y1+1;
1054 if(wg_freq_adjustment_mode >= 2)
1055 {
1056 wg_freq_adjustment_mode=0;
1057 // Find out whether we can expand our window.
1058 k=wg.xright-wg.xleft;
1059 i=0;
1060 while(i!=k)
1061 {
1062 i=k;
1063 wg.xleft=wg.xleft-k/2;
1064 wg.xright=wg.xright+k/2;
1065 if(wg.xleft<0)wg.xleft=0;
1066 if(wg.xright >= screen_width)wg.xright=screen_width-1;
1067 check_graph_placement(&wg);
1068 k=wg.xright-wg.xleft;
1069 }
1070 wg.xpoints=(int)(1000000*(wg_highest_freq-wg_lowest_freq)/fft1_hz_per_point);
1071 if(wg.xpoints < 4)wg.xpoints=4;
1072 if(wg.xpoints > fft1_size)wg.xpoints=fft1_size;
1073 wg_first_frequency=(float)(1000000*wg_lowest_freq
1074 -100000*frequency_scale_offset);
1075 wg.first_xpoint=(int)(wg_first_frequency/fft1_hz_per_point);
1076 wg_xpixels=wg.xright-wg.xleft-6*text_width+1;
1077 wg.pixels_per_xpoint=wg_xpixels/wg.xpoints;
1078 if(wg.pixels_per_xpoint > 0)
1079 {
1080 if(wg.pixels_per_xpoint == 1)
1081 {
1082 wg.xpoints_per_pixel=1;
1083 }
1084 else
1085 {
1086 wg.xpoints_per_pixel=0;
1087 }
1088 wg_xpixels=wg.xpoints*wg.pixels_per_xpoint;
1089 }
1090 else
1091 {
1092 wg.xpoints_per_pixel=wg.xpoints/wg_xpixels;
1093 wg.xpoints=wg_xpixels*wg.xpoints_per_pixel;
1094 }
1095 wg.xright=wg_xpixels+wg.xleft+6*text_width-1;
1096 }
1097 if(wg.first_xpoint<0)wg.first_xpoint=0;
1098 // Check if the desired spectrum fits within the frame and
1099 // make changes as required if not.
1100 wg_first_xpixel=wg.xleft+4*text_width;
1101 wg_last_xpixel=wg.xright-2*text_width;
1102 wg_xpixels = wg_last_xpixel-wg_first_xpixel+1;
1103 old_xpix=wg_xpixels;
1104 if(wg.pixels_per_xpoint != 0)
1105 {
1106 wg.xpoints=wg_xpixels/wg.pixels_per_xpoint;
1107 }
1108 else
1109 {
1110 wg.xpoints=wg_xpixels*wg.xpoints_per_pixel;
1111 }
1112 if(wg.xpoints < 4)
1113 {
1114 wg.xpoints=4;
1115 wg.pixels_per_xpoint=wg_xpixels/wg.xpoints;
1116 wg.xpoints_per_pixel=0;
1117 }
1118 if(rx_mode == MODE_TXTEST)
1119 {
1120 if(wg.xpoints_per_pixel != 0)
1121 {
1122 if( fft1_hz_per_point*wg.xpoints_per_pixel > 600)
1123 {
1124 wg.xpoints_per_pixel=595/fft1_hz_per_point;
1125 wg.xpoints=wg_xpixels*wg.xpoints_per_pixel;
1126 }
1127 }
1128 else
1129 {
1130 if(wg.pixels_per_xpoint*fft1_hz_per_point > 400)
1131 {
1132 wg.pixels_per_xpoint= 400/fft1_hz_per_point;
1133 wg.xpoints=wg_xpixels/wg.pixels_per_xpoint;
1134 wg_xpixels=wg.xpoints*wg.pixels_per_xpoint;
1135 }
1136 }
1137 txtest_no_of_segs=wg.xpoints*fft1_hz_per_point/600;
1138 if(txtest_no_of_segs > screen_width-4*text_width)
1139 {
1140 wg.xpoints=600*(screen_width-4*text_width)/fft1_hz_per_point;
1141 if(wg.pixels_per_xpoint != 0)
1142 {
1143 wg_xpixels=wg.xpoints*wg.pixels_per_xpoint;
1144 }
1145 else
1146 {
1147 wg_xpixels=wg.xpoints/wg.xpoints_per_pixel;
1148 wg.xpoints=wg_xpixels*wg.xpoints_per_pixel;
1149 }
1150 }
1151 if(wg_xpixels > wg.xright-wg.xleft-6*text_width+1)
1152 {
1153 wg_xpixels=wg.xright-wg.xleft-6*text_width+1;
1154 if(wg.pixels_per_xpoint != 0)
1155 {
1156 wg.xpoints=wg_xpixels/wg.pixels_per_xpoint;
1157 wg_xpixels=wg.xpoints*wg.pixels_per_xpoint;
1158 }
1159 else
1160 {
1161 wg.xpoints=wg_xpixels*wg.xpoints_per_pixel;
1162 }
1163 }
1164 }
1165 if(wg.xpoints>fft1_size)
1166 {
1167 wg.xpoints=fft1_size;
1168 if(wg.pixels_per_xpoint != 0)
1169 {
1170 wg_xpixels=wg.xpoints*wg.pixels_per_xpoint;
1171 }
1172 else
1173 {
1174 wg_xpixels=wg.xpoints/wg.xpoints_per_pixel;
1175 }
1176 }
1177 if(wg.first_xpoint+wg.xpoints>=fft1_size)wg.first_xpoint=fft1_size-wg.xpoints;
1178 // Now that we know that fft1 fits in the window, set the number of
1179 // pixels per data point.
1180 if(genparm[SECOND_FFT_ENABLE] != 0)
1181 {
1182 hgwat_xpoints=wg.xpoints*fft2_to_fft1_ratio;
1183 if(hgwat_xpoints > wg_xpixels)
1184 {
1185 hgwat_xpoints_per_pixel=hgwat_xpoints/wg_xpixels;
1186 hgwat_pixels_per_xpoint=0;
1187 wg.xpoints_per_pixel=hgwat_xpoints_per_pixel/fft2_to_fft1_ratio;
1188 if(wg.xpoints_per_pixel > 0)
1189 {
1190 hgwat_xpoints_per_pixel=wg.xpoints_per_pixel*fft2_to_fft1_ratio;
1191 wg_xpixels=hgwat_xpoints/hgwat_xpoints_per_pixel;
1192 wg.xpoints=wg_xpixels*wg.xpoints_per_pixel;
1193 if(wg.xpoints_per_pixel == 1)
1194 {
1195 wg.pixels_per_xpoint=1;
1196 }
1197 else
1198 {
1199 wg.pixels_per_xpoint=0;
1200 }
1201 wg_hz_per_pixel=fft1_hz_per_point*(float)wg.xpoints_per_pixel;
1202 }
1203 else
1204 {
1205 wg.pixels_per_xpoint=fft2_to_fft1_ratio/hgwat_xpoints_per_pixel;
1206 wg_xpixels=wg.xpoints*wg.pixels_per_xpoint;
1207 while(wg_xpixels > old_xpix)
1208 {
1209 wg.xpoints--;
1210 wg_xpixels-=wg.pixels_per_xpoint;
1211 }
1212 wg.xpoints=wg_xpixels/wg.pixels_per_xpoint;
1213 wg_hz_per_pixel=fft1_hz_per_point/(float)wg.pixels_per_xpoint;
1214 make_power_of_two(&wg.pixels_per_xpoint);
1215 hgwat_xpoints_per_pixel=fft2_to_fft1_ratio/wg.pixels_per_xpoint;
1216 }
1217 }
1218 else
1219 {
1220 hgwat_xpoints_per_pixel=0;
1221 hgwat_pixels_per_xpoint=wg_xpixels/hgwat_xpoints;
1222 wg.pixels_per_xpoint=fft2_to_fft1_ratio*hgwat_pixels_per_xpoint;
1223 wg_xpixels=wg.xpoints*wg.pixels_per_xpoint;
1224 wg.xpoints=wg_xpixels/wg.pixels_per_xpoint;
1225 wg_hz_per_pixel=fft1_hz_per_point/(float)wg.pixels_per_xpoint;
1226 if(wg.pixels_per_xpoint == 1)
1227 {
1228 wg.xpoints_per_pixel=1;
1229 }
1230 else
1231 {
1232 wg.xpoints_per_pixel=0;
1233 }
1234 }
1235 hgwat_first_xpoint=wg.first_xpoint*fft2_to_fft1_ratio;
1236 }
1237 else
1238 {
1239 if(wg.pixels_per_xpoint != 0)
1240 {
1241 wg_xpixels=wg.xpoints*wg.pixels_per_xpoint;
1242 wg_hz_per_pixel=fft1_hz_per_point/(float)wg.pixels_per_xpoint;
1243 }
1244 else
1245 {
1246 wg_xpixels=wg.xpoints/wg.xpoints_per_pixel;
1247 wg_hz_per_pixel=fft1_hz_per_point*(float)wg.xpoints_per_pixel;
1248 }
1249 }
1250 wg_last_xpixel=wg_first_xpixel+wg_xpixels-1;
1251 if(genparm[WG_WATERF_BLANKED_PERCENT] == 0)
1252 {
1253 wg_waterfall_blank_points=0;
1254 }
1255 else
1256 {
1257 wg_waterfall_blank_points=1+(genparm[WG_WATERF_BLANKED_PERCENT]*wg_xpixels)/100;
1258 }
1259 wg.xright=wg_last_xpixel+2*text_width;
1260 wg_first_frequency=fft1_hz_per_point*(float)wg.first_xpoint;
1261 set_fft1_endpoints();
1262 mix1_lowest_fq=(float)(fft1_first_point+1)*fft1_hz_per_point;
1263 t2=(float)wg.first_xpoint*fft1_hz_per_point;
1264 if(mix1_lowest_fq<t2) mix1_lowest_fq=t2;
1265 mix1_highest_fq=(float)(fft1_last_point-1)*fft1_hz_per_point;
1266 t2=(float)((float)wg_last_point*fft1_hz_per_point);
1267 if(mix1_highest_fq > t2)mix1_highest_fq=t2;
1268 if(wg.ybottom >= screen_height)wg.ybottom=screen_height-1;
1269 scro[wide_graph_scro].no=WIDE_GRAPH;
1270 scro[wide_graph_scro].x1=wg.xleft;
1271 scro[wide_graph_scro].x2=wg.xright;
1272 scro[wide_graph_scro].y1=wg.ytop;
1273 scro[wide_graph_scro].y2=wg.ybottom;
1274 wgbutt[WG_LEFT].x1=wg.xleft;
1275 wgbutt[WG_LEFT].x2=wg.xleft+2;
1276 wgbutt[WG_LEFT].y1=wg.ytop;
1277 wgbutt[WG_LEFT].y2=wg.ybottom;
1278 wgbutt[WG_RIGHT].x1=wg.xright-2;
1279 wgbutt[WG_RIGHT].x2=wg.xright;
1280 wgbutt[WG_RIGHT].y1=wg.ytop;
1281 wgbutt[WG_RIGHT].y2=wg.ybottom;
1282 wgbutt[WG_TOP].x1=wg.xleft;
1283 wgbutt[WG_TOP].x2=wg.xright;
1284 wgbutt[WG_TOP].y1=wg.ytop;
1285 wgbutt[WG_TOP].y2=wg.ytop+2;
1286 wgbutt[WG_BORDER].x1=wg.xleft;
1287 wgbutt[WG_BORDER].x2=wg.xright;
1288 wgbutt[WG_BORDER].y1=wg.yborder-1;
1289 wgbutt[WG_BORDER].y2=wg.yborder+1;
1290 wgbutt[WG_BOTTOM].x1=wg.xleft;
1291 wgbutt[WG_BOTTOM].x2=wg.xright;
1292 wgbutt[WG_BOTTOM].y1=wg.ybottom-2;
1293 wgbutt[WG_BOTTOM].y2=wg.ybottom;
1294 // Draw the border lines
1295 dual_graph_borders((void*)&wg,7);
1296 // Free the waterfall buffer in case there is already one allocated
1297 // Then allocate the number of bytes we actually need for the current screen.
1298 wg_waterf=chk_free(wg_waterf);
1299 // ************************************
1300 wg_waterf_size=wg_xpixels*wg_waterf_lines;
1301 max_wg_waterf_times=2+(int)(0.5F*(float)wg_waterf_lines/(float)text_height);
1302 wg_waterf_ptr=0;
1303 wg_waterf=malloc((unsigned int)max_wg_waterf_times*sizeof(WATERF_TIMES)+
1304 (unsigned int)wg_waterf_size*sizeof(short int)+
1305 (unsigned int)screen_height*sizeof(char));
1306 if(wg_waterf == NULL)
1307 {
1308 lirerr(1036);
1309 return;
1310 }
1311 wg_background=(void*)(wg_waterf)+
1312 (unsigned int)wg_waterf_size*sizeof(short int);
1313 wg_waterf_times=(WATERF_TIMES*)((void*)(wg_background)+
1314 (unsigned int)screen_height*sizeof(char));
1315 for(i=0;i<wg_waterf_size;i++)wg_waterf[i]=(short int)0x8000;
1316 for(i=0;i<max_wg_waterf_times; i++)wg_waterf_times[i].line=10000;
1317 // Write out the y scale for logarithmic spectrum graph.
1318 // We want a point with amplitude 1<<(fft1_n/2) to be placed at the
1319 // zero point of the dB scale.
1320 for(i=0; i<screen_height; i++)wg_background[i]=0;
1321 ypixels=wg.ybottom-wg.yborder-1;
1322 wg_db_per_pixel=(float)(20*log10(wg.yrange)/ypixels);
1323 db_scalestep=1.3*wg_db_per_pixel*text_height;
1324 adjust_scale(&db_scalestep);
1325 t1=(float)(20*log10(wg.yzero));
1326 i=(int)(t1/db_scalestep);
1327 scale_value=i*(1.00000*db_scalestep);
1328 scale_y=(float)(wg.ybottom+(t1-scale_value)/wg_db_per_pixel);
1329 scale_decimals=0;
1330 scale_rnd=.01F;
1331 if(db_scalestep < 1)
1332 {
1333 sprintf(s,"%f",db_scalestep);
1334 while(s[scale_decimals] != '.')scale_decimals++;
1335 scale_decimals++;
1336 while(s[scale_decimals] == '0' && s[scale_decimals] != 0)
1337 {
1338 scale_decimals++;
1339 scale_rnd/=10;
1340 }
1341 }
1342 while( scale_y-(float)(text_height/2-2) > wg.yborder+1.5*text_height)
1343 {
1344 i=0;
1345 if(scale_y+(float)(text_height+2) < wg.ybottom)
1346 {
1347 if(scale_value < 0)
1348 {
1349 t1=(float)(scale_value-scale_rnd);
1350 }
1351 else
1352 {
1353 t1=(float)(scale_value+scale_rnd);
1354 }
1355 sprintf(s,"%f",t1);
1356 while(s[i] != '.')i++;
1357 if(scale_decimals != 0)
1358 {
1359 i+=scale_decimals;
1360 }
1361 s[i]=0;
1362 lir_pixwrite(wg.xleft+text_width/2,(int)scale_y-text_height/2+2,s);
1363 }
1364 if(scale_y+2 < wg.ybottom)
1365 {
1366 k=(int)scale_y;
1367 wg_background[k]=WG_DBSCALE_COLOR;
1368 lir_hline(wg_first_xpixel+scale_decimals*text_width,
1369 k,wg_last_xpixel,WG_DBSCALE_COLOR);
1370 if(kill_all_flag) return;
1371 }
1372 scale_y-=(float)(db_scalestep/wg_db_per_pixel);
1373 scale_value+=db_scalestep;
1374 }
1375 // Init fft1_spectrum as the base line and place it on the screen.
1376 for(i=wg_first_xpixel; i<=wg_last_xpixel; i++)
1377 {
1378 fft1_spectrum[i]=(short int)(wg.ybottom-1);
1379 }
1380 lir_hline(wg_first_xpixel,wg.ybottom-1,wg_last_xpixel,15);
1381 new_fft1_averages(fft1_sumsq_pa, fft1_first_point, fft1_last_point);
1382 make_button(wg.xleft+text_width,wg.ybottom-text_height/2-2,
1383 wgbutt,WG_YSCALE_EXPAND,24);
1384 make_button(wg.xleft+3*text_width,wg.ybottom-text_height/2-2,
1385 wgbutt,WG_YSCALE_CONTRACT,25);
1386 i=(wg.ybottom+wg.yborder)/2;
1387 make_button(wg.xright-text_width,i-text_height/2-2,
1388 wgbutt,WG_YZERO_DECREASE,24);
1389 make_button(wg.xright-text_width,i+text_height/2+2,
1390 wgbutt,WG_YZERO_INCREASE,25);
1391 make_button(wg.xright-text_width,wg.ybottom-text_height/2-2,
1392 wgbutt,WG_AVG1NUM,(char)(wg.fft_avg1num+48));
1393 if(wg_freq_adjustment_mode == 0)
1394 {
1395 make_button(wg.xleft+text_width,wg.ytop+text_height/2+3,
1396 wgbutt,WG_FQMIN_DECREASE,26);
1397 make_button(wg.xleft+3*text_width,wg.ytop+text_height/2+3,
1398 wgbutt,WG_FQMIN_INCREASE,27);
1399 make_button(wg.xright-3*text_width,wg.ytop+text_height/2+3,
1400 wgbutt,WG_FQMAX_DECREASE,26);
1401 make_button(wg.xright-text_width,wg.ytop+text_height/2+3,
1402 wgbutt,WG_FQMAX_INCREASE,27);
1403 wgbutt[WG_FREQ_ADJUSTMENT_MODE].x1=wgbutt[WG_FQMIN_INCREASE].x2+2;
1404 wgbutt[WG_FREQ_ADJUSTMENT_MODE].x2=wgbutt[WG_FQMAX_DECREASE].x1-2;
1405 wgbutt[WG_FREQ_ADJUSTMENT_MODE].y1=wgbutt[WG_FQMAX_DECREASE].y1;
1406 wgbutt[WG_FREQ_ADJUSTMENT_MODE].y2=wgbutt[WG_FQMAX_DECREASE].y2;
1407 wg_freq_x1=wgbutt[WG_FQMIN_INCREASE].x2;
1408 wg_freq_x2=wgbutt[WG_FQMAX_DECREASE].x1;
1409 }
1410 else
1411 {
1412 wgbutt[WG_LOWEST_FREQ].x1=wg.xleft+2;
1413 wgbutt[WG_LOWEST_FREQ].x2=wgbutt[WG_LOWEST_FREQ].x1+15*text_width;
1414 wgbutt[WG_LOWEST_FREQ].y1=wg.ytop+2;
1415 wgbutt[WG_LOWEST_FREQ].y2=wgbutt[WG_LOWEST_FREQ].y1+text_height+2;
1416 wgbutt[WG_HIGHEST_FREQ].x2=wg.xright-2;
1417 wgbutt[WG_HIGHEST_FREQ].x1=wgbutt[WG_HIGHEST_FREQ].x2-15*text_width;
1418 wgbutt[WG_HIGHEST_FREQ].y1=wgbutt[WG_LOWEST_FREQ].y1;
1419 wgbutt[WG_HIGHEST_FREQ].y2=wgbutt[WG_LOWEST_FREQ].y2;
1420 if(wgbutt[WG_LOWEST_FREQ].x2+17 >= wgbutt[WG_HIGHEST_FREQ].x1)
1421 {
1422 i=(wgbutt[WG_LOWEST_FREQ].x2+wgbutt[WG_HIGHEST_FREQ].x1-1)/2;
1423 wgbutt[WG_LOWEST_FREQ].x2=i+8;
1424 wgbutt[WG_HIGHEST_FREQ].x1=i-8;
1425 }
1426 wgbutt[WG_FREQ_ADJUSTMENT_MODE].x1=wgbutt[WG_LOWEST_FREQ].x2+2;
1427 wgbutt[WG_FREQ_ADJUSTMENT_MODE].x2=wgbutt[WG_HIGHEST_FREQ].x1-2;
1428 wgbutt[WG_FREQ_ADJUSTMENT_MODE].y1=wgbutt[WG_LOWEST_FREQ].y1;
1429 wgbutt[WG_FREQ_ADJUSTMENT_MODE].y2=wgbutt[WG_LOWEST_FREQ].y2;
1430 wg_freq_x1=-1;
1431 }
1432 if(genparm[AFC_ENABLE] == 2)
1433 {
1434 if(wg.spur_inhibit == 0)
1435 {
1436 button_color=14;
1437 }
1438 else
1439 {
1440 button_color=3;
1441 }
1442 settextcolor(button_color);
1443 make_button(wg.xright-text_width,wg.ytop+3*text_height+3,
1444 wgbutt,WG_SPUR_TOGGLE,'c');
1445 show_button(&wgbutt[WG_SPUR_TOGGLE],"c");
1446 button_color=7;
1447 settextcolor(7);
1448 }
1449 spur_search_first_point=wg_first_point;
1450 spur_search_last_point=wg_last_point;
1451 if(genparm[SECOND_FFT_ENABLE] != 0)
1452 {
1453 spur_search_first_point*=fft2_to_fft1_ratio;
1454 spur_search_last_point*=fft2_to_fft1_ratio;
1455 }
1456 autospur_point=spur_search_last_point;
1457 // *********** fft1 averaging number button ******************
1458 wgbutt[WG_FFT1_AVGNUM].x1=2+wg.xleft;
1459 wgbutt[WG_FFT1_AVGNUM].x2=2+wg.xleft+(11*text_width)/2;
1460 wgbutt[WG_FFT1_AVGNUM].y1=2+wg.yborder;
1461 wgbutt[WG_FFT1_AVGNUM].y2=2+wg.yborder+text_height;
1462 wgbutt[WG_WATERF_AVGNUM].x1=2+wg.xleft;
1463 wgbutt[WG_WATERF_AVGNUM].x2=2+wg.xleft+(9*text_width)/2;
1464 wgbutt[WG_WATERF_AVGNUM].y1=wg.yborder-text_height-2;
1465 wgbutt[WG_WATERF_AVGNUM].y2=wg.yborder-2;
1466 wgbutt[WG_WATERF_GAIN].x1=wg.xright-(9*text_width)/2-2;
1467 wgbutt[WG_WATERF_GAIN].x2=wg.xright-2;
1468 wgbutt[WG_WATERF_GAIN].y1=wg.yborder-2*text_height-4;
1469 wgbutt[WG_WATERF_GAIN].y2=wg.yborder-text_height-4;
1470 wgbutt[WG_WATERF_ZERO].x1=wg.xright-(11*text_width)/2-2;
1471 wgbutt[WG_WATERF_ZERO].x2=wg.xright-2;
1472 wgbutt[WG_WATERF_ZERO].y1=wg.yborder-text_height-2;
1473 wgbutt[WG_WATERF_ZERO].y2=wg.yborder-2;
1474 make_wg_yfac();
1475 make_modepar_file(GRAPHTYPE_WG);
1476 wg_flag=1;
1477 wg_waterf_block=(wg_waterf_y2-wg_waterf_y1+1)*wg_xpixels;
1478 make_wg_waterf_cfac();
1479 // Check if there are selected frequencies that are still
1480 // within the permitted range.
1481 // Place their cursors on screen and remove other selected frequencies.
1482 if(rx_mode != MODE_TXTEST && rx_mode != MODE_RADAR)
1483 {
1484 for(i=0; i<genparm[MIX1_NO_OF_CHANNELS]; i++)
1485 {
1486 mix1_curx[i]=-1;
1487 if( mix1_selfreq[i] > mix1_lowest_fq && mix1_selfreq[i]<mix1_highest_fq)
1488 {
1489 add_mix1_cursor(i);
1490 if(genparm[AFC_ENABLE] != 0)
1491 {
1492 for(j=0; j<max_fftxn; j++)
1493 {
1494 k=i*max_fftxn+j;
1495 if(mix1_fq_mid[k]<mix1_lowest_fq)mix1_fq_mid[k]=mix1_lowest_fq;
1496 if(mix1_fq_mid[k]>mix1_highest_fq)mix1_fq_mid[k]=mix1_highest_fq;
1497 }
1498 }
1499 }
1500 else
1501 {
1502 mix1_selfreq[i]=-1;
1503 new_mix1_curx[i]=-1;
1504 mix1_point[i]=-1;
1505 }
1506 }
1507 }
1508 if( (ui.network_flag&NET_RX_OUTPUT) != 0)
1509 {
1510 for(i=0; i<MAX_FREQLIST; i++)
1511 {
1512 netfreq_curx[i]=-1;
1513 }
1514 }
1515 wg_timestamp_counter=0;
1516 baseb_reset_counter++;
1517 if(rx_mode == MODE_TXTEST)txtest_init();
1518 //update_indicator();
1519 resume_thread(THREAD_SCREEN);
1520 sc[SC_WG_WATERF_INIT]++;
1521 sc[SC_WG_BUTTONS]++;
1522 sc[SC_WG_FQ_SCALE]++;
1523 }
1524
1525
wg_default(void)1526 void wg_default(void)
1527 {
1528 wg.check=WG_VERNR;
1529 wg.yrange=32768;
1530 wg.yzero=1;
1531 wg.waterfall_db_gain=.25;
1532 wg.waterfall_db_zero=20;
1533 wg.spek_avgnum=1+(int)(0.2/fft1_blocktime);
1534 if(wg.spek_avgnum > 800)wg.spek_avgnum=800;
1535 wg.fft_avg1num=wg.spek_avgnum/3;
1536 if(genparm[SECOND_FFT_ENABLE] == 0)
1537 {
1538 wg.waterfall_avgnum=2*wg.spek_avgnum;
1539 }
1540 else
1541 {
1542 wg.waterfall_avgnum=1+(int)(5/fft2_blocktime);
1543 }
1544 check_wg_fft_avgnum();
1545 }
1546
1547
wg_default_x(void)1548 void wg_default_x(void)
1549 {
1550 int i;
1551 float t1;
1552 // Make the default window for the wide graphs (spectrum and waterfall)
1553 wg.xleft=0;
1554 i=fft1_size+6*text_width-1;
1555 if(i > screen_width-1)i=screen_width-1;
1556 wg.xright=i;
1557 // Decide what range in fft1 points we want to place on the x-axis
1558 // Default is to show approximately half the spectrum.
1559 wg_first_xpixel=wg.xleft+4*text_width;
1560 wg_last_xpixel=wg.xright-2*text_width;
1561 wg_xpixels=wg_last_xpixel-wg_first_xpixel+1;
1562 t1=(0.5F*(float)fft1_size)/(float)wg_xpixels;
1563 if(t1 > 1)
1564 {
1565 wg.xpoints_per_pixel=(int)(t1+0.5F);
1566 wg.xpoints=wg.xpoints_per_pixel*wg_xpixels;
1567 wg.pixels_per_xpoint=0;
1568 }
1569 else
1570 {
1571 wg.pixels_per_xpoint=(int)(1.01F/t1);
1572 wg.xpoints=wg_xpixels/wg.pixels_per_xpoint;
1573 if(wg.pixels_per_xpoint == 1)
1574 {
1575 wg.xpoints_per_pixel=1;
1576 }
1577 else
1578 {
1579 wg.xpoints_per_pixel=0;
1580 }
1581 }
1582 wg.first_xpoint=(fft1_size-wg.xpoints)/3;
1583 if(wg.first_xpoint<0)lirerr(314);
1584 }
1585
wg_default_y(void)1586 void wg_default_y(void)
1587 {
1588 wg.ytop=0;
1589 wg.yborder=(int)(0.2F*(float)screen_height);
1590 wg.ybottom=(int)(0.35F*(float)screen_height);
1591 }
1592
1593
init_wide_graph()1594 void init_wide_graph()
1595 {
1596 if (read_modepar_file(GRAPHTYPE_WG) == 0)
1597 {
1598 wg_default();
1599 }
1600 if(wg.check!=WG_VERNR)wg_default();
1601 if(wg.xpoints_per_pixel*wg.pixels_per_xpoint > 1)wg_default_x();
1602 if(wg.first_xpoint < 0)wg_default_x();
1603 if(wg.first_xpoint+wg.xpoints > fft1_size)wg_default_x();
1604 if(wg.xleft<0 || wg.xleft > wg.xright-32-6*text_width)wg_default_x();
1605 if(wg.xright>=screen_width)wg_default_x();
1606 if(wg.ytop < 0 || wg.ytop >wg.ybottom-50)wg_default_y();
1607 if(wg.ybottom>=screen_height)wg_default_y();
1608 if(wg.yborder < wg.ytop+text_height+YBO ||
1609 wg.yborder > wg.ybottom-2*text_height)wg_default_y();
1610 wg.spur_inhibit &= 1;
1611 if(genparm[SECOND_FFT_ENABLE] != 0 && wg.pixels_per_xpoint>2)
1612 make_power_of_two(&wg.pixels_per_xpoint);
1613 check_wg_fft_avgnum();
1614 wide_graph_scro=no_of_scro;
1615 if(fft1_size < 32)
1616 {
1617 lir_status=LIR_PARERR;
1618 return;
1619 }
1620 wg_freq_adjustment_mode=0;
1621 make_wide_graph(FALSE);
1622 no_of_scro++;
1623 if(no_of_scro >= MAX_SCRO)lirerr(89);
1624 }
1625