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