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 #include <unistd.h>
24 #include <string.h>
25 #include <fcntl.h>
26
27 #include "globdef.h"
28 #include "uidef.h"
29 #include "fft1def.h"
30 #include "fft2def.h"
31 #include "fft3def.h"
32 #include "screendef.h"
33 #include "seldef.h"
34 #include "sigdef.h"
35 #include "rusage.h"
36 #include "thrdef.h"
37 #include "options.h"
38 #include "blnkdef.h"
39 #include "sdrdef.h"
40
41 #define MOUSE_MIN_TIME 0.05
42 #define NBPROC_FFT1 1
43 #define CHK_INACTIVE 0
44 #define CHK_ACTIVE 1
45
46
47 int thrnum_fft1b[MAX_FFT1_THREADS];
48 int inptr_fft1b[MAX_FFT1_THREADS];
49 int ptrchk_fft1b[MAX_FFT1_THREADS];
50 float* out_fft1b[MAX_FFT1_THREADS];
51 float* buf_fft1b[MAX_FFT1_THREADS];
52
53 extern void fix_prio(int n);
54
55
ttest(char c)56 void ttest(char c)
57 {
58 int i, j;
59 float *z;
60 float t1;
61 fprintf( dmp,"\n%c",c);
62 for(j=0; j<=fft1n_mask; j++)
63 {
64 z=&fft1_float[j*fft1_block];
65 t1=0;
66 for(i=fft1_size-500; i<fft1_size; i++)t1+=z[2*i]*z[2*i]+z[2*i+1]*z[2*i+1];
67 fprintf( dmp," %.1f",sqrt(t1)/20000000.);
68 }
69 }
70
71
72
compute_timf2_powersum(void)73 void compute_timf2_powersum(void)
74 {
75 int i;
76 float t1, t2;
77 while( ((timf2_pn2-timf2_pb+timf2_size)&timf2_mask) > timf2_blockpower_block)
78 {
79 i=timf2_pb;
80 timf2_pb=(timf2_pb+timf2_blockpower_block)&timf2_mask;
81 t1=0;
82 if(sw_onechan)
83 {
84 if( fft_cntrl[FFT1_BCKCURMODE].mmx == 0)
85 {
86 while(i != timf2_pb)
87 {
88 t1+=timf2_float[i ]*timf2_float[i ]+
89 timf2_float[i+1]*timf2_float[i+1];
90 i=(i+4)&timf2_mask;
91 }
92 }
93 else
94 {
95 while(i != timf2_pb)
96 {
97 t1+=(float)timf2_shi[i ]*(float)timf2_shi[i ]+
98 (float)timf2_shi[i+1]*(float)timf2_shi[i+1];
99 }
100 }
101 timf2_blockpower[timf2_blockpower_pa]=t1;
102 }
103 else
104 {
105 t2=0;
106 if( fft_cntrl[FFT1_BCKCURMODE].mmx == 0)
107 {
108 while(i != timf2_pb)
109 {
110 t1+=timf2_float[i ]*timf2_float[i ]+
111 timf2_float[i+1]*timf2_float[i+1];
112 t2+=timf2_float[i+2]*timf2_float[i+2]+
113 timf2_float[i+3]*timf2_float[i+3];
114 i=(i+8)&timf2_mask;
115 }
116 }
117 else
118 {
119 while(i != timf2_pb)
120 {
121 t1+=(float)timf2_shi[i ]*(float)timf2_shi[i ]+
122 (float)timf2_shi[i+1]*(float)timf2_shi[i+1];
123 t2+=(float)timf2_shi[i+2]*(float)timf2_shi[i+2]+
124 (float)timf2_shi[i+3]*(float)timf2_shi[i+3];
125 }
126 }
127 timf2_blockpower[2*timf2_blockpower_pa ]=t1;
128 timf2_blockpower[2*timf2_blockpower_pa+1]=t2;
129 }
130 timf2_blockpower_pa=(timf2_blockpower_pa+1)&timf2_blockpower_mask;
131 }
132 }
133
134
135
136
137 #if BUFBARS == TRUE
138 #define RX_INDICATOR_MAXNUM 8
139 int rx_indicator_maxpos[RX_INDICATOR_MAXNUM];
140 int rx_indicator_minpos[RX_INDICATOR_MAXNUM];
141 int bufbar_reset_no;
142 double bufbar_reset_time;
143
144
show_bufbar(int n,int k)145 void show_bufbar(int n, int k)
146 {
147 int ia, ib;
148 if(rx_indicator_minpos[n] > k || rx_indicator_maxpos[n] < k)
149 {
150 ia=rx_indicator_minpos[n];
151 if(ia > k)ia=k;
152 ib=rx_indicator_maxpos[n];
153 if(ib < k)ib=k;
154 lir_hline(indicator_first_pixel,indicator_ypix-4*n,
155 indicator_first_pixel+ia-1,15);
156 lir_hline(indicator_first_pixel+ia, indicator_ypix-4*n,
157 indicator_first_pixel+ib-1,12);
158 lir_hline(indicator_first_pixel+ib,indicator_ypix-4*n,
159 indicator_first_pixel+INDICATOR_SIZE-1,1);
160 rx_indicator_minpos[n]=ia;
161 rx_indicator_maxpos[n]=ib;
162 }
163 }
164
reset_bufbar_pos(void)165 void reset_bufbar_pos(void)
166 {
167 bufbar_reset_no++;
168 if(bufbar_reset_no >= RX_INDICATOR_MAXNUM)
169 {
170 bufbar_reset_no=-1;
171 bufbar_reset_time=recent_time;
172 return;
173 }
174 rx_indicator_maxpos[bufbar_reset_no]=-1;
175 rx_indicator_minpos[bufbar_reset_no]=0x8ffffff;
176 }
177 #endif
178
179
180
clear_baseb(void)181 void clear_baseb(void)
182 {
183 int i, n, m;
184 float raw_wttim,t1;
185 // We have to recalculate timf3 from old transforms.
186 // Find out how much time the data waiting before fft1 sums up to.
187 make_ad_wttim();
188 while(ad_wts > timf1_usebytes)
189 {
190 lir_sleep(3000);
191 make_ad_wttim();
192 }
193 raw_wttim=ad_wttim;
194 // We need a total delay from input sample to output sample
195 // that can accomodate the most unfavourable situation while collecting
196 // enough data to make a new transform.
197 // Make da_wait_time the desired number of seconds from input sample
198 // to output sample.
199 // First a safety margin for processing delay and adjusting speed
200 // errors in case different soundboards are used for input and output.
201 // All delays are not maximum simultaneously. Subtract 10 ms
202 // just in case...
203 da_wait_time=0.001*genparm[OUTPUT_DELAY_MARGIN];
204 // Maximum data waiting in timf3 that is not enough for a new fft3 transform
205 // plus the number of 50% interleaved transforms we want to wait.
206 da_wait_time+=fft3_size/timf3_sampling_speed;
207 t1=da_wait_time-raw_wttim+fft1_size/ui.rx_ad_speed;
208 // We use a window for fft3 so we need to recalculate
209 // fft3_interleave-points extra to get the first transform output right.
210 t1+=fft3_interleave_points/timf3_sampling_speed;
211 // make data for 0.1 seconds extra
212 t1+=.1;
213 if(genparm[SECOND_FFT_ENABLE]!=0)
214 {
215 // Add time for data waiting in timf2.
216 make_fft2_wttim();
217 raw_wttim+=timf2_wttim;
218 // Maximum data waiting in timf2 that is not enough for a new fft2 transform
219 da_wait_time+=fft2_size/timf1_sampling_speed;
220 sc[SC_HG_FQ_SCALE]++;
221 n=t1/fft2_blocktime;
222 if(fft2_blocktime > 0.25)n++;
223 if(genparm[AFC_ENABLE] != 0 &&
224 (rx_mode < MODE_SSB || rx_mode == MODE_AM || rx_mode == MODE_FM))
225 {
226 n+=afct_delay_points;
227 da_wait_time+=afct_delay_points*fft2_blocktime;
228 }
229 if(n > fft2_nm)n=fft2_nm;
230 if(n > max_fft2n-3)n=max_fft2n-3;
231 fft2_nx=(fft2_na-n+max_fft2n)&fft2n_mask;
232 fft2_nc=fft2_nx;
233 new_fft2_averages();
234 }
235 else
236 {
237 // Maximum raw data waiting that is not enough for a new fft1 transform
238 m=fft1_size*(fft_cntrl[FFT1_CURMODE].real2complex+1)*
239 fft_cntrl[FFT1_CURMODE].parall_fft;
240 //m=fft1_size;
241
242 da_wait_time+=m/timf1_sampling_speed;
243 n=t1/fft1_blocktime;
244 if(fft1_blocktime > 0.25)n++;
245 if(genparm[AFC_ENABLE] != 0)
246 {
247 n+=afct_delay_points;
248 da_wait_time+=afct_delay_points*fft1_blocktime;
249 }
250 i=fft1_nx;
251 if(n > max_fft1n-3)n=max_fft1n-3;
252 if(n>fft1_nm)n=fft1_nm;
253 fft1_nx=(fft1_na-n+max_fft1n)&fft1n_mask;
254 fft1_nc=fft1_nx;
255 fft1_px=fft1_nx*fft1_block;
256 }
257 timf3_pa=0;
258 timf3_px=0;
259 timf3_py=0;
260 timf3_ps=0;
261 for(i=0;i<timf3_block;i++)timf3_float[i]=0;
262 basebnet_pa=0;
263 basebnet_px=0;
264 basebrawnet_pa=0;
265 basebrawnet_px=0;
266
267 da_resample_ratio=genparm[DA_OUTPUT_SPEED]/baseband_sampling_speed;
268 new_da_resample_ratio=da_resample_ratio;
269 for(i=0; i<genparm[MIX1_NO_OF_CHANNELS]; i++)
270 {
271 mix1_status[i]=0;
272 }
273 old_afct_delay=afct_delay_points;
274 poleval_pointer=0;
275 clear_coherent();
276 }
277
278 int local_spurcancel_flag;
279 int local_spurinit_flag;
280
spur_removal(void)281 void spur_removal(void)
282 {
283 int i, k, m, mm;
284 double dt1;
285 float t2, t3;
286 k=0;
287 if(genparm[AFC_ENABLE] == 2 && wg.spur_inhibit == 0)
288 {
289 if(autospur_point < spur_search_last_point)
290 {
291 t2=1/snd[RXAD].interrupt_rate;
292 t3=0.1*fftx_size/ui.rx_ad_speed;
293 if(t2<t3)t2=t3;
294 dt1=current_time();
295 m=512;
296 mm=16;
297 if(m < fftx_size/1024)m=fftx_size/1024;
298 if(mm < genparm[MAX_NO_OF_SPURS]/100)mm=genparm[MAX_NO_OF_SPURS]/100;
299 more_spurs:;
300 i=no_of_spurs;
301 k=0;
302 lir_sched_yield();
303 while( k<m && autospur_point < spur_search_last_point &&
304 no_of_spurs-i < mm)
305 {
306 init_spur_elimination();
307 k++;
308 }
309 if(autospur_point < spur_search_last_point)
310 {
311 if(current_time()-dt1 < t2)goto more_spurs;
312 }
313 }
314 }
315 if(local_spurinit_flag != spurinit_flag)
316 {
317 local_spurinit_flag=spurinit_flag;
318 init_spur_elimination();
319 }
320 if(local_spurcancel_flag != spurcancel_flag)
321 {
322 local_spurcancel_flag=spurcancel_flag;
323 no_of_spurs=0;
324 }
325 }
326
second_fft(void)327 void second_fft(void)
328 {
329 int m;
330 #if RUSAGE_OLD == TRUE
331 int local_workload_counter;
332 #endif
333 #if BUFBARS == TRUE
334 int k;
335 #endif
336 #if OSNUM == OSNUM_LINUX
337 clear_thread_times(THREAD_SECOND_FFT);
338 #endif
339 #if RUSAGE_OLD == TRUE
340 local_workload_counter=workload_counter;
341 #endif
342 thread_status_flag[THREAD_SECOND_FFT]=THRFLAG_ACTIVE;
343 while(!kill_all_flag &&
344 thread_command_flag[THREAD_SECOND_FFT] == THRFLAG_ACTIVE)
345 {
346 #if RUSAGE_OLD == TRUE
347 if(local_workload_counter != workload_counter)
348 {
349 local_workload_counter=workload_counter;
350 make_thread_times(THREAD_SECOND_FFT);
351 }
352 #endif
353 restart:;
354 m=0;
355 while( ((timf2_pn2-timf2_px+timf2_size)&timf2_mask) <
356 4*ui.rx_rf_channels*fft2_size )
357 {
358 m=1;
359 thread_status_flag[THREAD_SECOND_FFT]=THRFLAG_SEM_WAIT;
360 lir_await_event(EVENT_FFT2);
361 thread_status_flag[THREAD_SECOND_FFT]=THRFLAG_ACTIVE;
362 if(kill_all_flag || thread_command_flag[THREAD_SECOND_FFT] !=
363 THRFLAG_ACTIVE)goto fft2_x;
364 }
365 if(yieldflag_fft2_fft2 && m==0)lir_sched_yield();
366 // Add the two parts of timf2 so we get a single time function
367 // and produce the second fft.
368 // Note that the fft2 routine still is split into a number of small
369 // chunks so we have to call until the flag is set.
370 make_fft2_status=FFT2_NOT_ACTIVE;
371 while(make_fft2_status != FFT2_COMPLETE)
372 {
373 make_fft2();
374 if(yieldflag_fft2_fft2)lir_sched_yield();
375 }
376 if(genparm[AFC_ENABLE] >= 1)
377 {
378 ffts_na=fft2_na;
379 ffts_nm=fft2_nm;
380 spur_removal();
381 }
382 if(fft1_waterfall_flag)
383 {
384 if(recent_time-fft1_show_time > 0.05)
385 {
386 fft1_show_time=recent_time;
387 sc[SC_SHOW_FFT1]++;
388 lir_set_event(EVENT_SCREEN);
389 }
390 }
391 lir_set_event(EVENT_FFT1_READY);
392 #if BUFBARS == TRUE
393 if(timinfo_flag!=0)
394 {
395 k=(fft2_na-fft2_nx+max_fft2n)&fft2n_mask;
396 k*=fft2_size;
397 k/=fft2n_indicator_block;
398 show_bufbar(3,k);
399 }
400 #endif
401 }
402 if(thread_command_flag[THREAD_SECOND_FFT]==THRFLAG_IDLE)
403 {
404 thread_status_flag[THREAD_SECOND_FFT]=THRFLAG_IDLE;
405 while(thread_command_flag[THREAD_SECOND_FFT] == THRFLAG_IDLE)
406 {
407 lir_sleep(3000);
408 }
409 if(kill_all_flag) goto fft2_x;
410 if(thread_command_flag[THREAD_SECOND_FFT] == THRFLAG_ACTIVE)goto restart;
411 }
412 fft2_x:;
413 thread_status_flag[THREAD_SECOND_FFT]=THRFLAG_RETURNED;
414 while(thread_command_flag[THREAD_SECOND_FFT] != THRFLAG_NOT_ACTIVE)
415 {
416 lir_sleep(1000);
417 }
418 }
419
do_fft1_c(void)420 void do_fft1_c(void)
421 {
422 #if BUFBARS == TRUE
423 int i;
424 #endif
425 fft1_c();
426 #if BUFBARS == TRUE
427 if(timinfo_flag!=0)
428 {
429 i=(fft1_pa+fft1_block-fft1_px+fft1_mask+1)&fft1_mask;
430 i/=fft1_indicator_block;
431 show_bufbar(1,i);
432 }
433 #endif
434 }
435
do_fft1c(void)436 void do_fft1c(void)
437 {
438 int k;
439 #if OSNUM == OSNUM_LINUX
440 clear_thread_times(THREAD_DO_FFT1C);
441 //fix_prio(THREAD_DO_FFT1C);
442 #endif
443 thread_status_flag[THREAD_DO_FFT1C]=THRFLAG_ACTIVE;
444 while(!kill_all_flag &&
445 thread_command_flag[THREAD_DO_FFT1C] == THRFLAG_ACTIVE)
446 {
447 lir_await_event(EVENT_DO_FFT1C);
448 if(fft1_na != fft1_nb)
449 {
450 k=0;
451 while(fft1_na != fft1_nb)
452 {
453 do_fft1_c();
454 k++;
455 if(k == fft1_muln)
456 {
457 lir_set_event(EVENT_FFT1_READY);
458 k=0;
459 }
460 }
461 if(k != 0)
462 {
463 lir_set_event(EVENT_FFT1_READY);
464 }
465 if(fft1_waterfall_flag)
466 {
467 fft1_waterfall();
468 if(recent_time-fft1_show_time > 0.05)
469 {
470 fft1_show_time=recent_time;
471 sc[SC_SHOW_FFT1]++;
472 lir_set_event(EVENT_SCREEN);
473 }
474 }
475 }
476 }
477 thread_status_flag[THREAD_DO_FFT1C]=THRFLAG_RETURNED;
478 }
479
timf2_routine(void)480 void timf2_routine(void)
481 {
482 #if RUSAGE_OLD == TRUE
483 int local_workload_counter;
484 #endif
485 #if BUFBARS == TRUE
486 int k;
487 #endif
488 #if OSNUM == OSNUM_LINUX
489 clear_thread_times(THREAD_TIMF2);
490 #endif
491 #if RUSAGE_OLD == TRUE
492 local_workload_counter=workload_counter;
493 #endif
494 thread_status_flag[THREAD_TIMF2]=THRFLAG_ACTIVE;
495 while(!kill_all_flag &&
496 thread_command_flag[THREAD_TIMF2] == THRFLAG_ACTIVE)
497 {
498 #if RUSAGE_OLD == TRUE
499 if(local_workload_counter != workload_counter)
500 {
501 local_workload_counter=workload_counter;
502 make_thread_times(THREAD_TIMF2);
503 }
504 #endif
505 restart:;
506 thread_status_flag[THREAD_TIMF2]=THRFLAG_SEM_WAIT;
507 lir_await_event(EVENT_TIMF2);
508 thread_status_flag[THREAD_TIMF2]=THRFLAG_ACTIVE;
509 if(kill_all_flag || thread_command_flag[THREAD_TIMF2] !=
510 THRFLAG_ACTIVE)goto timf2_x;
511 while(fft1_px != fft1_pa && (timf2_px-timf2_pa+timf2_mask+1)>fft1_block)
512 {
513 while(fft1_na != fft1_nb)
514 {
515 do_fft1_c();
516 make_timf2();
517 }
518 #if BUFBARS == TRUE
519 if(timinfo_flag!=0)
520 {
521 k=(timf2_pa+fft1_block-timf2_px+timf2_mask+1)&timf2_mask;
522 k/=timf2_indicator_block;
523 show_bufbar(2,k);
524 }
525 #endif
526 if(yieldflag_timf2_fft1)lir_sched_yield();
527 first_noise_blanker();
528 lir_sched_yield();
529 if( ((timf2_pn2-timf2_px+timf2_size)&timf2_mask) >=
530 4*ui.rx_rf_channels*fft2_size )
531 {
532 lir_set_event(EVENT_FFT2);
533 }
534 if(mg.scale_type == MG_SCALE_STON)compute_timf2_powersum();
535 }
536 }
537 if(thread_command_flag[THREAD_TIMF2]==THRFLAG_IDLE)
538 {
539 thread_status_flag[THREAD_TIMF2]=THRFLAG_IDLE;
540 while(thread_command_flag[THREAD_TIMF2] == THRFLAG_IDLE)
541 {
542 lir_sleep(3000);
543 }
544 if(kill_all_flag) goto timf2_x;
545 if(thread_command_flag[THREAD_TIMF2] == THRFLAG_ACTIVE)goto restart;
546 }
547 timf2_x:;
548 thread_status_flag[THREAD_TIMF2]=THRFLAG_RETURNED;
549 while(thread_command_flag[THREAD_TIMF2] != THRFLAG_NOT_ACTIVE)
550 {
551 lir_sleep(1000);
552 }
553 }
554
mouse_rightpressed_dummy(void)555 void mouse_rightpressed_dummy(void)
556 {
557 // See wide_graph_add_signal()
558
559 if(rightpressed==BUTTON_RELEASED)
560 {
561 sc[SC_WG_WATERF_REDRAW]++;
562 rightpressed=BUTTON_IDLE;
563 mouse_task=-1;
564 }
565 }
566
567
do_fft1b(void)568 void do_fft1b(void)
569 {
570 int i, thread_no, event_no;
571 i=0;
572 thread_no=THREAD_FFT1B1;
573 while(thrnum_fft1b[i] != -1)
574 {
575 i++;
576 thread_no++;
577 }
578 thrnum_fft1b[i]=thread_no;
579 #if OSNUM == OSNUM_LINUX
580 clear_thread_times(thread_no);
581 //fix_prio(thread_no);
582 #endif
583 event_no=EVENT_DO_FFT1B1+i;
584 while( thread_command_flag[thread_no] == THRFLAG_ACTIVE)
585 {
586 thread_status_flag[thread_no]=THRFLAG_SEM_WAIT;
587 if(kill_all_flag)goto xx;
588 lir_await_event(event_no);
589 if(kill_all_flag)goto xx;
590 thread_status_flag[thread_no]=THRFLAG_ACTIVE;
591 lir_sched_yield();
592 fft1_b(inptr_fft1b[i],out_fft1b[i],buf_fft1b[i]);
593 thread_status_flag[thread_no]=THRFLAG_IDLE;
594 lir_sched_yield();
595 if(kill_all_flag)goto xx;
596 lir_set_event(EVENT_TIMF1);
597 lir_await_event(event_no);
598 }
599 xx:;
600 thread_status_flag[thread_no]=THRFLAG_RETURNED;
601 while(thread_command_flag[thread_no] != THRFLAG_NOT_ACTIVE)
602 {
603 lir_sleep(1000);
604 }
605 }
606
wideband_dsp(void)607 void wideband_dsp(void)
608 {
609 #if RUSAGE_OLD == TRUE
610 int local_workload_counter;
611 #endif
612 int i, k, m;
613 int fft1_pt, fft1_nz;
614 int timf1_overload_ticks;
615 int timf1_overload_count;
616 int local_ampinfo_reset;
617 int waitflag;
618 char s[80];
619 float t1;
620 #if OSNUM == OSNUM_LINUX
621 clear_thread_times(THREAD_WIDEBAND_DSP);
622 #endif
623 #if RUSAGE_OLD == TRUE
624 local_workload_counter=workload_counter;
625 #endif
626 // Allow this thread to use 100% of one CPU if the computer has
627 // more than one CPU and FFT2 is not selected.
628 // If FFT2 is selected and we have more than 3 CPUs we can
629 // also run this thread without yeilds.
630 local_ampinfo_reset=workload_reset_flag;
631 local_spurcancel_flag=spurcancel_flag;
632 local_spurinit_flag=spurinit_flag;
633 if(fft1_n > 12)
634 {
635 yieldflag_timf2_fft1=TRUE;
636 }
637 else
638 {
639 yieldflag_timf2_fft1=TRUE;
640 }
641 while(!kill_all_flag && timf1p_px==timf1p_pb)
642 {
643 lir_await_event(EVENT_TIMF1);
644 }
645 if(kill_all_flag)goto wide_error_exit;
646 if( genparm[SECOND_FFT_ENABLE] != 0 )
647 {
648 linrad_thread_create(THREAD_SECOND_FFT);
649 if(ui.max_blocked_cpus > 4)yieldflag_timf2_fft1=FALSE;
650 if(no_of_processors > 1)
651 {
652 linrad_thread_create(THREAD_TIMF2);
653 }
654 }
655 else
656 {
657 if(ui.max_blocked_cpus > 2)yieldflag_timf2_fft1=FALSE;
658 if(no_of_processors > 1)
659 {
660 linrad_thread_create(THREAD_DO_FFT1C);
661 while(thread_status_flag[THREAD_DO_FFT1C] != THRFLAG_ACTIVE)lir_sleep(1000);
662 }
663 }
664 if(no_of_fft1b > 0)
665 {
666 for(i=0; i<MAX_FFT1_THREADS; i++)
667 {
668 thrnum_fft1b[i]=-1;
669 ptrchk_fft1b[i]=CHK_INACTIVE;
670 }
671 lir_sched_yield();
672 for(i=0; i<no_of_fft1b; i++)
673 {
674 linrad_thread_create(THREAD_FFT1B1+i);
675 while(thread_status_flag[THREAD_FFT1B1+i] != THRFLAG_SEM_WAIT &&
676 thread_status_flag[THREAD_FFT1B1+i] != THRFLAG_RETURNED )
677 {
678 lir_sleep(3000);
679 }
680 }
681 }
682 if(kill_all_flag)goto wide_error_exit;
683 if(thread_command_flag[THREAD_SCREEN]!=THRFLAG_NOT_ACTIVE)
684 {
685 while(thread_status_flag[THREAD_SCREEN]!=THRFLAG_ACTIVE &&
686 thread_status_flag[THREAD_SCREEN]!=THRFLAG_IDLE &&
687 thread_status_flag[THREAD_SCREEN]!=THRFLAG_SEM_WAIT)
688 {
689 if(thread_command_flag[THREAD_WIDEBAND_DSP] ==
690 THRFLAG_KILL)goto wide_error_exit;
691 lir_sleep(10000);
692 if(kill_all_flag)goto wide_error_exit;
693 }
694 }
695 restart:;
696 k=0;
697 restart_2:;
698 lir_sched_yield();
699 timf1p_px=timf1p_pb;
700 fft1_pt=fft1_pa;
701 if( (ui.network_flag & NET_RXIN_FFT1) == 0)
702 {
703 while(!kill_all_flag && timf1p_px==timf1p_pb)
704 {
705 lir_await_event(EVENT_TIMF1);
706 }
707 k++;
708 if(k<3)goto restart_2;
709 }
710 lir_sched_yield();
711 timf1p_px=timf1p_pb;
712 mouse_time_wide=current_time();
713 timf1_overload_ticks=0;
714 timf1_overload_count=0;
715 thread_status_flag[THREAD_WIDEBAND_DSP]=THRFLAG_ACTIVE;
716 waitflag=0;
717 fft1_nz=-1;
718 while(!kill_all_flag &&
719 thread_command_flag[THREAD_WIDEBAND_DSP] == THRFLAG_ACTIVE)
720 {
721 if(ampinfo_flag != 0)
722 {
723 if(local_ampinfo_reset!=workload_reset_flag)
724 {
725 local_ampinfo_reset=workload_reset_flag;
726 clear_wide_maxamps();
727 }
728 }
729 #if RUSAGE_OLD == TRUE
730 if(local_workload_counter != workload_counter)
731 {
732 local_workload_counter=workload_counter;
733 make_thread_times(THREAD_WIDEBAND_DSP);
734 }
735 #endif
736 if( (ui.network_flag & NET_RXIN_FFT1) == 0)
737 {
738 if( ((timf1p_pb-timf1p_px+timf1_bytes)&timf1_bytemask)
739 < timf1_blockbytes &&
740 genparm[AFC_ENABLE] >= 1 && genparm[SECOND_FFT_ENABLE] == 0)
741 {
742 spur_removal();
743 }
744 await_event:;
745 if(kill_all_flag || thread_command_flag[THREAD_WIDEBAND_DSP] !=
746 THRFLAG_ACTIVE)goto wideend;
747 if(((timf1p_pb-timf1p_px+timf1_bytes)&timf1_bytemask) < timf1_blockbytes)
748 {
749 if(mouse_task==-1 || (mouse_task&GRAPH_MASK) >= MAX_WIDEBAND_GRAPHS)
750 {
751 thread_status_flag[THREAD_WIDEBAND_DSP]=THRFLAG_SEM_WAIT;
752 lir_await_event(EVENT_TIMF1);
753 waitflag=0;
754 thread_status_flag[THREAD_WIDEBAND_DSP]=THRFLAG_ACTIVE;
755 goto await_event;
756 }
757 else
758 {
759 t1=current_time()-mouse_time_wide;
760 if(t1 <= MOUSE_MIN_TIME)
761 {
762 t1=MOUSE_MIN_TIME-t1;
763 if(t1 > 0.25/snd[RXAD].interrupt_rate)t1=0.25/snd[RXAD].interrupt_rate;
764 lir_sleep(1000000*t1);
765 goto await_event;
766 }
767 }
768 }
769 else
770 {
771 if(no_of_fft1b == 0)
772 {
773 lir_sched_yield();
774 }
775 else
776 {
777 k=0;
778 for(i=0; i<no_of_fft1b; i++)
779 {
780 if(thread_status_flag[THREAD_FFT1B1+i] != THRFLAG_ACTIVE)k=1;
781 }
782 if(k==0)
783 {
784 thread_status_flag[THREAD_WIDEBAND_DSP]=THRFLAG_SEM_WAIT;
785 lir_await_event(EVENT_TIMF1);
786 waitflag=0;
787 thread_status_flag[THREAD_WIDEBAND_DSP]=THRFLAG_ACTIVE;
788 goto await_event;
789 }
790
791 if(waitflag != 0)
792 {
793 lir_sleep(10);
794 }
795 }
796 }
797 i=snd[RXAD].block_bytes;
798 if(ui.rx_addev_no >= 256 && ui.rx_addev_no < SPECIFIC_DEVICE_CODES)i<<=1;
799 k=(timf1p_pa-timf1p_px+timf1_bytes)&timf1_bytemask;
800 k/=(i+timf1_blockbytes);
801 if(audio_dump_flag == 0 && k > 5+2*no_of_fft1b)
802 {
803 timf1_overload_ticks++;
804 if(timf1_overload_ticks > snd[RXAD].interrupt_rate )
805 {
806 timf1_overload_count++;
807 sprintf(s,"BUFFER ERROR (timf1) %d",timf1_overload_count);
808 wg_error(s,WGERR_TIMF1_OVERLOAD);
809 timf1_overload_ticks=0;
810 }
811 }
812 else
813 {
814 timf1_overload_ticks=0;
815 }
816 }
817 else
818 {
819 if(genparm[AFC_ENABLE] >= 1 && genparm[SECOND_FFT_ENABLE] == 0)
820 {
821 spur_removal();
822 }
823 await_netevent:;
824 if(fft1_na == fft1_nb)
825 {
826 thread_status_flag[THREAD_WIDEBAND_DSP]=THRFLAG_SEM_WAIT;
827 lir_await_event(EVENT_TIMF1);
828 thread_status_flag[THREAD_WIDEBAND_DSP]=THRFLAG_ACTIVE;
829 }
830 }
831 if(kill_all_flag || thread_command_flag[THREAD_WIDEBAND_DSP] !=
832 THRFLAG_ACTIVE)goto wideend;
833 // Here we do the mouse actions that affect the wide graph.
834 // Currently only the waterfall memory area may become re-allocated
835 if(recent_time-mouse_time_wide > MOUSE_MIN_TIME)
836 {
837 mouse_time_wide=current_time();
838 if(mouse_task!=-1)
839 {
840 k=mouse_task&GRAPH_MASK;
841 if( k < MAX_WIDEBAND_GRAPHS)
842 {
843 set_button_states();
844 if(mouse_active_flag == 0)
845 {
846 switch (k)
847 {
848 case WIDE_GRAPH:
849 if( (mouse_task&GRAPH_RIGHTPRESSED) != 0)
850 {
851 wide_graph_add_signal();
852 if(rightpressed==BUTTON_IDLE)mouse_task=-1;
853 goto mouse_x;
854 }
855 else
856 {
857 mouse_on_wide_graph();
858 }
859 break;
860
861 case HIRES_GRAPH:
862 if( (mouse_task&GRAPH_RIGHTPRESSED) != 0)
863 {
864 mouse_rightpressed_dummy();
865 if(rightpressed==BUTTON_IDLE)mouse_task=-1;
866 goto mouse_x;
867 }
868 else
869 {
870 mouse_on_hires_graph();
871 }
872 break;
873
874 case TRANSMIT_GRAPH:
875 if( (mouse_task&GRAPH_RIGHTPRESSED) != 0)
876 {
877 mouse_rightpressed_dummy();
878 if(rightpressed==BUTTON_IDLE)mouse_task=-1;
879 goto mouse_x;
880 }
881 else
882 {
883 mouse_on_tx_graph();
884 }
885 break;
886
887 case FREQ_GRAPH:
888 mouse_on_freq_graph();
889 break;
890
891 case RADAR_GRAPH:
892 if( (mouse_task&GRAPH_RIGHTPRESSED) != 0)
893 {
894 mouse_rightpressed_dummy();
895 if(rightpressed==BUTTON_IDLE)mouse_task=-1;
896 goto mouse_x;
897 }
898 else
899 {
900 mouse_on_radar_graph();
901 }
902 break;
903 }
904 if(mouse_active_flag == 0)
905 {
906 lirerr(28877);
907 goto wide_error_exit;
908 }
909 }
910 if(numinput_flag==0)
911 {
912 current_mouse_activity();
913 if(kill_all_flag)goto wide_error_exit;
914 }
915 if( (numinput_flag&DATA_READY_PARM) != 0)
916 {
917 par_from_keyboard_routine();
918 if(kill_all_flag)goto wide_error_exit;
919 par_from_keyboard_routine=NULL;
920 mouse_active_flag=0;
921 numinput_flag=0;
922 leftpressed=BUTTON_IDLE;
923 rightpressed=BUTTON_IDLE;
924 }
925 if(mouse_active_flag == 0)
926 {
927 mouse_task=-1;
928 }
929 mouse_x:;
930 }
931 }
932 }
933 if(kill_all_flag) goto wide_error_exit;
934 if( (ui.network_flag & NET_RXIN_FFT1) == 0)
935 {
936 if( ((timf1p_pb-timf1p_px+timf1_bytes)&timf1_bytemask) <
937 timf1_blockbytes)
938 {
939 if(no_of_fft1b == 0)
940 {
941 goto wideend;
942 }
943 else
944 {
945 goto fft1_b_results;
946 }
947 }
948 #if BUFBARS == TRUE
949 if(timinfo_flag!=0)
950 {
951 k=snd[RXAD].block_bytes;
952 if(ui.rx_addev_no >= 256 && ui.rx_addev_no < SPECIFIC_DEVICE_CODES)k<<=1;
953 k=(timf1p_pa+k-timf1p_px+timf1_bytes)&timf1_bytemask;
954 k/=timf1_indicator_block;
955 show_bufbar(0,k);
956 }
957 #endif
958 if(computation_pause_flag != 0)
959 {
960 timf1p_px=(timf1p_px+timf1_blockbytes)&timf1_bytemask;
961 goto await_event;
962 }
963 else
964 {
965 if(no_of_fft1b > 0)
966 {
967 // We are doing the bulk of the FFT work, fft1_b, in one or more
968 // separate threads. We now have a pointer to a new set of
969 // input data at timf1p_px. Find a free thread to give the task.
970 if(kill_all_flag || thread_command_flag[THREAD_WIDEBAND_DSP] !=
971 THRFLAG_ACTIVE)goto wideend;
972 i=0;
973 lir_sched_yield();
974 while(i < no_of_fft1b && ((timf1p_pb-timf1p_px+timf1_bytes)&
975 timf1_bytemask) >=timf1_blockbytes)
976 {
977 if(ptrchk_fft1b[i] == CHK_INACTIVE &&
978 thread_status_flag[THREAD_FFT1B1+i] == THRFLAG_SEM_WAIT)
979 {
980 // There is a thread waiting for the task.
981 ptrchk_fft1b[i]=CHK_ACTIVE;
982 inptr_fft1b[i]=timf1p_px;
983 timf1p_px=(timf1p_px+timf1_blockbytes)&timf1_bytemask;
984 out_fft1b[i]=&fft1_float[fft1_pt];
985 fft1_pt=(fft1_pt+fft1_mulblock)&fft1_mask;
986 buf_fft1b[i]=&fftw_tmp[i*(fft1_tmp_bytes/sizeof(float)+4)];
987 lir_set_event(EVENT_DO_FFT1B1+i);
988 waitflag=1;
989 }
990 i++;
991 }
992 // ********************************************************************
993 fft1_b_results:
994 if(kill_all_flag || thread_command_flag[THREAD_WIDEBAND_DSP] !=
995 THRFLAG_ACTIVE)goto wideend;
996 // Find the oldest fft1_b computation.
997 m=-1;
998 k=-1;
999 lir_sched_yield();
1000 for(i=0; i<no_of_fft1b; i++)
1001 {
1002 if( ((timf1p_px-inptr_fft1b[i] +
1003 timf1_bytes)&timf1_bytemask) > m)
1004 {
1005 m=(timf1p_px-inptr_fft1b[i]+timf1_bytes)&timf1_bytemask;
1006 k=i;
1007 }
1008 }
1009 if(k >= 0 && ptrchk_fft1b[k] == CHK_ACTIVE &&
1010 thread_status_flag[THREAD_FFT1B1+k] == THRFLAG_IDLE)
1011 {
1012 ptrchk_fft1b[k]=CHK_INACTIVE;
1013 lir_set_event(EVENT_DO_FFT1B1+k);
1014 waitflag=1;
1015 if( (ui.network_flag&NET_RXOUT_FFT1) != 0)
1016 {
1017 memcpy(&fft1_netsend_buffer[fft1net_pa],
1018 &fft1_float[fft1_pa],(unsigned int)fft1_mulblock);
1019 fft1net_pa=(fft1net_pa+fft1_blockbytes)&fft1net_mask;
1020 }
1021 fft1_pa=(fft1_pa+fft1_mulblock)&fft1_mask;
1022 goto fft1_b_results;
1023 }
1024 }
1025 else
1026 {
1027 fft1_b(timf1p_px, &fft1_float[fft1_pa], fftw_tmp);
1028 timf1p_px=(timf1p_px+timf1_blockbytes)&timf1_bytemask;
1029 if( (ui.network_flag&NET_RXOUT_FFT1) != 0)
1030 {
1031 memcpy(&fft1_netsend_buffer[fft1net_pa],
1032 &fft1_float[fft1_pa],(unsigned int)fft1_mulblock);
1033 fft1net_pa=(fft1net_pa+fft1_blockbytes)&fft1net_mask;
1034 }
1035 fft1_pa=(fft1_pa+fft1_mulblock)&fft1_mask;
1036 }
1037 fft1_na=fft1_pa/fft1_block;
1038 if(fft1_nm != fft1n_mask)fft1_nm++;
1039 //ttest('A');
1040 }
1041 }
1042 else
1043 {
1044 if(fft1_na == fft1_nb)goto wideend;
1045 }
1046 if(genparm[SECOND_FFT_ENABLE] == 0 )
1047 {
1048 if(no_of_processors > 1)
1049 {
1050 if(fft1_nz != fft1_pa)
1051 {
1052 lir_set_event(EVENT_DO_FFT1C);
1053 waitflag=1;
1054 fft1_nz=fft1_pa;
1055 }
1056 }
1057 else
1058 {
1059 while(fft1_na != fft1_nb)
1060 {
1061 do_fft1_c();
1062 }
1063 if(fft1_waterfall_flag)
1064 {
1065 fft1_waterfall();
1066 if(recent_time-fft1_show_time > 0.05)
1067 {
1068 fft1_show_time=recent_time;
1069 sc[SC_SHOW_FFT1]++;
1070 lir_set_event(EVENT_SCREEN);
1071 }
1072 }
1073 }
1074 lir_set_event(EVENT_FFT1_READY);
1075 }
1076 else
1077 {
1078 if(no_of_processors > 1)
1079 {
1080 lir_set_event(EVENT_TIMF2);
1081 lir_sched_yield();
1082 }
1083 else
1084 {
1085 while(fft1_na != fft1_nb)
1086 {
1087 do_fft1_c();
1088 if(yieldflag_timf2_fft1)lir_sched_yield();
1089 make_timf2();
1090 }
1091 #if BUFBARS == TRUE
1092 if(timinfo_flag!=0)
1093 {
1094 k=(timf2_pa+fft1_block-timf2_px+timf2_size)&timf2_mask;
1095 k/=timf2_indicator_block;
1096 show_bufbar(2,k);
1097 }
1098 #endif
1099 first_noise_blanker();
1100 lir_sched_yield();
1101 if( ((timf2_pn2-timf2_px+timf2_size)&timf2_mask) >=
1102 4*ui.rx_rf_channels*fft2_size )
1103 {
1104 lir_set_event(EVENT_FFT2);
1105 }
1106 if(mg.scale_type == MG_SCALE_STON)compute_timf2_powersum();
1107 }
1108 }
1109 if( (ui.network_flag & NET_RXIN_FFT1) != 0)
1110 {
1111 if(fft1_na != fft1_nb)goto await_netevent;
1112 }
1113 wideend:;
1114 }
1115 // ********************************************************************
1116 if(thread_command_flag[THREAD_WIDEBAND_DSP]==THRFLAG_IDLE)
1117 {
1118 // The wideband dsp thread is running and it puts out
1119 // the waterfall graph.
1120 // We stop it now on order from the tx_test thread.
1121 thread_status_flag[THREAD_WIDEBAND_DSP]=THRFLAG_IDLE;
1122 while(thread_command_flag[THREAD_WIDEBAND_DSP]==THRFLAG_IDLE)
1123 {
1124 lir_await_event(EVENT_TIMF1);
1125 timf1p_px=(timf1p_px+timf1_blockbytes)&timf1_bytemask;
1126 }
1127 if(thread_command_flag[THREAD_WIDEBAND_DSP] == THRFLAG_ACTIVE)goto restart;
1128 }
1129 wide_error_exit:;
1130 if( genparm[SECOND_FFT_ENABLE] != 0 )
1131 {
1132 linrad_thread_stop_and_join(THREAD_SECOND_FFT);
1133 if(no_of_processors > 1)
1134 {
1135 linrad_thread_stop_and_join(THREAD_TIMF2);
1136 }
1137 }
1138 else
1139 {
1140 if(no_of_processors > 1)
1141 {
1142 linrad_thread_stop_and_join(THREAD_DO_FFT1C);
1143 }
1144 }
1145 if(no_of_fft1b > 0)
1146 {
1147 for(i=0; i<no_of_fft1b; i++)
1148 {
1149 linrad_thread_stop_and_join(THREAD_FFT1B1+i);
1150 }
1151 }
1152 thread_status_flag[THREAD_WIDEBAND_DSP]=THRFLAG_RETURNED;
1153 while(thread_command_flag[THREAD_WIDEBAND_DSP] != THRFLAG_NOT_ACTIVE)
1154 {
1155 lir_sleep(1000);
1156 }
1157 }
1158
narrowband_dsp(void)1159 void narrowband_dsp(void)
1160 {
1161 #if RUSAGE_OLD == TRUE
1162 int local_workload_counter;
1163 #endif
1164 int fftx_flag;
1165 int local_baseb_reset_counter;
1166 int i, k;
1167 int idle_flag;
1168 int local_bg_update_filter;
1169 double dt1;
1170 double total_time1, idle_time, baseb_clear_time;
1171 float t1;
1172 int fft3_overload_ticks;
1173 int fft3_overload_count;
1174 char s[80];
1175 #if OSNUM == OSNUM_LINUX
1176 clear_thread_times(THREAD_NARROWBAND_DSP);
1177 #endif
1178 #if RUSAGE_OLD == TRUE
1179 local_workload_counter=workload_counter;
1180 #endif
1181 ampinfo_reset=workload_reset_flag;
1182 fft3_overload_ticks=0;
1183 fft3_overload_count=0;
1184 new_baseb_flag=-1;
1185 total_time1=current_time();
1186 dt1=total_time1;
1187 mouse_time_narrow=total_time1;
1188 idle_time=total_time1;
1189 #if BUFBARS == TRUE
1190 for(i=0; i<RX_INDICATOR_MAXNUM; i++)rx_indicator_maxpos[i]=-1;
1191 for(i=0; i<RX_INDICATOR_MAXNUM; i++)rx_indicator_minpos[i]=-1;
1192 bufbar_reset_time=total_time1;
1193 bufbar_reset_no=-1;
1194 #endif
1195 idle_flag=0;
1196 local_bg_update_filter=bg_update_filter;
1197 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1198 // *******************************************************
1199 // MAIN RECEIVE LOOP
1200 // *******************************************************
1201 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1202 local_baseb_reset_counter=0;
1203 baseb_reset_counter=0;
1204 // � � � � � � � �??init_baseband_sizes();
1205 baseb_clear_time=0;
1206 fftx_flag=0;
1207 while(thread_status_flag[THREAD_SCREEN]!=THRFLAG_ACTIVE &&
1208 thread_status_flag[THREAD_SCREEN]!=THRFLAG_IDLE &&
1209 thread_status_flag[THREAD_SCREEN]!=THRFLAG_SEM_WAIT)
1210 {
1211 if(thread_command_flag[THREAD_NARROWBAND_DSP] ==
1212 THRFLAG_KILL)goto wcw_error_exit;
1213 lir_sleep(10000);
1214 }
1215 thread_status_flag[THREAD_NARROWBAND_DSP]=THRFLAG_ACTIVE;
1216 while(thread_command_flag[THREAD_NARROWBAND_DSP] == THRFLAG_ACTIVE)
1217 {
1218 #if RUSAGE_OLD == TRUE
1219 if(local_workload_counter != workload_counter)
1220 {
1221 local_workload_counter=workload_counter;
1222 make_thread_times(THREAD_NARROWBAND_DSP);
1223 }
1224 #endif
1225 dt1=current_time();
1226 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1227 idle_flag++;
1228 switch (idle_flag)
1229 {
1230 case 1:
1231 if(eme_active_flag != 0)
1232 {
1233 if(dt1 - eme_time > 3)
1234 {
1235 sc[SC_COMPUTE_EME_DATA]++;
1236 eme_time=dt1;
1237 }
1238 }
1239 break;
1240
1241 case 2:
1242 if(fft1_handle != NULL)
1243 {
1244 memcheck(198,fft1mem,&fft1_handle);
1245 if(kill_all_flag) goto wcw_error_exit;
1246 }
1247 if(baseband_handle != NULL)
1248 {
1249 memcheck(298,basebmem,&baseband_handle);
1250 if(kill_all_flag) goto wcw_error_exit;
1251 }
1252 break;
1253
1254 case 3:
1255 if(afc_handle != NULL)
1256 {
1257 memcheck(398,afcmem,&afc_handle);
1258 if(kill_all_flag) goto wcw_error_exit;
1259 }
1260 if(fft3_handle != NULL)
1261 {
1262 memcheck(498,fft3mem,&fft3_handle);
1263 if(kill_all_flag) goto wcw_error_exit;
1264 }
1265 if(blanker_handle != NULL)
1266 {
1267 memcheck(598,blankermem,&blanker_handle);
1268 if(kill_all_flag) goto wcw_error_exit;
1269 }
1270 break;
1271
1272 case 4:
1273 if(hires_handle != NULL)
1274 {
1275 memcheck(598,hiresmem,&hires_handle);
1276 if(kill_all_flag) goto wcw_error_exit;
1277 }
1278 if( allow_wse_parport != 0)
1279 {
1280 // Read now and then to make apm aware Linrad is running.
1281 // See z_APM.txt
1282 if (wse.parport != USB2LPT16_PORT_NUMBER)
1283 {
1284 lir_inb(wse.parport);
1285 }
1286 }
1287 break;
1288
1289 case 5:
1290 #if BUFBARS == TRUE
1291 if(recent_time-bufbar_reset_time > 2)reset_bufbar_pos();
1292 #endif
1293 break;
1294
1295 default:
1296 if(recent_time-idle_time >0.2)
1297 {
1298 idle_flag=0;
1299 idle_time=recent_time;
1300 }
1301 break;
1302 }
1303 if( mouse_task==-1 || (mouse_task&GRAPH_MASK) <= MAX_WIDEBAND_GRAPHS)
1304 {
1305 thread_status_flag[THREAD_NARROWBAND_DSP]=THRFLAG_SEM_WAIT;
1306 lir_await_event(EVENT_FFT1_READY);
1307 thread_status_flag[THREAD_NARROWBAND_DSP]=THRFLAG_ACTIVE;
1308 if(kill_all_flag) goto wcw_error_exit;
1309 if(thread_command_flag[THREAD_NARROWBAND_DSP]
1310 !=THRFLAG_ACTIVE)goto narend;
1311 }
1312 else
1313 {
1314 t1=current_time()-mouse_time_narrow;
1315 if(t1 <= MOUSE_MIN_TIME)
1316 {
1317 if( ((fft3_pa-fft3_px+fft3_totsiz)&fft3_mask) >= fft3_block &&
1318 ((baseb_py-baseb_pa+baseband_mask)&baseband_mask) > 4*(int)mix2.size)
1319 {
1320 goto more_mix2;
1321 }
1322 if( ((timf3_pa-timf3_px+timf3_size)&timf3_mask) >=
1323 twice_rxchan*fft3_size &&
1324 ((fft3_px-fft3_pa+fft3_mask)&fft3_mask) > fft3_block)
1325 {
1326 goto more_fft3;
1327 }
1328 if(fftx_flag != 0)
1329 {
1330 goto more_fftx;
1331 }
1332 if(t1 > 0.5/snd[RXAD].interrupt_rate)t1=0.5/snd[RXAD].interrupt_rate;
1333 lir_sleep(1000000*t1);
1334 }
1335 }
1336 // Here we do the mouse actions that affect the narrowband graphs.
1337 // Note that memory areas may become re-allocated and that no other
1338 // threads may try to acces the narrowband arrays in the meantime.
1339 // The screen thread is stopped by the memory allocation routines
1340 if(recent_time-mouse_time_narrow > MOUSE_MIN_TIME)
1341 {
1342 mouse_time_narrow=current_time();
1343 if(bg_update_filter != local_bg_update_filter)
1344 {
1345 local_bg_update_filter=bg_update_filter;
1346 make_bg_filter();
1347 if(kill_all_flag) goto wcw_error_exit;
1348 make_modepar_file(GRAPHTYPE_BG);
1349 mg_clear_flag=TRUE;
1350 }
1351 k=mouse_task&GRAPH_MASK;
1352 if( k > MAX_WIDEBAND_GRAPHS)
1353 {
1354 set_button_states();
1355 if( (mouse_task&GRAPH_RIGHTPRESSED) != 0)
1356 {
1357 rightpressed=BUTTON_IDLE;
1358 mouse_task=-1;
1359 goto mouse_x;
1360 }
1361 if(mouse_active_flag == 0)
1362 {
1363 switch (k)
1364 {
1365 case AFC_GRAPH:
1366 mouse_on_afc_graph();
1367 break;
1368
1369 case BASEBAND_GRAPH:
1370 mouse_on_baseband_graph();
1371 break;
1372
1373 case POL_GRAPH:
1374 mouse_on_pol_graph();
1375 break;
1376
1377 case COH_GRAPH:
1378 mouse_on_coh_graph();
1379 break;
1380
1381 case EME_GRAPH:
1382 mouse_on_eme_graph();
1383 break;
1384
1385 case METER_GRAPH:
1386 mouse_on_meter_graph();
1387 break;
1388
1389 case ELEKTOR_GRAPH:
1390 mouse_on_elektor_graph();
1391 break;
1392
1393 #if LIBUDEV_PRESENT == 1
1394 case FCDPROPLUS_GRAPH:
1395 mouse_on_fcdproplus_graph();
1396 break;
1397 #endif
1398
1399 default:
1400 mouse_on_users_graph();
1401 break;
1402 }
1403 if(mouse_active_flag == 0)lirerr(8877);
1404 }
1405 if(numinput_flag==0)
1406 {
1407 current_mouse_activity();
1408 if(kill_all_flag) goto wcw_error_exit;
1409 }
1410 if( (numinput_flag&DATA_READY_PARM) != 0)
1411 {
1412 par_from_keyboard_routine();
1413 if(kill_all_flag) goto wcw_error_exit;
1414 par_from_keyboard_routine=NULL;
1415 mouse_active_flag=0;
1416 numinput_flag=0;
1417 leftpressed=BUTTON_IDLE;
1418 }
1419 if(mouse_active_flag == 0)
1420 {
1421 mouse_task=-1;
1422 }
1423 mouse_x:;
1424 }
1425 }
1426 if(local_baseb_reset_counter!=baseb_reset_counter)
1427 {
1428 do_baseb_reset:;
1429 i=0;
1430 local_baseb_reset_counter=baseb_reset_counter;
1431 // We control the rx output thread from here. It should be either
1432 // active or waiting on the semaphore.
1433 // Send it to the semaphore if it is not already there.
1434 control_rxout:;
1435 if(thread_status_flag[THREAD_RX_OUTPUT] == THRFLAG_SEMCLEAR)goto dasem;
1436 if(thread_status_flag[THREAD_RX_OUTPUT] == THRFLAG_IDLE)goto daidle;
1437 if(!kill_all_flag &&
1438 thread_status_flag[THREAD_RX_OUTPUT] != THRFLAG_ACTIVE)
1439 {
1440 if(thread_status_flag[THREAD_RX_OUTPUT] == THRFLAG_SEMCLEAR)goto dasem;
1441 if(thread_status_flag[THREAD_RX_OUTPUT] == THRFLAG_IDLE)goto daidle;
1442 if(i<6)
1443 {
1444 i++;
1445 lir_sleep(i*i*2000);
1446 goto control_rxout;
1447 }
1448 lirerr(672954);
1449 goto wcw_error_exit;
1450 }
1451 pause_thread(THREAD_RX_OUTPUT);
1452 daidle:;
1453 thread_command_flag[THREAD_RX_OUTPUT]=THRFLAG_SEMCLEAR;
1454 lir_sched_yield();
1455 while(thread_status_flag[THREAD_RX_OUTPUT] != THRFLAG_SEMCLEAR)
1456 {
1457 lir_sleep(1000);
1458 if(kill_all_flag) goto wcw_error_exit;
1459 }
1460 dasem:;
1461 if(mix1_selfreq[0] >= 0)
1462 {
1463 new_baseb_flag=3;
1464 init_baseband_sizes();
1465 make_baseband_graph(TRUE);
1466 clear_baseb();
1467 baseb_clear_time=current_time();
1468 local_baseb_reset_counter=baseb_reset_counter;
1469 goto narend_chk;
1470 }
1471 else
1472 {
1473 if( (ui.network_flag & NET_RX_INPUT) != 0)
1474 {
1475 net_send_slaves_freq();
1476 }
1477 new_baseb_flag=-1;
1478 }
1479 }
1480 more_fftx:;
1481 if(local_baseb_reset_counter!=baseb_reset_counter)goto do_baseb_reset;
1482 fftx_flag=0;
1483 if( genparm[SECOND_FFT_ENABLE] == 0 )
1484 {
1485 if(new_baseb_flag >= 0)
1486 {
1487 if(genparm[AFC_ENABLE] != 0 &&
1488 (rx_mode < MODE_SSB || rx_mode == MODE_AM || rx_mode == MODE_FM))
1489 {
1490 if( fft1_nb != fft1_nc)
1491 {
1492 make_afc();
1493 if( ag.mode_control != 0 && afc_graph_filled != 0)sc[SC_SHOW_AFC]++;
1494 }
1495 if( fft1_nm >= afc_tpts)
1496 {
1497 if( ((fft1_nc-fft1_nx+max_fft1n)&fft1n_mask) > afct_delay_points
1498 &&((timf3_px-timf3_pa+timf3_mask)&timf3_mask) >= timf3_block)
1499 {
1500 fft1_mix1_afc();
1501 }
1502 }
1503 if( ((fft1_nb-fft1_nx+max_fft1n)&fft1n_mask) >
1504 afct_delay_points )fftx_flag|=1;
1505 if( ((timf3_px-timf3_pa+timf3_mask)&timf3_mask) <
1506 timf3_block)fftx_flag|=2;
1507 }
1508 else
1509 {
1510 if( fft1_nb != fft1_nx &&
1511 ((timf3_px-timf3_pa+timf3_mask)&timf3_mask) >= timf3_block)
1512 {
1513 fft1_mix1_fixed();
1514 if(fft1_nb != fft1_nx)fftx_flag|=1;
1515 if( ((timf3_px-timf3_pa+timf3_mask)&timf3_mask) <
1516 timf3_block)fftx_flag|=2;
1517 }
1518 }
1519 }
1520 else
1521 {
1522 fft1_nx=fft1_nb;
1523 fft1_px=fft1_pb;
1524 fft1_nc=fft1_nb;
1525 goto clear_select;
1526 }
1527 }
1528 else
1529 {
1530 if(new_baseb_flag >= 0)
1531 {
1532 if(genparm[AFC_ENABLE] != 0 &&
1533 (rx_mode < MODE_SSB || rx_mode == MODE_AM || rx_mode == MODE_FM) )
1534 {
1535 if(fft2_na != fft2_nc)
1536 {
1537 make_afc();
1538 if( ag.mode_control != 0 && afc_graph_filled != 0)sc[SC_SHOW_AFC]++;
1539 }
1540 if( ((fft2_nc-fft2_nx+max_fft2n)&fft2n_mask) > afct_delay_points &&
1541 ((timf3_px-timf3_pa+timf3_mask)&timf3_mask) >= timf3_block)
1542 {
1543 fft2_mix1_afc();
1544 }
1545 if(((fft2_na-fft2_nx+max_fft2n)&fft2n_mask) >
1546 afct_delay_points)fftx_flag|=1;
1547 if( ((timf3_px-timf3_pa+timf3_mask)&timf3_mask) <
1548 timf3_block)fftx_flag|=2;
1549 }
1550 else
1551 {
1552 if(fft2_na != fft2_nx &&
1553 ((timf3_px-timf3_pa+timf3_mask)&timf3_mask) >= timf3_block)
1554 {
1555 fft2_mix1_fixed();
1556 }
1557 if(fft2_na != fft2_nx)fftx_flag|=1;
1558 if( ((timf3_px-timf3_pa+timf3_mask)&timf3_mask) < timf3_block)
1559 {
1560 fftx_flag|=2;
1561 }
1562 }
1563 }
1564 else
1565 {
1566 clear_select:;
1567 timf3_px=timf3_pa;
1568 timf3_py=timf3_pa;
1569 fft3_px=fft3_pa;
1570 baseb_wts=2;
1571 baseb_pb=baseb_pa;
1572 baseb_py=baseb_pa;
1573 baseb_pn=baseb_pa;
1574 goto narend_chk;
1575 }
1576 }
1577 #if BUFBARS == TRUE
1578 if(timinfo_flag!=0)
1579 {
1580 i=(timf3_pa+timf3_block-timf3_px+timf3_size)&timf3_mask;
1581 i/=timf3_indicator_block;
1582 show_bufbar(4,i);
1583 }
1584 #endif
1585 if(local_baseb_reset_counter!=baseb_reset_counter)goto do_baseb_reset;
1586 if( ((timf3_pa-timf3_px+timf3_size)&timf3_mask) >=
1587 twice_rxchan*fft3_size &&
1588 ((fft3_px-fft3_pa+fft3_mask)&fft3_mask) > fft3_block)
1589 {
1590 more_fft3:;
1591 make_fft3_all();
1592 }
1593 #if BUFBARS == TRUE
1594 if(fft3_handle != NULL && timinfo_flag!=0)
1595 {
1596 i=(fft3_pa+fft3_block-fft3_px+fft3_totsiz)&fft3_mask;
1597 i/=fft3_indicator_block;
1598 show_bufbar(5,i);
1599 }
1600 #endif
1601 k=(fft3_pa-fft3_px+fft3_totsiz)&fft3_mask;
1602 k/=fft3_block;
1603 if(audio_dump_flag == 0 && k >= 2)
1604 {
1605 fft3_overload_ticks++;
1606 if(fft3_overload_ticks > 5)
1607 {
1608 fft3_overload_count++;
1609 sprintf(s,"BUFFER ERROR (fft3) %d",fft3_overload_count);
1610 wg_error(s,WGERR_FFT3_OVERLOAD);
1611 fft3_overload_ticks=0;
1612 }
1613 }
1614 else
1615 {
1616 fft3_overload_ticks=0;
1617 }
1618 if( ((fft3_pa-fft3_px+fft3_totsiz)&fft3_mask) >= fft3_block &&
1619 ((baseb_py-baseb_pa+baseband_mask)&baseband_mask) > 4*(int)mix2.size)
1620 {
1621 more_mix2:;
1622 if(local_baseb_reset_counter!=baseb_reset_counter)goto do_baseb_reset;
1623 fft3_mix2();
1624 if( ((baseb_pa-baseb_py+baseband_size)&baseband_mask) >= baseb_output_block)
1625 {
1626 lir_set_event(EVENT_BASEB);
1627 }
1628 if(kill_all_flag) goto wcw_error_exit;
1629 if(new_baseb_flag ==0)
1630 {
1631 if(genparm[CW_DECODE_ENABLE] != 0)
1632 {
1633 coherent_cw_detect();
1634 if(kill_all_flag) goto wcw_error_exit;
1635 }
1636 if(cg.oscill_on != 0)sc[SC_CG_REDRAW]++;
1637 }
1638 }
1639 #if BUFBARS == TRUE
1640 if(baseband_handle != NULL && timinfo_flag!=0)
1641 {
1642 i=(baseb_pa+fft3_block+2-baseb_py+baseband_mask+1)&baseband_mask;
1643 i/=baseb_indicator_block;
1644 show_bufbar(6,i);
1645 }
1646 #endif
1647 if(new_baseb_flag > 0)
1648 {
1649 lir_sched_yield();
1650 make_timing_info();
1651 update_snd(RXDA);
1652 if(kill_all_flag) goto wcw_error_exit;
1653 t1=total_wttim-da_wait_time-da_wttim;
1654 if(!audio_dump_flag && new_baseb_flag == 3)
1655 {
1656 if(t1 > 0.01 )
1657 {
1658 new_baseb_flag=2;
1659 }
1660 goto narend_chk;
1661 }
1662 if(baseb_clear_time+3+2*da_wait_time < current_time())lirerr(1058);
1663 // new_baseb_flag == 1 or 2
1664 // We want data in buffers corresponding to da_wait_time.
1665 // We arrive here when there is more than that, move pointers
1666 // to discard data corresponding to total_wttim-da_wait_time
1667 // If there is too much data in memory, move the baseb pointer
1668 // to discard more data.
1669 if(new_baseb_flag == 2)
1670 {
1671 if(t1*baseband_sampling_speed > 4)
1672 {
1673 i=t1*baseband_sampling_speed;
1674 if(i > baseb_wts-1)
1675 {
1676 baseb_py=(baseb_py+(int)(baseb_wts)-1+baseband_size)&baseband_mask;
1677 goto narend_chk;
1678 }
1679 baseb_py=(baseb_py+i-1+baseband_size)&baseband_mask;
1680 }
1681 new_baseb_flag=1;
1682 goto narend_chk;
1683 }
1684 lir_sched_yield();
1685 if( (ui.network_flag & NET_RXIN_FFT1) == 0)
1686 {
1687 i=timf1p_pb;
1688 thread_status_flag[THREAD_NARROWBAND_DSP]=THRFLAG_INPUT_WAIT;
1689 while(i == timf1p_pb)
1690 {
1691 if(thread_command_flag[THREAD_NARROWBAND_DSP] != THRFLAG_ACTIVE)
1692 {
1693 thread_status_flag[THREAD_NARROWBAND_DSP]=THRFLAG_ACTIVE;
1694 goto narend_chk;
1695 }
1696 lir_sleep(1000);
1697 if(kill_all_flag) goto wcw_error_exit;
1698 }
1699 thread_status_flag[THREAD_NARROWBAND_DSP]=THRFLAG_ACTIVE;
1700 }
1701 if(cg.meter_graph_on != 0)sc[SC_MG_REDRAW]++;
1702 workload_reset_flag++;
1703 if( (ui.network_flag & NET_RX_INPUT) != 0)
1704 {
1705 net_send_slaves_freq();
1706 }
1707 new_baseb_flag=0;
1708 timf2_blockpower_px=-1;
1709 timf2_pb=timf2_pn2;
1710 sc[SC_BG_WATERF_REDRAW]+=3;
1711 thread_command_flag[THREAD_RX_OUTPUT]=THRFLAG_ACTIVE;
1712 lir_set_event(EVENT_RX_START_DA);
1713 goto more_fftx;
1714 }
1715 narend_chk:;
1716 if(kill_all_flag)goto wcw_error_exit;
1717 if( ((fft3_pa-fft3_px+fft3_totsiz)&fft3_mask) >= fft3_block &&
1718 ((baseb_py-baseb_pa+baseband_mask)&baseband_mask) > 4*(int)mix2.size)
1719 {
1720 lir_sched_yield();
1721 goto more_mix2;
1722 }
1723 if( ((timf3_pa-timf3_px+timf3_size)&timf3_mask) >=
1724 twice_rxchan*fft3_size &&
1725 ((fft3_px-fft3_pa+fft3_mask)&fft3_mask) > fft3_block)
1726 {
1727 lir_sched_yield();
1728 goto more_fft3;
1729 }
1730 if(fftx_flag != 0)
1731 {
1732 if(new_baseb_flag == 0)
1733 {
1734 if( (fftx_flag&2) == 0)
1735 {
1736 lir_sched_yield();
1737 }
1738 else
1739 {
1740 lir_sleep(5000);
1741 }
1742 }
1743 if(!kill_all_flag && thread_command_flag[THREAD_NARROWBAND_DSP] ==
1744 THRFLAG_ACTIVE)
1745 {
1746 goto more_fftx;
1747 }
1748 }
1749 narend:;
1750 }
1751 wcw_error_exit:;
1752 thread_status_flag[THREAD_NARROWBAND_DSP]=THRFLAG_RETURNED;
1753 lir_sched_yield();
1754 while(thread_command_flag[THREAD_NARROWBAND_DSP] != THRFLAG_NOT_ACTIVE)
1755 {
1756 lir_sleep(1000);
1757 }
1758 }
1759
1760