1 // Copyright (c) <2012> <Leif Asbrink>
2 //
3 // Permission is hereby granted, free of charge, to any person
4 // obtaining a copy of this software and associated documentation
5 // files (the "Software"), to deal in the Software without restriction,
6 // including without limitation the rights to use, copy, modify,
7 // merge, publish, distribute, sublicense, and/or sell copies of
8 // the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
22 
23 
24 #include <unistd.h>
25 #include <string.h>
26 #include "globdef.h"
27 #include "uidef.h"
28 #include "fft1def.h"
29 #include "fft2def.h"
30 #include "fft3def.h"
31 #include "screendef.h"
32 #include "seldef.h"
33 #include "blnkdef.h"
34 #include "sigdef.h"
35 #include "hwaredef.h"
36 
37 #define TIMF3_OSCILLOSCOPE_RATE 2
38 
fft1_block_timing(void)39 void fft1_block_timing(void)
40 {
41 fft1_interleave_ratio=(float)(fft1_interleave_points)/fft1_size;
42 fft1_new_points=fft1_size-fft1_interleave_points;
43 timf1_sampling_speed=ui.rx_ad_speed;
44 if( (ui.rx_input_mode&IQ_DATA) == 0)
45   {
46   timf1_sampling_speed*=0.5;
47   }
48 fft1_blocktime=(float)(fft1_new_points)/timf1_sampling_speed;
49 }
50 
prepare_mixer(MIXER_VARIABLES * m,int nn)51 void prepare_mixer(MIXER_VARIABLES *m, int nn)
52 {
53 unsigned int i, j, k;
54 float t1;
55 if( genparm[nn]!= 0 && (genparm[nn]!= 2 || rx_mode == MODE_TXTEST))
56   {
57   make_window(3,m[0].size, genparm[nn], m[0].window);
58   }
59 init_fft(0,m[0].n, m[0].size, m[0].table, m[0].permute);
60 // If we use a window for mix1 we need crossover functions, sin and cos
61 // squared. Will not be used in case the window itself is sin squared.
62 // Find out how long to make the crossover region.
63 // Stop it when the window has fallen by 20dB compared to the
64 // start of the crossover region.
65 m[0].crossover_points=0;
66 if( genparm[nn] != 0 && genparm[nn] != 2 )
67   {
68   if(genparm[nn] == 9)
69     {
70     m[0].crossover_points=m[0].size/8;
71     }
72   else
73     {
74     if(genparm[nn] == 8)
75       {
76       m[0].crossover_points=m[0].size/16;
77       }
78     else
79       {
80       i=m[0].interleave_points/2;
81       t1=m[0].window[i];
82       while(m[0].window[i]<30*t1 && i>0)
83         {
84         i--;
85         m[0].crossover_points++;
86         }
87       if(m[0].crossover_points > 0.75*m[0].new_points)
88                                  m[0].crossover_points=0.75*m[0].new_points;
89       if(m[0].crossover_points > m[0].interleave_points/2)
90                                  m[0].crossover_points=m[0].interleave_points/2;
91       }
92     }
93   t1=0.25*PI_L/m[0].crossover_points;
94   j=(m[0].size-m[0].new_points)/2;
95   k=j;
96   k+=m[0].crossover_points/2;
97   j-=m[0].crossover_points/2;
98   for(i=0; i<m[0].crossover_points; i++)
99     {
100     m[0].cos2win[i]=m[0].window[k]*pow(cos(t1),2.0);
101     m[0].sin2win[i]=m[0].window[j]*pow(sin(t1),2.0);
102     k--;
103     j++;
104     t1+=0.5*PI_L/m[0].crossover_points;
105     }
106   }
107 }
108 
make_interleave_ratio(int nn)109 float make_interleave_ratio(int nn)
110 {
111 // Make interleave_ratio the distance between the points where the
112 // window function is 0.5.
113 if(genparm[nn] != 0)
114   {
115   if(genparm[nn] == 9)
116     {
117     return 0.625;
118     }
119   else
120     {
121     if(genparm[nn] == 8)
122       {
123       return 0.8;
124       }
125     else
126       {
127       return 2*asin(pow(0.5,1.0/genparm[nn]))/PI_L;
128       }
129     }
130   }
131 return 0;
132 }
133 
134 
get_wideband_sizes(void)135 void get_wideband_sizes(void)
136 {
137 float t1;
138 int i, j, m, n, k, bwfac;
139 int reduced_max_dma;
140 if(fft1_handle != NULL)
141   {
142   lirerr(1002);
143   return;
144   }
145 fft1mode=(ui.rx_input_mode&(TWO_CHANNELS+IQ_DATA))/2;
146 // Before doing anything else, set output format information
147 rx_daout_bytes=1+(genparm[OUTPUT_MODE]&1);               //bit 0
148 rx_daout_channels=1+((genparm[OUTPUT_MODE]>>1)&1);       //bit 1
149 if(rx_daout_channels < ui.rx_min_da_channels)
150   {
151   rx_daout_channels = ui.rx_min_da_channels;
152   }
153 // Tell assembly routines how many channels we have (so we make no
154 // mistake when changing struct ui.
155 rx_channels=ui.rx_rf_channels;
156 twice_rxchan=2*ui.rx_rf_channels;
157 // *********************************************************************
158 // First find size of first fft.
159 // In case a window was selected we need more points for the
160 // same bandwidth. Get the interleave ratio.
161 fft1_interleave_ratio=make_interleave_ratio(FIRST_FFT_SINPOW);
162 if( (ui.network_flag & NET_RXIN_FFT1) == 0)
163   {
164   if(genparm[FIRST_FFT_BANDWIDTH]==0)
165     {
166     bwfac=65536;
167     }
168   else
169     {
170     bwfac=(0.3536*ui.rx_ad_speed)/
171                   ((1-fft1_interleave_ratio)*genparm[FIRST_FFT_BANDWIDTH]);
172     }
173   j=bwfac;
174   if( (ui.rx_input_mode&IQ_DATA) != 0)j*=2;
175 // j is the number of points we need for the whole transform to get the
176 // desired bandwidth multiplied by 1.414.
177 // Make j a power of two so the bandwidth will be in the range
178 // 0.707*desired < bw < 1.414*desired.
179   fft1_n=1;
180   i=j;
181   while(j != 0)
182    {
183    j/=2;
184    fft1_n++;
185    }
186 // Never make the size below n=6 (=64)
187 // Note that i becomes small so we arrive at fft1_n=6
188   if(fft1_n < 7)fft1_n=7;
189   fft1_size=1<<fft1_n;
190   if( (float)(fft1_size)/i > 1.5)
191     {
192 reduce_fft1_size:;
193     fft1_size/=2;
194     fft1_n--;
195     }
196   }
197 if(fft1_n > 12)
198   {
199   yieldflag_wdsp_fft1=TRUE;
200   }
201 else
202   {
203   yieldflag_wdsp_fft1=FALSE;
204   }
205 if(genparm[SECOND_FFT_ENABLE] == 0)
206   {
207   if(ui.max_blocked_cpus > 0)yieldflag_wdsp_fft1=FALSE;
208   }
209 else
210   {
211   if(ui.max_blocked_cpus > 2)yieldflag_wdsp_fft1=FALSE;
212   }
213 // Each channel output is 2*float (re, im)
214 fft1_block=twice_rxchan*fft1_size;
215 fft1_muln=(fft_cntrl[FFT1_CURMODE].real2complex+1)
216                                      *fft_cntrl[FFT1_CURMODE].parall_fft;
217 fft1_mulblock=fft1_block*fft1_muln;
218 j=fft1_size*(fft_cntrl[FFT1_CURMODE].real2complex+1);
219 fft1_permute_size=j;
220 fft1_window_size=j;
221 if(rx_mode == MODE_TUNE)
222   {
223   fft1_costab_size=j;
224   }
225 else
226   {
227   fft1_costab_size=j/2;
228   if(fft_cntrl[FFT1_CURMODE].permute == 2)
229     {
230     fft1_costab_size*=2;
231     fft1_permute_size*=2;
232     fft1_window_size+=16;
233     }
234 // To save cash we use short int for the unscramble table.
235 // Make sure the unscramble array is not too big.
236   if(fft1_permute_size > 0x10000)goto reduce_fft1_size;
237   if(genparm[FIRST_FFT_VERNR]==5 &&
238                fft1_permute_size > 0x8000)goto reduce_fft1_size;
239   if(genparm[FIRST_FFT_SINPOW] == 0)fft1_window_size=0;
240   }
241 fft1_blockbytes=fft1_block*sizeof(float);
242 // Each channel input is 16 bit or 32 bit.
243 snd[RXAD].framesize=2*ui.rx_ad_channels;
244 if( (ui.rx_input_mode&DWORD_INPUT) != 0) snd[RXAD].framesize*=2;
245 // Get number of points to overlap transforms so window function does
246 // not drop below 0.5.
247 // In this way all points contribute by approximately the same amount
248 // to the averaged power spectrum.
249 // We also need this to be able to use MMX for the back transform.
250 fft1_interleave_points=1+fft1_interleave_ratio*fft1_size;
251 fft1_interleave_points&=0xfffe;
252 fft1_bandwidth=0.5*ui.rx_ad_speed/((1-fft1_interleave_ratio)*fft1_size);
253 if( (ui.rx_input_mode&IQ_DATA) != 0)fft1_bandwidth*=2;
254 // *******************************************************
255 // Get the sizes for the second fft and the first mixer
256 // The first frequency mixer shifts the signal in timf1 or timf2 to
257 // the baseband.
258 // Rather tham multiplying with a sin/cos table of the selected frequency
259 // we use the corresponding fourier transforms from which a group of lines
260 // are selected, frequency shifted and back transformed.
261 new_mix1_n:;
262 mix1.n=fft1_n-genparm[MIX1_BANDWIDTH_REDUCTION_N];
263 if(genparm[SECOND_FFT_ENABLE] == 0)
264   {
265   fft2_size=0;
266   timf2pow_size=0;
267 // If we get signals from back transformation of fft1
268 // we use an interleave ratio that makes the interleave points
269 // go even up in mix1.size.
270   if(mix1.n < 3)mix1.n=3;
271   mix1.size=1<<mix1.n;
272   mix1.interleave_points=fft1_interleave_ratio*mix1.size;
273   mix1.interleave_points&=0xfffffffe;
274   fft1_interleave_points=mix1.interleave_points*(fft1_size/mix1.size);
275   fft1_block_timing();
276   fftx_blocktime=fft1_blocktime;
277   spur_freq_factor=(float)(fft1_new_points)/fft1_size;
278   timf3_sampling_speed=timf1_sampling_speed/fft1_size;
279   }
280 else
281   {
282   if(calibrate_flag == 0 && fft1_n > 15)goto reduce_fft1_size;
283 // Make the time constant for the blanker noise floor about 1 second.
284 // The first fft outputs data in blocks of fft1_new_points
285   fft1_block_timing();
286   j=(float)(ui.rx_ad_speed+fft1_new_points/2)/fft1_new_points;
287   if(j<1)j=1;
288   timf2_noise_floor_avgnum=j;
289   blanker_info_update_counter=0;
290   fft1_lowlevel_fraction=.75;
291   j/=8;
292   if(j<1)j=1;
293   blanker_info_update_interval=j;
294   timf2_display_interval=timf2_noise_floor_avgnum/10;
295   if(timf2_display_interval < 2)timf2_display_interval=2;
296   timf2_ovfl=0;
297   timf2_display_counter=0;
298   timf2_display_maxpoint=0;
299   timf2_display_maxval_uint=0;
300   timf2_display_maxval_float=0;
301   fft2_interleave_ratio=make_interleave_ratio(SECOND_FFT_SINPOW);
302   j=1<<(genparm[SECOND_FFT_NINC]);
303   fft2_n=fft1_n;
304 fft2_sizeset:;
305   fft2_size=1<<fft2_n;
306   if(fft2_n > 12 && ui.max_blocked_cpus == 0)
307     {
308     yieldflag_fft2_fft2=TRUE;
309     }
310   else
311     {
312     yieldflag_fft2_fft2=FALSE;
313     }
314   fft2_bandwidth=0.5*ui.rx_ad_speed/((1-fft2_interleave_ratio)*fft2_size);
315   if( (ui.rx_input_mode&IQ_DATA) != 0)fft2_bandwidth*=2;
316   if(fft2_bandwidth*j < 1.5*fft1_bandwidth)goto fft2_size_x;
317   fft2_n++;
318   goto fft2_sizeset;
319 fft2_size_x:;
320   fft2_interleave_points=1+fft2_interleave_ratio*fft2_size;
321   fft2_interleave_points&=0xfffe;
322 // Make timf2 hold 2 seconds of data
323   timf2pow_size=2*timf1_sampling_speed;
324 // In case we are in the powtim function, fft2 is not
325 // in use although we use its arrays. Change accordingly:
326   if(lir_status==LIR_POWTIM)
327     {
328     timf2pow_size=timf1_sampling_speed*genparm[FFT1_STORAGE_TIME];
329     }
330 #if(IA64 == 0)
331   if(timf2pow_size > 0x3fffffff)timf2pow_size=0x3fffffff;
332 #endif
333   make_power_of_two(&timf2pow_size);
334   // or four fft2 transforms if that is more
335   if(timf2pow_size < 8*fft2_size) timf2pow_size = 8*fft2_size;
336   while(timf2pow_size < 2*screen_width*ui.rx_rf_channels)timf2pow_size*=2;
337 #if(IA64 == 0)
338   if((float)(timf2pow_size)*(float)(4*ui.rx_rf_channels*sizeof(float)) >=
339           (long int)0x8000000)
340                       timf2pow_size=0x2000000/(ui.rx_rf_channels*sizeof(float));
341 #else
342   if((float)(timf2pow_size)*(float)(4*ui.rx_rf_channels*sizeof(float)) >=
343           (long int)0x80000000)
344                       timf2pow_size=0x80000000/(ui.rx_rf_channels*sizeof(float));
345 #endif
346 // There are 2 transforms (strong, weak) for each rx channel
347   timf2pow_mask=timf2pow_size-1;
348   timf2_size=4*ui.rx_rf_channels*timf2pow_size;
349   timf2_mask=timf2_size-1;
350   timf2_neg=timf2_mask-fft2_size;
351   timf2_input_block=(fft1_size-fft1_interleave_points)*4*ui.rx_rf_channels;
352   timf2_pa=0;
353   timf2_pb=0;
354   timf2_pc=0;
355   timf2_pn1=0;
356   timf2_pn2=0;
357   timf2_pt=0;
358   timf2p_fit=0;
359   timf2_px=0;
360   timf2_blockpower_size=2*genparm[BASEBAND_STORAGE_TIME]*
361                       timf1_sampling_speed/(fft1_size-fft1_interleave_points);
362   make_power_of_two(&timf2_blockpower_size);
363   timf2_blockpower_mask=timf2_blockpower_size-1;
364   timf2_blockpower_pa=0;
365   timf2_blockpower_px=0;
366 // Set start noise floor 23dB above one bit amplitude
367 // and set channel noise = 1 so sum never becomes zero to avoid
368 // problems with log function.
369   timf2_noise_floor=200;
370   timf2_despiked_pwr[0]=timf2_noise_floor;
371   timf2_despiked_pwrinc[0]=1;
372   if(ui.rx_rf_channels == 2)
373     {
374     timf2_despiked_pwr[1]=timf2_noise_floor;
375     timf2_despiked_pwrinc[1]=1;
376     timf2_noise_floor*=2;
377     }
378   timf2_fitted_pulses=0;
379   timf2_cleared_points=0;
380   timf2_blanker_points=0;
381   clever_blanker_rate=0;
382   stupid_blanker_rate=0;
383   mix1.n+=fft2_n-fft1_n;
384   if(mix1.n < 3)mix1.n=3;
385   mix1.size=1<<mix1.n;
386   if(mix1.n > 12)
387     {
388     yieldflag_ndsp_mix1=TRUE;
389     }
390   else
391     {
392     yieldflag_ndsp_mix1=FALSE;
393     }
394   if(genparm[SECOND_FFT_ENABLE] == 0)
395     {
396     if(ui.max_blocked_cpus > 1)yieldflag_ndsp_mix1=FALSE;
397     }
398   else
399     {
400     if(ui.max_blocked_cpus > 3)yieldflag_ndsp_mix1=FALSE;
401     }
402   mix1.interleave_points=fft2_interleave_ratio*mix1.size;
403   mix1.interleave_points&=0xfffffffe;
404   fft2_interleave_points=mix1.interleave_points*(fft2_size/mix1.size);
405   fft2_interleave_ratio=(float)(fft2_interleave_points)/fft2_size;
406   fft2_new_points=fft2_size-fft2_interleave_points;
407   fft2_blocktime=(float)(fft2_new_points)/timf1_sampling_speed;
408   fftx_blocktime=fft2_blocktime;
409 // Keep fft2 transforms for genparm[FFT2_STORAGE_TIME] seconds.
410   max_fft2n=genparm[FFT2_STORAGE_TIME]/fft2_blocktime;
411   make_power_of_two(&max_fft2n);
412   if(max_fft2n<4)max_fft2n=4;
413   t1=(float)(max_fft2n)*fft2_blockbytes;
414   if(t1 > 0x20000000)
415     {
416     max_fft2n=0x20000000/fft2_blockbytes;
417     }
418   fft2n_mask=max_fft2n-1;
419   fft2_blockbytes=twice_rxchan*fft2_size;
420   fft2_totbytes=fft2_blockbytes*max_fft2n;
421   fft2_mask=fft2_totbytes-1;
422   fft2_pa=0;
423   fft2_pt=0;
424   fft2_na=0;
425   fft2_nc=0;
426   fft2_nb=fft2n_mask;
427   fft2_nx=0;
428   fft2_nm=0;
429   timf3_sampling_speed=timf1_sampling_speed/fft2_size;
430   timf2_output_block=fft2_new_points*4*ui.rx_rf_channels;
431   spur_freq_factor=(float)(fft2_new_points)/fft2_size;
432   }
433 timf3_sampling_speed*=mix1.size;
434 // ***********************************************************
435 // Transfer from the hardware device driver to our part of memory is
436 // done by read statements.
437 // If too few bytes are read each time we loose too much time because
438 // of the overhead of each read statement.
439 // If too many bytes are read each time we get an extra delay that
440 // is not acceptable in some receive modes.
441 // One output transform is fft1_blockbytes or fft1_size*twice_rxchan data words
442 // In I/Q mode (complex input format) the input contains the same
443 // number of data words as the output and the same number of fragments.
444 // In real mode (real input format) the fft routine contains a reduction
445 // of sampling speed (real to complex conversion).
446 // The number of input words is still the same as the number of output words
447 // but the fragment size is 2 times smaller at twice the sampling frequency.
448 // Make the maximum delay time 25% of the time for a full transform.
449 // This allows the user to force low delay times by selecting large
450 // fft1 bandwidths. (At questionable noise blanker performance)
451 if(genparm[SECOND_FFT_ENABLE] == 0)
452   {
453   min_delay_time=fft1_size;
454   }
455 else
456   {
457   min_delay_time=fft2_size;
458   }
459 min_delay_time/=3*timf1_sampling_speed;
460 if(min_delay_time>0.1)min_delay_time=0.1;
461 snd[RXAD].block_frames=min_delay_time*ui.rx_ad_speed;
462 make_power_of_two((int*)&snd[RXAD].block_frames);
463 reduced_max_dma=ui.max_dma_rate;
464 switch(ui.rx_addev_no)
465   {
466   case PERSEUS_DEVICE_CODE:
467   if(reduced_max_dma>800)reduced_max_dma=800;
468   break;
469 
470   case EXCALIBUR_DEVICE_CODE:
471   if(reduced_max_dma>400)reduced_max_dma=400;
472   break;
473 
474   }
475 if(snd[RXAD].block_frames<8)snd[RXAD].block_frames=8;
476 snd[RXAD].interrupt_rate=(float)(ui.rx_ad_speed)/snd[RXAD].block_frames;
477 while(snd[RXAD].interrupt_rate < ui.min_dma_rate && snd[RXAD].block_frames>8)
478   {
479   snd[RXAD].interrupt_rate*=2;
480   snd[RXAD].block_frames/=2;
481   }
482 while(snd[RXAD].interrupt_rate > reduced_max_dma)
483   {
484   snd[RXAD].interrupt_rate/=2;
485   snd[RXAD].block_frames*=2;
486   }
487 if( (ui.network_flag&NET_RX_INPUT)!=0)
488   {
489   snd[RXAD].block_frames=snd[RXAD].block_bytes/snd[RXAD].framesize;
490   snd[RXAD].interrupt_rate=(float)(ui.rx_ad_speed)/snd[RXAD].block_frames;
491   }
492 else
493   {
494   if(diskread_flag != 2 && (ui.rx_addev_no == SDR14_DEVICE_CODE ||
495                             ui.rx_addev_no == SDRIQ_DEVICE_CODE ))
496     {
497     snd[RXAD].block_bytes=8192;
498     snd[RXAD].framesize=4;
499     snd[RXAD].block_frames=2048;
500     snd[RXAD].interrupt_rate=(float)(ui.rx_ad_speed)/snd[RXAD].block_frames;
501     }
502   else
503     {
504     snd[RXAD].block_bytes=snd[RXAD].block_frames*snd[RXAD].framesize;
505 // Set the interrupt rate high in case we write to the network.
506 // This will spread out the packages in time and make them easier
507 // to pick up on a slow computer.
508     k=10;
509     if( (ui.network_flag & (NET_RXOUT_FFT1+NET_RXOUT_FFT2+NET_RXOUT_TIMF2))!=0)
510       {
511       k=400;
512       }
513     if( (ui.network_flag&(NET_RXOUT_RAW16+NET_RXOUT_RAW18+NET_RXOUT_RAW24))!=0)
514       {
515       k=200;
516       }
517 // Set interrupt rate high if the transmit side is enabled.
518 // This will reduce time jitter on the input from the morse hand key.
519     if(ui.tx_enable != 0)k=400;
520     if(k<ui.min_dma_rate)k=ui.min_dma_rate;
521     if(k>reduced_max_dma)k=reduced_max_dma;
522 // If we read from disk, allow big buffers.
523 // But not if we send to the network.
524     if( diskread_flag >=2 && (ui.network_flag & NET_RX_OUTPUT)==0)
525       {
526       while(snd[RXAD].interrupt_rate > 200)
527         {
528         snd[RXAD].block_frames*=2;
529         snd[RXAD].block_bytes*=2;
530         snd[RXAD].interrupt_rate/=2;
531         }
532       }
533     else
534       {
535       while( 2*snd[RXAD].interrupt_rate < k && snd[RXAD].block_frames>8)
536         {
537         snd[RXAD].block_frames/=2;
538         snd[RXAD].block_bytes/=2;
539         snd[RXAD].interrupt_rate*=2;
540         }
541       }
542     }
543   }
544 // With the Delta44 we save 18 bit out of the 32 bits we read.
545 // Out of the 24 bits of data the last 6 contain only noise.
546 // Allocate snd[RXAD].block_bytes even if we use 16 bit format because
547 // the network write may use this scratch area.
548 save_rw_bytes=snd[RXAD].block_bytes;
549 rx_read_bytes=snd[RXAD].block_bytes;
550 if((ui.rx_input_mode&DWORD_INPUT) != 0)save_rw_bytes=18*snd[RXAD].block_bytes/32;
551 ad_bufmargin=2*(snd[RXAD].block_bytes+fft1_size*snd[RXAD].framesize);
552 timf1_blockbytes=fft1_new_points*snd[RXAD].framesize;
553 // In case fft1_size is small, the input thread might wake up the
554 // wideband routine very often causing needless overhead.
555 fft1_hz_per_point=(float)ui.rx_ad_speed/fft1_size;
556 if( (ui.rx_input_mode&IQ_DATA) == 0)
557   {
558   fft1_hz_per_point/=2;
559   timf1_blockbytes*=2;
560   }
561 timf1_blockbytes*=fft_cntrl[FFT1_CURMODE].parall_fft;
562 timf1_blockbytes*=(fft_cntrl[FFT1_CURMODE].real2complex+1);
563 timf1_usebytes=timf1_blockbytes;
564 if(timf1_usebytes < (int)snd[RXAD].block_bytes)timf1_usebytes=snd[RXAD].block_bytes;
565 i=genparm[FIRST_FFT_NO_OF_THREADS];
566 // In case the oscilloscope for timf3 is enabled we want to
567 // update the screen at about TIMF3_OSCILLOSCOPE_RATE Hz.
568 timf3_osc_interval=twice_rxchan*(int)(timf3_sampling_speed/
569                                                       TIMF3_OSCILLOSCOPE_RATE);
570 m=1+twice_rxchan;
571 t1=screen_height/(2*m);
572 for(i=0; i<8; i++)timf3_y0[i]=screen_height-(i+1)*t1;
573 // Allow for genparm[MIX1_NO_OF_CHANNELS] signals
574 // during the time for which we have transforms plus
575 // the duration of a transform (with a 5 s margin)
576 if( genparm[SECOND_FFT_ENABLE] == 0)
577   {
578   t1=genparm[FFT1_STORAGE_TIME]+fft1_size/timf1_sampling_speed;
579   }
580 else
581   {
582   t1=genparm[FFT2_STORAGE_TIME]+fft2_size/timf1_sampling_speed;
583   }
584 t1+=5;
585 t1*=timf3_sampling_speed;
586 if((unsigned long)(t1*genparm[MIX1_NO_OF_CHANNELS]*2*twice_rxchan*sizeof(float)) > 0x7fffffffUL)
587   {
588   t1=0x7fffffff/(genparm[MIX1_NO_OF_CHANNELS]*2*twice_rxchan*sizeof(float));
589   }
590 timf3_size=t1;
591 make_power_of_two(&timf3_size);
592 while(timf3_size < 2*screen_width)timf3_size *= 2;
593 timf3_size*=twice_rxchan;
594 timf3_totsiz=genparm[MIX1_NO_OF_CHANNELS]*timf3_size;
595 while( (float)(timf3_totsiz)*2*sizeof(float) > 0x7fffff00)
596   {
597   timf3_size/=2;
598   timf3_totsiz/=2;
599   }
600 timf3_mask=timf3_size-1;
601 mix1.new_points=mix1.size-mix1.interleave_points;
602 timf3_block=twice_rxchan*mix1.new_points;
603 timf3_pa=0;
604 timf3_px=0;
605 timf3_py=0;
606 timf3_oscilloscope_limit=timf3_osc_interval+
607                                     twice_rxchan*(mix1.new_points+screen_width/2);
608 // ***********************************************************
609 // In case second fft is not enabled we need a buffer that can hold
610 // transforms during the time we average over in the AFC process
611 // in case it is enabled.
612 max_fft1n=8;
613 if(genparm[SECOND_FFT_ENABLE] == 0)
614   {
615 // Keep fft1 transforms for genparm[FFT1_STORAGE_TIME] seconds.
616   max_fft1n=genparm[FFT1_STORAGE_TIME]/fft1_blocktime;
617   make_power_of_two(&max_fft1n);
618   }
619 // Always allocate at least 8 buffers.
620 // We may average over 5 buffers and use 2 for raw data processing.
621 if(max_fft1n < 8)max_fft1n=8;
622 t1=(float)(max_fft1n)*fft1_size;
623 t1*=twice_rxchan*sizeof(float);
624 if(t1 > 0x40000000)
625   {
626   max_fft1n=0x40000000/(fft1_size*twice_rxchan*sizeof(float));
627   }
628 fft1_bytes=max_fft1n*fft1_size;
629 n=8;
630 if(8*(int)snd[RXAD].block_bytes > 4000000)n/=snd[RXAD].block_bytes/500000;
631 if(n < 1) n=1;
632 if(fft1_bytes < n*(int)snd[RXAD].block_bytes)
633                                           fft1_bytes=snd[RXAD].block_bytes*n;
634 max_fft1n=fft1_bytes/fft1_size;
635 fft1n_mask=max_fft1n-1;
636 fft1_bytes*=twice_rxchan;
637 fft1_mask=fft1_bytes-1;
638 fft1_bytes*=sizeof(float);
639 // ******************************************************
640 // We store fft1 power spectra in memory for fast calculation of averages.
641 // Check wide_graph.c for details.
642 max_fft1_sumsq=(1.+genparm[FFT1_STORAGE_TIME])/fft1_blocktime;
643 // We may group averages up to 5 to save time and space if avg time is long
644 if(rx_mode == MODE_RADAR)
645   {
646   max_fft1_sumsq*=10;
647   if((float)(max_fft1_sumsq)*fft1_size > 100000000.)
648     {
649     max_fft1_sumsq=100000000./fft1_size;
650     }
651   make_power_of_two(&max_fft1_sumsq);
652   }
653 else
654   {
655   max_fft1_sumsq/=5;
656   k=0;
657   while(max_fft1_sumsq != 0)
658     {
659     max_fft1_sumsq/=2;
660     k++;
661     }
662   max_fft1_sumsq=1<<k;
663   if(max_fft1_sumsq<64)max_fft1_sumsq=max_fft1n;
664   }
665 if(genparm[SECOND_FFT_ENABLE] != 0 ||
666      (genparm[SECOND_FFT_ENABLE] == 0 && genparm[AFC_ENABLE] == 0))
667   {
668   fft1afc_flag=0;
669   }
670 else
671   {
672   fft1afc_flag=1;
673   }
674 t1=max_fft1_sumsq*fft1_size*sizeof(float);
675 if((unsigned long)t1 > 0x3ffffffUL)
676   {
677   max_fft1_sumsq=0x3fffffff/(fft1_size*sizeof(float));
678   }
679 fft1_sumsq_bufsize=max_fft1_sumsq*fft1_size;
680 make_power_of_two(&fft1_sumsq_bufsize);
681 if(fft1_sumsq_bufsize > 0x3ffffff)fft1_sumsq_bufsize/=2;
682 max_fft1_sumsq--;
683 fft1_sumsq_mask=fft1_sumsq_bufsize-1;
684 // The raw data from the ad converter is read into timf1.
685 // This buffer is used as input to fft1. For this purpose only a
686 // small buffer is needed.
687 timf1_bytes=4*fft1_blockbytes;
688 no_of_fft1b=genparm[FIRST_FFT_NO_OF_THREADS];
689 if(no_of_fft1b > no_of_processors-1)no_of_fft1b=no_of_processors-1;
690 if(no_of_fft1b > 1)timf1_bytes*=no_of_fft1b;
691 // We read data into timf1 in blocks of snd[RXAD].block_bytes.
692 if(timf1_bytes < 2*(int)snd[RXAD].block_bytes+ad_bufmargin)
693                         timf1_bytes=2*snd[RXAD].block_bytes+ad_bufmargin;
694 timf1_bytes+=snd[RXAD].framesize;
695 // When data is saved on the hard disk we send the contents of
696 // the buffer to the hard disk through a fwrite statement that will
697 // require the data to stay unchanged until the write is completed.
698 // Allow the data to reside in the buffer for 1 second because
699 // disk writes become pretty slow occasionally.
700 t1=ui.rx_ad_speed*snd[RXAD].framesize;
701 // In case we use Windows, allow 2 seconds.
702 if(os_flag == OS_FLAG_WINDOWS )t1*=2;
703 // With very high sampling rates such as the 200 MHz of PCIe-9842
704 // the buffer becomes extremely large. Do not allow the timing
705 // requirement for disk save to increase the buffer above 32 megabytes
706 if(t1 > 32000000.0)t1=32000000.0;
707 if(timf1_bytes < t1)timf1_bytes=t1;
708 // Make sure timf1 is also a power of two
709 make_power_of_two(&timf1_bytes);
710 if(rx_mode== MODE_TUNE)timf1_bytes=2*fft1_bytes;
711 timf1_bytemask=timf1_bytes-1;
712 timf1_neg=timf1_bytes/2;
713 timf1p_pa=0;
714 timf1p_pb=0;
715 timf1p_px=0;
716 fft1_pa=0;
717 fft1_na=0;
718 fft1_pb=0;
719 fft1net_pa=0;
720 fft1net_px=0;
721 fft1_px=0;
722 fft1_nm=0;
723 fft1_nb=0;
724 fft1_nc=0;
725 fft1_nx=0;
726 // In case we use approximate conversion from real to complex data
727 // we have to allocate memory and prepare for the assembly routines
728 // in getiq.s
729 // Set a value in case we run setup first
730 fft1_sumsq_recalc=fft1_size/2;
731 
732 // To save time i.e. when oversampling we only compute spectrum between
733 // the points actually used.
734 // Set up values (full spectrum) for use in test modes.
735 wg.first_xpoint=0;
736 wg_last_point=fft1_size-1;
737 fft1_tmp_bytes=fft1_blockbytes*(fft_cntrl[FFT1_CURMODE].real2complex+1)*
738                                        fft_cntrl[FFT1_CURMODE].parall_fft;
739 if(genparm[SECOND_FFT_ENABLE] != 0 && fft_cntrl[FFT1_BCKCURMODE].mmx == 0)
740   {
741   fft1_tmp_bytes*=2;
742   }
743 if(fft1_tmp_bytes < (int)snd[RXAD].block_bytes)fft1_tmp_bytes=snd[RXAD].block_bytes;
744 // If second fft is enabled, we will calculate the noise floor
745 // in liminfo_groups segments of the entire spectrum.
746 // Start by assuming 500Hz is a reasonable bandwidth to get the
747 // noise floor in.
748 fftx_points_per_hz=1.0/fft1_hz_per_point;
749 if(genparm[SECOND_FFT_ENABLE] != 0)
750   {
751   fftx_size=fft2_size;
752   max_fftxn=max_fft2n;
753   liminfo_groups=500./fft1_hz_per_point;
754   make_power_of_two(&liminfo_groups);
755   if(liminfo_groups<16)liminfo_groups=16;
756   liminfo_group_points=fft1_size/liminfo_groups;
757   if(liminfo_group_points == 0)
758     {
759     liminfo_group_points=1;
760     liminfo_groups=fft1_size;
761     }
762   fft2_att_limit=fft2_n-1-genparm[SECOND_FFT_ATT_N];
763   fft2_to_fft1_ratio=fft2_size/fft1_size;
764   fftx_points_per_hz*=fft2_to_fft1_ratio;
765   }
766 else
767   {
768   fftx_size=fft1_size;
769   max_fftxn=max_fft1n;
770   liminfo_groups=0;
771   }
772 if(genparm[AFC_ENABLE]==0) genparm[MAX_NO_OF_SPURS] = 0;
773 fftn_tmp_bytes=fft1_tmp_bytes;
774 if(2*ui.rx_rf_channels*mix1.size*sizeof(float) > (unsigned)(fftn_tmp_bytes))
775   {
776   fftn_tmp_bytes=2*ui.rx_rf_channels*mix1.size*sizeof(float);
777   }
778 if(fft1_bytes < fft1_tmp_bytes)fft1_bytes=fft1_tmp_bytes;
779 if(rx_mode == MODE_TXTEST)
780   {
781   if(mix1.size*fft1_hz_per_point > 5300)
782     {
783     genparm[MIX1_BANDWIDTH_REDUCTION_N]++;
784     goto new_mix1_n;
785     }
786   if(mix1.size*fft1_hz_per_point < 2550)
787     {
788     genparm[MIX1_BANDWIDTH_REDUCTION_N]--;
789     goto new_mix1_n;
790     }
791   }
792 if(mix1.size > 32768)
793   {
794   genparm[MIX1_BANDWIDTH_REDUCTION_N]++;
795   goto new_mix1_n;
796   }
797 for(i=0; i<MAX_SC; i++)
798   {
799   sd[i]=0;
800   sc[i]=0;
801   }
802 }
803 
get_buffers(int filldat)804 void get_buffers(int filldat)
805 {
806 int i,j,k;
807 int split_size, afcbuf_size;
808 float t1;
809 int *inttab;
810 short int ishort;
811 afcbuf_size=0;
812 sw_onechan=(ui.rx_rf_channels==1);
813 // ***************************************************************
814 // The memory allocation is essential to program speed.
815 // Some time critical loops use several arrays. Place them next
816 // to each other in memory space so cash works well (?).
817 // (Was important for Pentium MMX, maybe not with modern computers)
818 init_memalloc(fft1mem, MAX_FFT1_ARRAYS);
819 mem( 2,&timf1_char,timf1_bytes,0);
820 mem( 3,&fft1_window,fft1_window_size*sizeof(float),0);
821 mem( 4,&fft1tab,fft1_costab_size*sizeof(COSIN_TABLE),16*sizeof(float));
822 // ***************************************************************
823 // fftw_tmp is used in THREAD_WIDEBAND_DSP in:
824 // fftw_tmp is also used in THREAD_POWTIM in:
825 k=fft1_tmp_bytes;
826 if(no_of_fft1b > 1)
827   {
828   k=no_of_fft1b*(k+4*sizeof(float));
829   }
830 if(rx_mode == MODE_RX_ADTEST)k=4*screen_width*sizeof(int);
831 mem( 5,&fftw_tmp,2*k,4*sizeof(float));
832 mem( 551,&timf2_tmp,2*fft1_tmp_bytes,8*sizeof(float));
833 // ***************************************************************
834 mem( 552,&fftn_tmp,fftn_tmp_bytes,8*sizeof(float));
835 mem( 553,&rawsave_tmp,snd[RXAD].block_bytes,0);
836 mem( 554,&rawsave_tmp_net,snd[RXAD].block_bytes,0);
837 mem( 555,&rawsave_tmp_disk,snd[RXAD].block_bytes,0);
838 mem( 6,&fft1_permute,fft1_permute_size*sizeof(short int),8*sizeof(int));
839 mem( 7,&fft1_filtercorr,fft1_blockbytes,8*sizeof(float));
840 mem( 8,&fft1_char, 2*fft1_bytes,0);
841 mem( 9,&wg_waterf_sum,fft1_size*sizeof(float),0);
842 mem(10,&fft1_sumsq,fft1_sumsq_bufsize*sizeof(float),0);
843 if(fft1afc_flag != 0)
844   {
845 // AFC based on fft1 !!
846   if(sw_onechan)
847     {
848     mem(1011,&fft1_power,fft1_size*max_fft1n*sizeof(float),0);
849     mem(1012,&fft1_powersum,fft1_size*sizeof(float),0);
850     }
851   else
852     {
853     mem(2011,&fft1_xypower,fft1_size*max_fft1n*sizeof(TWOCHAN_POWER),0);
854     mem(2012,&fft1_xysum,fft1_size*sizeof(TWOCHAN_POWER),0);
855     }
856   }
857 mem(13,&fft1_slowsum,fft1_size*sizeof(float),0);
858 if( (ui.rx_input_mode&IQ_DATA) != 0)
859   {
860   mem(14,&fft1_foldcorr,twice_rxchan*fft1_size*sizeof(float),0);
861   }
862 mem(15,&fft1_spectrum,screen_width*sizeof(short int),0);
863 mem(16,&fft1_desired,fft1_size*sizeof(float),0);
864 mem(17,&wg_waterf_yfac,fft1_size*sizeof(float),0);
865 mem(18,&mix1.permute,mix1.size*sizeof(short int),0);
866 mem(19,&mix1.table,mix1.size*sizeof(COSIN_TABLE)/2,0);
867 mem(20,&timf3_float,2*timf3_totsiz*sizeof(float),0);
868 mem(21,&timf3_graph,ui.rx_rf_channels*screen_width*sizeof(short int),0);
869 mem(22,&liminfo_wait,fft1_size*sizeof(char),0);
870 mem(23,&liminfo,2*fft1_size*sizeof(float),0);
871 mem(24,&liminfo_group_min,liminfo_groups*sizeof(float),0);
872 if(genparm[SECOND_FFT_ENABLE] != 0)
873   {
874   split_size=4*ui.rx_rf_channels*fft1_size;
875   swfloat=fft_cntrl[FFT1_BCKCURMODE].mmx == 0 &&
876                    fft_cntrl[FFT2_CURMODE].mmx == 0;
877   if(swfloat)
878     {
879     mem(25,&fft1_split_float, split_size*sizeof(float),0);
880     }
881   else
882     {
883     mem(25,&fft1_split_shi, split_size*sizeof(short int),4*sizeof(int));
884     }
885   mem( 554,&fftf_tmp,fft2_size*sizeof(float),0);
886   mem( 555,&fftt_tmp,fft2_size*sizeof(float),0);
887   mem( 640,&timf2_blockpower,ui.rx_rf_channels*
888                                     timf2_blockpower_size*sizeof(float),0);
889   }
890 mem(26,&mix1_fqwin,(mix1.size/2+16)*sizeof(float),0);
891 mem(27,&mix1.cos2win,mix1.new_points*sizeof(float),0);
892 mem(28,&mix1.sin2win,mix1.new_points*sizeof(float),0);
893 if(genparm[SECOND_FFT_ENABLE] == 0)
894   {
895   if( genparm[FIRST_FFT_SINPOW]!=0 &&
896       (genparm[FIRST_FFT_SINPOW]!= 2 || rx_mode == MODE_TXTEST))
897     {
898     mem(1029,&mix1.window,(mix1.size/2+1)*sizeof(float),0);
899     }
900   }
901 else
902   {
903   if( genparm[FIRST_FFT_SINPOW]!= 2)
904     {
905     if( genparm[FIRST_FFT_SINPOW]!=0 && genparm[FIRST_FFT_SINPOW]!= 2)
906       {
907       if( fft_cntrl[FFT1_BCKCURMODE].mmx != 0)
908         {
909         mem(2029,&fft1_inverted_mmxwin,2*(16+fft1_size/2)*4*sizeof(short int),8);
910         }
911       else
912         {
913         mem(3029,&fft1_inverted_window,(16+fft1_size/2)*sizeof(float),0);
914         }
915       }
916     }
917   mem(30,&fft1_backbuffer,4*ui.rx_rf_channels*fft1_size*sizeof(short int),0);
918   mem(31,&fft1_back_scramble,fft1_size*sizeof(short int),0);
919   mem(3925,&hg_fft2_pwrsum,2*screen_width*sizeof(float),0);
920   if(!sw_onechan)
921     {
922     mem(3926,&hg_fft2_pwr,max_fft2n*2*screen_width*sizeof(float),0);
923     }
924   if(swfloat)
925     {
926     mem(32,&timf2_float,4*ui.rx_rf_channels*timf2pow_size*sizeof(float),0);
927     if(lir_status != LIR_POWTIM)
928       {
929       mem(33,&timf2_pwr_float,timf2pow_size*sizeof(float),0);
930       }
931     else
932       {
933       mem(33,&timf2_pwr_int,2*screen_width*sizeof(float),0);
934       }
935     }
936   else
937     {
938     mem(32,&timf2_shi,4*ui.rx_rf_channels*timf2pow_size*sizeof(short int),0);
939     mem(33,&timf2_pwr_int,(timf2pow_size+8)*sizeof(int),4);
940     }
941   if(fft_cntrl[FFT1_CURMODE].permute == 2 ||
942      fft_cntrl[FFT1_CURMODE].real2complex == 1)
943     {
944     mem(34,&fft1_backtab,fft1_size*sizeof(COSIN_TABLE)/2,0);
945     }
946   if( fft_cntrl[FFT1_BCKCURMODE].mmx != 0)
947     {
948     mem(35,&fft1_mmxcosin,
949                        fft1_size*sizeof(MMX_COSIN_TABLE)/2, 8*sizeof(float));
950     }
951   if(sw_onechan)
952     {
953     mem(1039,&fft2_power_float,fft2_size*max_fft2n*sizeof(float),0);
954     mem(1040,&fft2_powersum_float,fft2_size*sizeof(float),0);
955     }
956   else
957     {
958     mem(2039,&fft2_xypower,fft2_size*max_fft2n*sizeof(TWOCHAN_POWER),0);
959     mem(2040,&fft2_xysum,fft2_size*sizeof(TWOCHAN_POWER),0);
960     }
961   mem(3039,&fft2_bigpermute,fft2_size*sizeof(int),16*sizeof(int));
962   if(fft_cntrl[FFT2_CURMODE].mmx == 0)
963     {
964     mem(1036,&fft2_float,max_fft2n*2*fft2_size*
965                                              ui.rx_rf_channels*sizeof(float),0);
966     mem(1037,&fft2_permute,fft2_size*sizeof(short int),0);
967     mem(1038,&fft2_tab,fft2_size*sizeof(COSIN_TABLE)/2,0);
968     if(genparm[SECOND_FFT_SINPOW] != 0)
969       {
970       mem(1041,&fft2_window,fft2_size*sizeof(float),0);
971       }
972     }
973   else
974     {
975     mem(3038,&fft2_short_int,max_fft2n*2*fft2_size*
976                                ui.rx_rf_channels*sizeof(short int),0);
977     mem(3040,&fft2_mmxcosin,
978                       fft2_size*sizeof(MMX_COSIN_TABLE)/2, 16*sizeof(float));
979     mem(3041,&fft2_mmxwin,fft2_size*sizeof(short int),0);
980     }
981   if( lir_status==LIR_POWTIM ||
982       (genparm[SECOND_FFT_SINPOW]!= 0 && genparm[SECOND_FFT_SINPOW]!= 2))
983     {
984     mem(3042,&mix1.window,(mix1.size/2+1)*sizeof(float),0);
985     }
986   }
987 if(genparm[SECOND_FFT_ENABLE] == 0)
988   {
989   afcbuf_size=max_fft1n*MAX_MIX1;
990   }
991 else
992   {
993   afcbuf_size=max_fft2n*MAX_MIX1;
994   }
995 if(genparm[AFC_ENABLE] != 0)
996   {
997   mem(43,&mix1_fq_mid,afcbuf_size*sizeof(float),0);
998   mem(44,&mix1_fq_start,afcbuf_size*sizeof(float),0);
999   mem(45,&mix1_fq_curv,afcbuf_size*sizeof(float),0);
1000   mem(46,&mix1_fq_slope,afcbuf_size*sizeof(float),0);
1001   mem(47,&mix1_eval_avgn,afcbuf_size*sizeof(short int),0);
1002   mem(48,&mix1_eval_fq,afcbuf_size*sizeof(float),0);
1003   mem(49,&mix1_eval_sigpwr,afcbuf_size*sizeof(float),0);
1004   mem(50,&mix1_eval_noise,afcbuf_size*sizeof(float),0);
1005   mem(51,&mix1_fitted_fq,afcbuf_size*sizeof(float),0);
1006   }
1007 // Allocate memory for automatic spur cancellation
1008 if(genparm[MAX_NO_OF_SPURS] != 0)
1009   {
1010   if(genparm[MAX_NO_OF_SPURS] > fftx_size/SPUR_WIDTH)
1011     {
1012     genparm[MAX_NO_OF_SPURS] = fftx_size/SPUR_WIDTH;
1013     }
1014   spur_block=SPUR_WIDTH*max_fftxn*twice_rxchan;
1015   if(genparm[SECOND_FFT_ENABLE] !=0 && fft_cntrl[FFT2_CURMODE].mmx != 0)
1016     {
1017     mem(1052,&spur_table_mmx,
1018                genparm[MAX_NO_OF_SPURS]*spur_block*sizeof(short int),0);
1019     }
1020   else
1021     {
1022     mem(2052,&spur_table,
1023                    genparm[MAX_NO_OF_SPURS]*spur_block*sizeof(float),0);
1024     }
1025   mem(53,&spur_location, genparm[MAX_NO_OF_SPURS]*sizeof(int),0);
1026   mem(54,&spur_flag, genparm[MAX_NO_OF_SPURS]*sizeof(int),0);
1027   mem(55,&spur_power, SPUR_WIDTH*sizeof(float),0);
1028   mem(56,&spur_d0pha, genparm[MAX_NO_OF_SPURS]*sizeof(float),0);
1029   mem(57,&spur_d1pha, genparm[MAX_NO_OF_SPURS]*sizeof(float),0);
1030   mem(58,&spur_d2pha, genparm[MAX_NO_OF_SPURS]*sizeof(float),0);
1031   mem(59,&spur_ampl, genparm[MAX_NO_OF_SPURS]*sizeof(float),0);
1032   mem(60,&spur_noise, genparm[MAX_NO_OF_SPURS]*sizeof(float),0);
1033   mem(61,&spur_avgd2, genparm[MAX_NO_OF_SPURS]*sizeof(float),0);
1034   mem(62,&spur_pol,genparm[MAX_NO_OF_SPURS]*3*sizeof(float),0);
1035   mem(63,&spur_spectra,NO_OF_SPUR_SPECTRA*SPUR_SIZE*sizeof(float),0);
1036   mem(64,&spur_freq, genparm[MAX_NO_OF_SPURS]*sizeof(int),0);
1037   mem(65,&spur_ind, genparm[MAX_NO_OF_SPURS]*max_fftxn*sizeof(int),0);
1038   mem(66,&spur_signal, max_fftxn*twice_rxchan*
1039                               genparm[MAX_NO_OF_SPURS]*sizeof(float),0);
1040   if(sw_onechan)
1041     {
1042     mem(67,&spursearch_powersum,fftx_size*sizeof(float),0);
1043     }
1044   else
1045     {
1046     mem(68,&spursearch_xysum,fftx_size*sizeof(TWOCHAN_POWER),0);
1047     }
1048   mem(67,&spursearch_spectrum,fftx_size*sizeof(float),0);
1049   spur_speknum=0.1*genparm[SPUR_TIMECONSTANT]/fftx_blocktime;
1050   if(spur_speknum < 4)spur_speknum=4;
1051   if(4*spur_speknum > max_fftxn && genparm[MAX_NO_OF_SPURS] != 0)
1052     {
1053     lir_status=LIR_SPURERR;
1054     return;
1055     }
1056   spursearch_sum_counter=0;
1057   sp_numsub=spur_speknum-1;
1058   sp_avgnum=spur_speknum/3;
1059   if(sp_avgnum > 10)sp_avgnum=10;
1060   spur_max_d2=PI_L*spur_freq_factor/spur_speknum;
1061 // The spur signal is coherently averaged over spur_speknum transforms
1062 // while noise is non-coherent rms value.
1063 // Set the minimum S/N for at least 3dB in the narrower bandwidth for
1064 // the noise we would get if the noise vas evaluated at the
1065 // same bandwidth as the signal.
1066   spur_minston=1/sqrt(0.5*(float)(spur_speknum));
1067 // Make spur_weiold/new These parameters prevent the second
1068 // derivative of the phase (frequency drift) to change rapidly.
1069   t1=0.5*spur_speknum;
1070   spur_weiold=t1/(1+t1);
1071   spur_weinew=1/(1+t1);
1072 // To fit a straight line to spur phase we need sum of squares.
1073   t1=-0.5*sp_numsub;
1074   spur_linefit=0;
1075   for(i=0; i<spur_speknum; i++)
1076     {
1077     spur_linefit+=t1*t1;
1078     t1+=1;
1079     }
1080   }
1081 no_of_spurs=0;
1082 baseband_totmem=0;
1083 afc_totmem=0;
1084 hires_totmem=0;
1085 fft3_totmem=0;
1086 // *********************************************************
1087 // Memory allocations for tx test mode.
1088 if(rx_mode == MODE_TXTEST)
1089   {
1090   mem(7201,&txtest_ypeak, screen_width*sizeof(short int),0);
1091   mem(7211,&txtest_ypeak_decay, screen_width*sizeof(short int),0);
1092   mem(7202,&txtest_yavg, screen_width*sizeof(short int),0);
1093   i=(1+5*max_fft1_sumsq)*screen_width;
1094   mem(7203,&txtest_power, i*sizeof(float),0);
1095   mem(7204,&txtest_powersum, screen_width*sizeof(float),0);
1096   mem(7205,&txtest_peak_power, screen_width*sizeof(float),0);
1097   mem(7215,&txtest_peak_power_decay, screen_width*sizeof(float),0);
1098   mem(7206,&txtest_old_yavg, screen_width*sizeof(short int),0);
1099   mem(7207,&txtest_old_ypeak, screen_width*sizeof(short int),0);
1100   mem(7217,&txtest_old_ypeak_decay, screen_width*sizeof(short int),0);
1101   mem(7208,&fft1_old_spectrum, screen_width*sizeof(short int),0);
1102   }
1103 i=screen_width;
1104 make_power_of_two(&i);
1105 mg_size=i;
1106 mg_mask=mg_size-1;
1107 mem(7246,&mg_barbuf, 3*text_width*screen_height*sizeof(char),0);
1108 mem(7247,&mg_rms_meter, mg_size*ui.rx_rf_channels*sizeof(float),0);
1109 mem(7248,&mg_peak_ypix, 2*mg_size*ui.rx_rf_channels*sizeof(short int),0);
1110 mem(7249,&mg_rms_ypix, 2*mg_size*ui.rx_rf_channels*sizeof(short int),0);
1111 mem(7250,&mg_behind_meter, screen_height*sizeof(char),0);
1112 mem(7254,&mg_peak_meter, mg_size*ui.rx_rf_channels*sizeof(float),0);
1113 if( (ui.network_flag&NET_RXOUT_FFT1) != 0)
1114   {
1115   fft1net_size=fft1_blockbytes*FFT1_NETSEND_MAXBUF;
1116   fft1net_mask=fft1net_size-1;
1117   mem(7467,&fft1_netsend_buffer,fft1net_size,0);
1118   }
1119 if( (ui.network_flag&NET_RXOUT_BASEB) != 0)
1120   {
1121 // Allocate space for 0.3 seconds of data.
1122   basebnet_size=0.3*genparm[DA_OUTPUT_SPEED]*2*
1123                                       ui.rx_rf_channels*sizeof(short int);
1124   make_power_of_two(&basebnet_size);
1125   basebnet_mask=basebnet_size-1;
1126   mem(7577,&baseb_netsend_buffer,basebnet_size,0);
1127   basebnet_block_bytes=(2*ui.rx_rf_channels*genparm[DA_OUTPUT_SPEED])
1128                                                        /ui.max_dma_rate;
1129   make_power_of_two(&basebnet_block_bytes);
1130   }
1131 if(genparm[FFT1_CORRELATION_SPECTRUM]!=0 && ui.rx_rf_channels==2)
1132   {
1133 // Allocate memory for an averaged correlation spectrum in the main
1134 // spectrum window.
1135   fft1_correlation_flag=TRUE;
1136   mem(8101,&fft1_corrsum,2*fft1_sumsq_bufsize*sizeof(float),0);
1137   mem(8102,&fft1_slowcorr,2*fft1_size*sizeof(float),0);
1138   mem(8103,&fft1_corr_spectrum,screen_width*sizeof(short int),0);
1139   }
1140 else
1141   {
1142   fft1_correlation_flag=FALSE;
1143   }
1144 fftx_totmem=memalloc(&fft1_handle,"fft1,fft2");
1145 if(fftx_totmem==0)
1146   {
1147   lir_status=LIR_FFT1ERR;
1148   return;
1149   }
1150 if(filldat==0)return;
1151 fft1_calibrate_flag=0;
1152 for(i=0; i<genparm[MAX_NO_OF_SPURS]*max_fftxn; i++)spur_ind[i]=-1;
1153 if(genparm[AFC_ENABLE] != 0)
1154   {
1155   for(i=0; i<afcbuf_size; i++)mix1_fq_mid[i]=-1;
1156   for(i=0; i<afcbuf_size; i++)mix1_fq_start[i]=-1;
1157   for(i=0; i<afcbuf_size; i++)mix1_fq_slope[i]=0;
1158   for(i=0; i<afcbuf_size; i++)mix1_fq_curv[i]=0;
1159   for(i=0; i<MAX_MIX1; i++)mix1_phase_step[i]=0;
1160   for(i=0; i<MAX_MIX1; i++)mix1_phase[i]=0;
1161   for(i=0; i<MAX_MIX1; i++)mix1_phase_rot[i]=0;
1162   for(i=0; i<MAX_MIX1; i++)mix1_old_phase[i]=0;
1163   for(i=0; i<MAX_MIX1; i++)mix1_old_point[i]=0;
1164   }
1165 if(genparm[SECOND_FFT_ENABLE] != 0)
1166   {
1167   for(i=0; i<2*screen_width; i++)hg_fft2_pwrsum[i]=1;
1168   }
1169 timf1_float=(float*)(timf1_char);
1170 timf1_int=(int*)(timf1_char);
1171 timf1_short_int=(short int*)(timf1_char);
1172 rxin_isho=(short int*)(timf1_char);
1173 rxin_int=(int*)(timf1_char);
1174 rxin_char=(char*)(timf1_char);
1175 fft1_short_int=(short int*)(fft1_char);
1176 fft1_int=(int*)(fft1_char);
1177 fft1_float=(float*)(fft1_char);
1178 timf3_int=(int*)(timf3_float);
1179 if(genparm[MAX_NO_OF_SPURS] != 0)
1180   {
1181 // Spur removal runs with fft1 or fft2. Place its scratch areas
1182 // on the correct thread.
1183   if(genparm[SECOND_FFT_ENABLE] == 0)
1184     {
1185     sp_sig=(float*)(fftw_tmp);
1186     }
1187   else
1188     {
1189     sp_sig=(float*)(fftf_tmp);
1190     }
1191   sp_der=(float*)((void*)(sp_sig)+fftx_size*sizeof(float)/4);
1192   sp_pha=(float*)((void*)(sp_der)+fftx_size*sizeof(float)/4);
1193   sp_tmp=(float*)((void*)(sp_pha)+fftx_size*sizeof(float)/4);
1194   for(i=0; i<fftx_size; i++)spursearch_spectrum[i]=1;
1195   }
1196 // *********************************************************************
1197 make_window(5,mix1.size, 4, mix1_fqwin);
1198 if(genparm[SECOND_FFT_ENABLE] == 0)
1199   {
1200   if(lir_status != LIR_POWTIM) prepare_mixer(&mix1, FIRST_FFT_SINPOW);
1201   }
1202 else
1203   {
1204   prepare_mixer(&mix1, SECOND_FFT_SINPOW);
1205   if( genparm[FIRST_FFT_SINPOW]!= 2)
1206     {
1207     if( fft_cntrl[FFT1_BCKCURMODE].mmx != 0)
1208       {
1209       make_mmxwindow(3,fft1_size, genparm[FIRST_FFT_SINPOW], fft1_inverted_mmxwin);
1210       }
1211     else
1212       {
1213       make_window(3,fft1_size, genparm[FIRST_FFT_SINPOW], fft1_inverted_window);
1214       }
1215     }
1216   make_permute(fft_cntrl[FFT1_BCKCURMODE].permute, fft1_n,
1217                                                 fft1_size, fft1_back_scramble);
1218   if(fft_cntrl[FFT1_CURMODE].permute == 2 ||
1219      fft_cntrl[FFT1_CURMODE].real2complex == 1)
1220     {
1221     make_sincos(0, fft1_size, fft1_backtab);
1222     }
1223   else
1224     {
1225     fft1_backtab=fft1tab;
1226     }
1227   if( fft_cntrl[FFT1_BCKCURMODE].mmx != 0)
1228     {
1229     init_mmxfft(fft1_size,fft1_mmxcosin);
1230     }
1231   make_bigpermute(fft_cntrl[FFT2_CURMODE].permute,
1232                                         fft2_n, fft2_size, fft2_bigpermute);
1233   if(fft_cntrl[FFT2_CURMODE].mmx == 0)
1234     {
1235     make_sincos(1, fft2_size, fft2_tab);
1236 // ****************************************************
1237     if(genparm[SECOND_FFT_SINPOW] != 0)
1238       {
1239       make_window(fft_cntrl[FFT2_CURMODE].window,fft2_size,
1240                                     genparm[SECOND_FFT_SINPOW], fft2_window);
1241       }
1242     }
1243   else
1244     {
1245     if(genparm[SECOND_FFT_SINPOW] != 0)
1246       {
1247       make_mmxwindow(0,fft2_size, genparm[SECOND_FFT_SINPOW], fft2_mmxwin);
1248 // Scramble the window so we get it in the order it will be used.
1249       for(i=0; i<fft2_size; i++)
1250         {
1251         j=fft2_bigpermute[i];
1252         if(j<i)
1253           {
1254           ishort=fft2_mmxwin[i];
1255           fft2_mmxwin[i]=fft2_mmxwin[j];
1256           fft2_mmxwin[j]=ishort;
1257           }
1258         }
1259       }
1260 // Scale fft2_bigpermute so mmx routines do not have to multiply addresses.
1261     if(sw_onechan)
1262       {
1263       k=8;
1264       }
1265     else
1266       {
1267       k=16;
1268       }
1269     for(i=0; i<fft2_size; i++)fft2_bigpermute[i]*=k;
1270 // The mmx routine wants to negate the imaginary parts in the first
1271 // loop. Put suitable pattern for before bigpermute.
1272     fft2_bigpermute[-1]=0xffff0000;
1273     fft2_bigpermute[-2]=0xffff0000;
1274     fft2_bigpermute[-3]=0x10000;
1275     fft2_bigpermute[-4]=0x10000;
1276     fft2_bigpermute[-5]=0xffff;
1277     fft2_bigpermute[-6]=0xffff;
1278     fft2_bigpermute[-7]=1;
1279     fft2_bigpermute[-8]=1;
1280     fft2_bigpermute[-9]=0xffff;
1281     fft2_bigpermute[-10]=0xffff0000;
1282     fft2_bigpermute[-11]=1;
1283     fft2_bigpermute[-12]=0x10000;
1284     init_mmxfft(fft2_size,fft2_mmxcosin);
1285     }
1286   }
1287 // Store bitmask for use by SIMD routine in scratch area before fft1tab
1288 inttab=(int*)(fft1tab);
1289 inttab[-1]=0x80000000;
1290 inttab[-2]=0;
1291 inttab[-3]=0x80000000;
1292 inttab[-4]=0;
1293 // Bitmask for use by simd routine in scratch area before fft1_filtercorr
1294 inttab=(int*)(fft1_filtercorr);
1295 inttab[-1]=0x80000000;
1296 inttab[-2]=0;
1297 inttab[-3]=0x80000000;
1298 inttab[-4]=0;
1299 if(kill_all_flag)return;
1300 i=1;
1301 if(fft_cntrl[FFT1_CURMODE].permute == 2)i=2;
1302 if(fft_cntrl[FFT1_CURMODE].real2complex == 0)
1303   {
1304   make_sincos(i, fft1_size, fft1tab);
1305   make_permute(fft_cntrl[FFT1_CURMODE].permute, fft1_n, fft1_size, fft1_permute);
1306   make_window(fft_cntrl[FFT1_CURMODE].window,fft1_size,
1307                                        genparm[FIRST_FFT_SINPOW], fft1_window);
1308   j=fft1_size;
1309   }
1310 else
1311   {
1312   make_sincos(i, 2*fft1_size, fft1tab);
1313   make_permute(fft_cntrl[FFT1_CURMODE].permute, fft1_n+1,
1314                                                 2*fft1_size, fft1_permute);
1315   make_window(fft_cntrl[FFT1_CURMODE].window,2*fft1_size,
1316                                        genparm[FIRST_FFT_SINPOW], fft1_window);
1317   }
1318 if( (ui.network_flag & NET_RXIN_FFT1) == 0)
1319   {
1320   init_fft1_filtercorr();
1321   if(kill_all_flag)return;
1322   if( (ui.rx_input_mode&IQ_DATA) != 0)
1323     {
1324     init_foldcorr();
1325     }
1326   if(kill_all_flag)return;
1327   }
1328 memset(fft1_char,0,fft1_bytes);
1329 memset(liminfo,0,2*fft1_size*sizeof(float));
1330 memset(liminfo_wait,0,fft1_size*sizeof(unsigned char));
1331 memset(fft1_slowsum,0,fft1_size*sizeof(float));
1332 if(fft1_correlation_flag)memset(fft1_slowcorr,0,2*fft1_size*sizeof(float));
1333 memset(wg_waterf_sum,0,fft1_size*sizeof(float));
1334 memset(timf1_char,0,timf1_bytes);
1335 memset(fft1_sumsq,0,fft1_sumsq_bufsize*sizeof(float));
1336 memset(timf3_float,0,2*timf3_totsiz*sizeof(float));
1337 memset(fft1_spectrum,-32000,screen_width*sizeof(short int));
1338 if(genparm[SECOND_FFT_ENABLE] != 0)
1339   {
1340   if(swfloat)
1341     {
1342     if(lir_status != LIR_POWTIM)
1343       {
1344       for(i=0; i<timf2pow_size; i++)
1345         {
1346         timf2_pwr_float[i]=0.5;
1347         }
1348       }
1349     memset(timf2_float,0,4*ui.rx_rf_channels*timf2pow_size*sizeof(float));
1350     }
1351   else
1352     {
1353     for(i=0;i<timf2pow_size+8; i++)timf2_pwr_int[i]=4;
1354     memset(timf2_shi,0,4*ui.rx_rf_channels*timf2pow_size*sizeof(short int));
1355     }
1356   }
1357 memset(mg_rms_meter,0,mg_size*ui.rx_rf_channels*sizeof(float));
1358 memset(mg_peak_meter,0,mg_size*ui.rx_rf_channels*sizeof(float));
1359 memset(mg_rms_ypix,0,2*mg_size*ui.rx_rf_channels*sizeof(short int));
1360 memset(mg_peak_ypix,0,2*mg_size*ui.rx_rf_channels*sizeof(short int));
1361 measured_ad_speed=-1;
1362 measured_da_speed=-1;
1363 fft1_sumsq_counter=0;
1364 fft1_sumsq_tot=0;
1365 wg_flag=0;
1366 hg_flag=0;
1367 ag_flag=0;
1368 bg_flag=0;
1369 pg_flag=0;
1370 cg_flag=0;
1371 eg_flag=0;
1372 fg_flag=0;
1373 mg_flag=0;
1374 tg_flag=0;
1375 rg_flag=0;
1376 eme_active_flag=0;
1377 timinfo_flag=0;
1378 ampinfo_flag=0;
1379 numinput_flag=0;
1380 no_of_scro=0;
1381 fft1_sumsq_pa=0;
1382 fft1_sumsq_pwg=0;
1383 wg_waterf_sum_counter=0;
1384 wg_waterf=NULL;
1385 wg_waterf_ptr=0;
1386 bg_waterf_sum_counter=0;
1387 bg_waterf=NULL;
1388 bg_waterf_ptr=0;
1389 local_bg_waterf_ptr=0;
1390 wg_background=NULL;
1391 fft1_noise_floor=0;
1392 overrun_count=0;
1393 new_baseb_flag=-1;
1394 diskread_pause_flag=0;
1395 fft1back_lowgain_n=genparm[FIRST_BCKFFT_ATT_N];
1396 // In case fft2 is much bigger than fft1 it will be a good idea to
1397 // split fft2 processing into smaller chunks so overrun problems
1398 // will not occur.
1399 t1=(float)(fft2_new_points)/fft1_new_points;
1400 fft2_chunk_n=(int)(1+fft2_n/t1)&0xfffffffe;
1401 if(fft2_chunk_n<2)fft2_chunk_n=2;
1402 for(i=0; i<genparm[MIX1_NO_OF_CHANNELS]; i++)
1403   {
1404   mix1_selfreq[i]=-1;
1405   mix1_curx[i]=-1;
1406   new_mix1_curx[i]=-1;
1407   }
1408 // Clear variables that might become uninitialised
1409 total_wttim=0;
1410 ad_wttim=0;
1411 fft1_wttim=0;
1412 timf2_wttim=0;
1413 fft2_wttim=0;
1414 timf3_wttim=0;
1415 fft3_wttim=0;
1416 baseb_wttim=0;
1417 db_wttim=0;
1418 da_wttim=0;
1419 afc_tpts=0;
1420 afc_curx=-1;
1421 hg_curx=-1;
1422 // Initialise fftx variables (used by AFC)
1423 if(genparm[SECOND_FFT_ENABLE] != 0)
1424   {
1425   fftxn_mask=fft2n_mask;
1426   fftx_na=fft2_na;
1427   fftx_pwr=fft2_power_float;
1428   fftx_nm=fft2_nm;
1429   fftx_nx=fft2_nx;
1430   fftx_xypower=fft2_xypower;
1431   fftx=fft2_float;
1432   }
1433 else
1434   {
1435   fftxn_mask=fft1n_mask;
1436   fftx_na=fft1_nb;
1437   fftx_pwr=fft1_power;
1438   fftx_nm=fft1_nm;
1439   fftx_nx=fft1_nx;
1440   fftx=fft1_float;
1441   fftx_xypower=fft1_xypower;
1442   }
1443 if(fft1afc_flag != 0)
1444   {
1445 // AFC based on fft1 !!
1446   if(sw_onechan)
1447     {
1448     memset(fft1_power,0,max_fft1n*fft1_size*sizeof(float));
1449     }
1450   else
1451     {
1452     memset(fft1_xypower,0,fft1_size*max_fft1n*sizeof(TWOCHAN_POWER));
1453     }
1454   }
1455 if(genparm[AFC_ENABLE] != 0)
1456   {
1457   for(i=0; i<afcbuf_size; i++)
1458     {
1459     mix1_eval_noise[i]=1;
1460     mix1_eval_fq[i]=1;
1461     }
1462   }
1463 if(genparm[SECOND_FFT_ENABLE] != 0)
1464   {
1465   if(fft_cntrl[FFT2_CURMODE].mmx == 0)
1466     {
1467     memset(fft2_float,0,max_fft2n*2*fft2_size*ui.rx_rf_channels*sizeof(float));
1468     }
1469   else
1470     {
1471     memset(fft2_short_int,0,max_fft2n*2*fft2_size*ui.rx_rf_channels*sizeof(short int));
1472     }
1473   if(sw_onechan)
1474     {
1475     memset(fft2_power_float,0,max_fft2n*fft2_size*sizeof(float));
1476     }
1477   else
1478     {
1479     memset(fft2_xypower,0,fft2_size*max_fft2n*sizeof(TWOCHAN_POWER));
1480     }
1481   }
1482 if(genparm[MAX_NO_OF_SPURS] != 0)
1483   {
1484   init_spur_spectra();
1485   }
1486 if(rx_mode == MODE_TXTEST)
1487   {
1488   for(i=0; i<screen_width; i++)txtest_peak_power_decay[i]=0.1;
1489   for(i=0; i<screen_width; i++)txtest_powersum[i]=0.1;
1490   k=(1+5*max_fft1_sumsq)*screen_width;
1491   for(i=0; i<k; i++)txtest_power[i]=0.1;
1492   }
1493 
1494 
1495 wav_write_flag=0;
1496 audio_dump_flag=0;
1497 swmmx_fft2=(genparm[SECOND_FFT_ENABLE] != 0
1498                                      && fft_cntrl[FFT2_CURMODE].mmx != 0);
1499 swmmx_fft1=(genparm[SECOND_FFT_ENABLE] != 0
1500                                      && fft_cntrl[FFT1_BCKCURMODE].mmx != 0);
1501 old_passband_center=-1;
1502 indicator_first_pixel=29*text_width;
1503 indicator_ypix=screen_height-3.5*text_height;
1504 timf1_indicator_block=timf1_bytes/INDICATOR_SIZE;
1505 fft1_indicator_block=(fft1_mask+1)/INDICATOR_SIZE;
1506 timf2_indicator_block=(timf2_mask+1)/INDICATOR_SIZE;
1507 fft2n_indicator_block=max_fft2n*fft2_size/INDICATOR_SIZE;
1508 timf3_indicator_block=timf3_size/INDICATOR_SIZE;
1509 clear_wide_maxamps();
1510 for(i=0; i<MAX_SC; i++)sc[i]=0;
1511 // Disable the S-meter averaging. (F2 while running to enable)
1512 s_meter_avgnum=-1;
1513 // Print some info in case we have a dump file
1514 if(dmp!=NULL)
1515   {
1516   PERMDEB"ui.rx_rf_channels=%d, ",ui.rx_rf_channels);
1517   PERMDEB"ui.rx_ad_channels=%d\n",ui.rx_ad_channels);
1518   if( (ui.rx_input_mode&DWORD_INPUT) == 0)
1519     {
1520     PERMDEB"NOT ");
1521     }
1522   PERMDEB"DWORD INPUT, ");
1523   if( (ui.rx_input_mode&QWORD_INPUT) == 0)
1524     {
1525     PERMDEB"NOT ");
1526     }
1527   PERMDEB"QWORD INPUT, ");
1528   if( (ui.rx_input_mode&FLOAT_INPUT) == 0)
1529     {
1530     PERMDEB"NOT ");
1531     }
1532   PERMDEB"FLOAT INPUT\n");
1533   if( (ui.rx_input_mode&BYTE_INPUT) == 0)
1534     {
1535     PERMDEB"NOT ");
1536     }
1537   PERMDEB"BYTE INPUT, ");
1538   if( (ui.rx_input_mode&DIGITAL_IQ) == 0)
1539     {
1540     PERMDEB"NOT ");
1541     }
1542   PERMDEB"DIGITAL_IQ, ");
1543   if( (ui.rx_input_mode&IQ_DATA) == 0)
1544     {
1545     PERMDEB"NOT ");
1546     }
1547   PERMDEB"IQ DATA, snd[RXAD].block_bytes %d, ",snd[RXAD].block_bytes);
1548   PERMDEB"\nRXin interrupt_rate %.1f\n",snd[RXAD].interrupt_rate);
1549 //
1550   PERMDEB"fft1_n %d, ",fft1_n);
1551   PERMDEB"fft1_size %d, ",fft1_size);
1552   PERMDEB"interleave (_ratio %f  _points %d)\n",
1553                               fft1_interleave_ratio,fft1_interleave_points);
1554 //
1555   PERMDEB"fft1mode %d, ",fft1mode);
1556   PERMDEB"snd[RXAD].framesize %d, ",snd[RXAD].framesize);
1557   PERMDEB"fft1 vers [%d] %s\n",genparm[FIRST_FFT_VERNR],
1558                                         fft_cntrl[FFT1_CURMODE].text);
1559 //
1560   PERMDEB"timf1_blockbytes %d, ",timf1_blockbytes);
1561   PERMDEB"fft1_blockbytes %d, ",fft1_blockbytes);
1562   PERMDEB"timf1_bytes %d\n",timf1_bytes);
1563 //
1564   PERMDEB"fft1_bytes %d, ",fft1_bytes);
1565   PERMDEB"max_fft1_sumsq %d, ",max_fft1_sumsq);
1566   PERMDEB"fft1win (N) %d, ",genparm[FIRST_FFT_SINPOW]);
1567   PERMDEB"mix1.size %d\n",mix1.size);
1568 //
1569   PERMDEB"backwards fft1: ");
1570   if(swfloat)
1571     {
1572     PERMDEB"32 bit float");
1573     }
1574   else
1575     {
1576     PERMDEB"16 bit int");
1577     }
1578   PERMDEB", fft2_size %d, ",fft2_size);
1579   if(fft_cntrl[FFT2_CURMODE].mmx == 0)
1580     {
1581     PERMDEB"32 bit float");
1582     }
1583   else
1584     {
1585     PERMDEB"16 bit int");
1586     }
1587   PERMDEB"\ntimf3_size %d, ",timf3_size);
1588   PERMDEB"timf3_sampling_speed %f\n",timf3_sampling_speed);
1589   fflush(dmp);
1590   }
1591 memcheck(1,fft1mem,&fft1_handle);
1592 no_of_rx_overrun_errors=0;
1593 no_of_rx_underrun_errors=0;
1594 no_of_tx_overrun_errors=0;
1595 no_of_tx_underrun_errors=0;
1596 count_rx_underrun_flag=FALSE;
1597 internal_generator_phase1=0;
1598 internal_generator_phase2=0;
1599 internal_generator_shift=0;
1600 internal_generator_key=0;
1601 ag.mode_control=0;
1602 accumulated_netwait_time=0;
1603 }
1604 
init_blanker(void)1605 void init_blanker(void)
1606 {
1607 int i,j,k,m;
1608 unsigned short int *tmp_permute;
1609 COSIN_TABLE *tmp_tab;
1610 float t1,t2,t3,t4,t5,t6,r1,r2,phrot;
1611 float *buf2, *buf3;
1612 int me01, me04;
1613 buf2=(float*)((void*)(fft1_float)+2*fft1_blockbytes);
1614 buf3=(float*)((void*)(fft1_float)+3*fft1_blockbytes);
1615 me04=((twice_rxchan+1)*(screen_width+1)*sizeof(short int)+15)&0xfffffff0;
1616 // In case the system is properly calibrated we can use
1617 // fft1_desired to get the pulse response of our system.
1618 init_memalloc(blankermem,MAX_BLANKER_ARRAYS);
1619 mem(5,&timf2pix,me04,0);
1620 if( (fft1_calibrate_flag&CALAMP)==CALAMP)
1621   {
1622 // Place the pulse at 8 different positions from -0.5 to +0.5
1623 // in order to even out oscillatory behaviors.
1624 // Store the accumulated pulse power in buf2
1625   tmp_permute=(unsigned short int*)(fft1_float);
1626   tmp_tab=(COSIN_TABLE*)((void*)(fft1_float)+fft1_blockbytes);
1627   init_fft(0,fft1_n, fft1_size, tmp_tab, tmp_permute);
1628   for(i=0; i<fft1_size/2; i++)buf2[i]=0;
1629   t3=0.25*PI_L/fft1_size;
1630   for(k=0; k<8; k++)
1631     {
1632     t1=0;
1633     t2=(k-3.75)*t3;
1634     for(i=0; i<fft1_size; i++)
1635       {
1636       fftw_tmp[2*i  ]=cos(t1)*fft1_desired[i];
1637       fftw_tmp[2*i+1]=sin(t1)*fft1_desired[i];
1638       t1+=t2;
1639       }
1640     fftback(fft1_size, fft1_n, fftw_tmp, tmp_tab, tmp_permute,FALSE);
1641     buf2[0]+=pow(fftw_tmp[1],2.)+pow(fftw_tmp[0],2.);
1642     for(i=1; i<fft1_size/2; i++)
1643       {
1644       j=fft1_size-i;
1645       buf2[i]+=pow(fftw_tmp[2*i+1],2.)+pow(fftw_tmp[2*i  ],2.)
1646               +pow(fftw_tmp[2*j+1],2.)+pow(fftw_tmp[2*j  ],2.);
1647       }
1648     }
1649 // Store the relative pulse level=bln[i].rest that remains outside
1650 // a region of a width=bln[i].size corresponding to a power of n=bln[i].n
1651   for(i=0; i<BLN_INFO_SIZE; i++)
1652     {
1653     bln[i].n=i+2;
1654     bln[i].size=1<<bln[i].n;
1655     bln[i].rest=0.5*(buf2[bln[i].size/2]+buf2[bln[i].size/2-1])/buf2[0];
1656     bln[i].avgmax=(i+1)*(i+1)*bln[i].size;
1657     }
1658 // skip if rest is too small (-90 dB).
1659   i=BLN_INFO_SIZE-1;
1660   while(bln[i].rest < 0.000000001)
1661     {
1662     bln[i].rest=0;
1663     i--;
1664     }
1665   largest_blnfit=i;
1666   refpul_n=bln[i].n;
1667   refpul_size=bln[i].size;
1668   me01=2*MAX_REFPULSES*refpul_size;
1669 // Calculate the summed power of the outer size/2 points
1670 // for each size.
1671 // Store relative to buf2[0] in bln[i].avgpwr
1672   j=1;
1673   i=0;
1674   k=2;
1675 check_avgpwr:;
1676   t1=0;
1677   while(k < bln[i].size)
1678     {
1679     t1+=buf2[j];
1680     j++;
1681     k+=2;
1682     }
1683   bln[i].avgpwr=t1/buf2[0];
1684   i++;
1685   if(i <=largest_blnfit)goto check_avgpwr;
1686 // Find the -15dB width of the pulse response but do not make
1687 // blanker_pulsewidth smaller than 2.
1688   blanker_pulsewidth=2;
1689   while(buf2[blanker_pulsewidth]>0.033*buf2[0])blanker_pulsewidth++;
1690 // ********************************************************
1691 // We now know refpul_size, the total length of the pulse response
1692 // for the current hardware and calibration.
1693 // Allocate memory for the clever (linear) noise blanker.
1694 // ********************************************************
1695 // ********************************************************
1696 // ********************************************************
1697 // ********************************************************
1698   mem(1,&blanker_refpulse,me01*sizeof(float),0);
1699   mem(2,&blanker_phasefunc,2*refpul_size*sizeof(float),0);
1700   mem(3,&blanker_pulindex,MAX_REFPULSES*sizeof(int),0);
1701   mem(4,&blanker_input,twice_rxchan*refpul_size*sizeof(float),0);
1702   mem(6,&blanker_flag,((ui.rx_rf_channels*timf2_mask/4+16)*sizeof(char)),0);
1703   i=memalloc(&blanker_handle,"blanker");
1704   if(i == 0)
1705     {
1706     lirerr(1061);
1707     return;
1708     }
1709 // **************************
1710 // Use fft1_desired to get time domain in fft1_size points.
1711 // Reduce to the number of points we actually want.
1712 // Produce MAX_REFPULSES standard pulses, all shifted differently in time.
1713 // The time shifted pulses are obtained by change of the phase slope.
1714 // To shift by one sample point in time, the phase slope has to change
1715 // by 2*pi/refpul_size.
1716 // Normalise the reference pulses so the amplitude = 1 and the phase = 0
1717 // for the max point
1718 // **************************
1719   for(i=0; i<fft1_size; i++)
1720     {
1721     fftw_tmp[2*i  ]=fft1_desired[i];
1722     fftw_tmp[2*i+1]=0;
1723     t1+=t2;
1724     }
1725   fftback(fft1_size, fft1_n, fftw_tmp, tmp_tab, tmp_permute, FALSE);
1726   init_fft(0,refpul_n, refpul_size, tmp_tab, tmp_permute);
1727   for(i=0; i<refpul_size; i++)fftw_tmp[2*refpul_size-1-i]=fftw_tmp[2*fft1_size-1-i];
1728   t1=8*PI_L/refpul_size;
1729   t2=t1;
1730   i=0;
1731   while(t2 < PI_L/2)
1732     {
1733     t3=sin(t2);
1734     fftw_tmp[refpul_size-2*i  ]*=t3;
1735     fftw_tmp[refpul_size-2*i+1]*=t3;
1736     fftw_tmp[refpul_size+2*i  ]*=t3;
1737     fftw_tmp[refpul_size+2*i+1]*=t3;
1738     i++;
1739     t2+=t1;
1740     }
1741   fftforward(refpul_size, refpul_n, fftw_tmp, tmp_tab, tmp_permute,FALSE);
1742   for(i=0; i<me01; i++)blanker_refpulse[i]=0;
1743   k=ui.rx_rf_channels*me01;
1744   liminfo_amplitude_factor=1;
1745 // Now we have the desired spectrum in refpul_size points.
1746 // Since fft1_desired is a real function the imaginary part
1747 // is rounding errors only so it is not used.
1748   phrot = PI_L/2;
1749   t6=PI_L/MAX_REFPULSES;
1750   for(k=0; k<MAX_REFPULSES; k++)
1751     {
1752     t5=phrot;
1753     for(i=0; i<refpul_size; i++)
1754       {
1755       buf3[2*i  ]=fftw_tmp[2*i]*cos(t5);
1756       buf3[2*i+1]=fftw_tmp[2*i]*sin(t5);
1757       t5-=phrot/(refpul_size/2);
1758       }
1759     fftback(refpul_size, refpul_n, buf3, tmp_tab, tmp_permute, FALSE);
1760 // move the pulse from location 0 to the midpoint refpul_size/2
1761     r1=buf3[0];
1762     r2=buf3[1];
1763     for(i=0; i<refpul_size; i++)
1764       {
1765       t1=buf3[i];
1766       buf3[i]=buf3[i+refpul_size];
1767       buf3[i+refpul_size]=t1;
1768       }
1769     t1=r1*r1+r2*r2;
1770     r1/=t1;
1771     r2/=t1;
1772     m=2*k*refpul_size;
1773     for(i=0; i<refpul_size; i++)
1774       {
1775       t1=buf3[2*i  ];
1776       t2=buf3[2*i+1];
1777       blanker_refpulse[m+2*i  ]=t1*r1+t2*r2;
1778       blanker_refpulse[m+2*i+1]=t2*r1-t1*r2;
1779       }
1780     phrot-=t6;
1781     }
1782 // ********************************
1783 // In case the passband is not symmetric the phase of a pulse
1784 // will vary linearly with time.
1785 // Find out by how much.
1786 // Produce a phase function which we can use to transform
1787 // pulses for the phase to become constant.
1788 // ********************************
1789   blanker_phaserot=0;
1790   t2=0;
1791   for(i=0; i<fft1_size; i++)
1792     {
1793     blanker_phaserot+=i*pow(fft1_desired[i],2.);
1794     t2+=pow(fft1_desired[i],2.);
1795     }
1796   blanker_phaserot*=-2*PI_L/(t2*fft1_size);
1797   for(i=0; i<refpul_size/2; i++)
1798     {
1799     t1=i*blanker_phaserot;
1800     blanker_phasefunc[refpul_size+2*i]=cos(t1);
1801     blanker_phasefunc[refpul_size+2*i+1]=sin(t1);
1802     blanker_phasefunc[refpul_size-2*i]=cos(t1);
1803     blanker_phasefunc[refpul_size-2*i+1]=-sin(t1);
1804     }
1805   t1=0.5*i*refpul_size*blanker_phaserot;
1806   blanker_phasefunc[0]=cos(t1);
1807   blanker_phasefunc[1]=sin(t1);
1808 // ********************************
1809 // The blanker routine will use the known impulse response to
1810 // subtract a standard pulse that is taken from the
1811 // selection of standard pulses in blanker_refpulse.
1812 // This way oscillations on both sides of a pulse will be removed
1813 // without much loss of data.
1814 // To decide which standard pulse to use the blanker
1815 // routine first transforms the phase in the region of
1816 // the peak by use of blanker_phasefunc
1817 // It then uses the 3 strongest points to evaluate the peak
1818 // position with decimals.
1819 // Do the same here using the standard pulses and make a table
1820 // that can be used by the blanker routine to find the optimum
1821 // standard pulse.
1822 // ********************************
1823   for(i=0; i<MAX_REFPULSES; i++)blanker_pulindex[i]=-1;
1824   for(k=0; k<MAX_REFPULSES; k++)
1825     {
1826     m=2*k*refpul_size;
1827     j=0;
1828     for(i=refpul_size/2-1; i<=refpul_size/2+1; i++)
1829       {
1830       t1=blanker_refpulse[m+2*i  ];
1831       t2=blanker_refpulse[m+2*i+1];
1832       t3=blanker_phasefunc[2*i  ];
1833       t4=blanker_phasefunc[2*i+1];
1834       buf3[2*j  ]=t1*t3+t2*t4;
1835       j++;
1836       }
1837 // Fit a parabola to the max point and it's nearest neighbours.
1838 // As input we have 3 data points y(x)
1839 // Find parameters a,b and c to place these points on the curve:
1840 //  y(x)=a+b*(x-c)**2=a+b*x**2-2*x*b*c+b*c**2
1841 // The equations to solve are:
1842 // y(-1)=a + b + 2*b*c + b*c**2
1843 // y( 0)=a     +         b*c**2
1844 // y( 1)=a + b - 2*b*c + b*c**2
1845 //  b has to be negative (for a positive peak)
1846 //  abs(c) has to be below 0.5 since y(0)is the largest value.
1847 //  t4=y(-1)-y(1)=4*b*c
1848 //  t3=2*(y(-1)+y(1)-2*y(0))=4*b
1849 //  t4/t3=c=peak offset
1850     t4=buf3[0]-buf3[4];
1851     t3=2*(buf3[0]+buf3[4]-2*buf3[2]);
1852     t4/=t3;
1853     if(t4<0)
1854       {
1855       t4=-sqrt(0.5)*sqrt(-t4);
1856       }
1857     else
1858       {
1859       t4=sqrt(0.5)*sqrt(t4);
1860       }
1861     j=MAX_REFPULSES*(t4+0.5)+0.5;
1862     if(j<0)j=0;
1863     if(j>=MAX_REFPULSES)j=MAX_REFPULSES-1;
1864     blanker_pulindex[j]=k;
1865     }
1866   i=0;
1867 mkindex:;
1868   while(blanker_pulindex[i] != -1 && i<MAX_REFPULSES)i++;
1869   if(i==0)
1870     {
1871     while(blanker_pulindex[i] == -1)
1872       {
1873       blanker_pulindex[i]=0;
1874       i++;
1875       }
1876     goto mkindex;
1877     }
1878   if(i<MAX_REFPULSES)
1879     {
1880     j=i;
1881     while(blanker_pulindex[j] == -1 && j<MAX_REFPULSES)j++;
1882     if(j>=MAX_REFPULSES)
1883       {
1884       while(i<MAX_REFPULSES)
1885         {
1886         blanker_pulindex[i] = MAX_REFPULSES-1;
1887         i++;
1888         }
1889       }
1890     else
1891       {
1892       j--;
1893       while(i-j<2)
1894         {
1895         blanker_pulindex[i] = blanker_pulindex[i-1];
1896         blanker_pulindex[j] = blanker_pulindex[j+1];
1897         i++;
1898         j--;
1899         }
1900       i--;
1901       goto mkindex;
1902       }
1903     }
1904   blnfit_range=bln[largest_blnfit].size/2+blanker_pulsewidth;
1905   blnclear_range=blnfit_range/4;
1906   if(blnclear_range < 3*blanker_pulsewidth)blnclear_range=3*blanker_pulsewidth;
1907   DEB"blanker_pulsewidth %d range %d\n", blanker_pulsewidth, blnclear_range);
1908   }
1909 else
1910   {
1911   i=memalloc(&blanker_handle,"blanker");
1912   if(i == 0)
1913     {
1914     lirerr(1061);
1915     return;
1916     }
1917   blnclear_range=32;
1918   blnfit_range=48;
1919   largest_blnfit=0;
1920   blanker_pulsewidth=0;
1921   refpul_n=0;
1922   refpul_size=0;
1923   }
1924 t1=screen_height/(2*(1+4*ui.rx_rf_channels));
1925 for(i=0; i<16; i++)
1926   {
1927   timf2_y0[i]=screen_height-(i+1)*t1;
1928   timf2_ymax[i]=timf2_y0[i]+t1;
1929   timf2_ymin[i]=timf2_y0[i]-t1;
1930   if(timf2_ymax[i]>=screen_height)timf2_ymax[i]=screen_height-1;
1931   }
1932 k=me04/sizeof(short int);
1933 for(i=0; i<k; i++)timf2pix[i]=timf2_y0[0];
1934 timf2_show_pointer=-1;
1935 timf2_display_counter=0;
1936 memcheck(22,blankermem,&blanker_handle);
1937 }
1938 
free_buffers(void)1939 void free_buffers(void)
1940 {
1941 if(!kill_all_flag)
1942   {
1943   if(fft1_handle != NULL)memcheck(99,fft1mem,&fft1_handle);
1944   if(baseband_handle != NULL)memcheck(99,basebmem,&baseband_handle);
1945   if(afc_handle != NULL)memcheck(99,afcmem,&afc_handle);
1946   if(fft3_handle != NULL)memcheck(99,fft3mem,&fft3_handle);
1947   if(hires_handle != NULL)memcheck(99,hiresmem,&hires_handle);
1948   }
1949 if(dmp != NULL)fflush(dmp);
1950 if(diskwrite_flag == 1)
1951   {
1952   fclose(save_wr_file);
1953   save_wr_file=NULL;
1954   lir_sync();
1955   diskwrite_flag = 0;
1956   }
1957 fft1_handle=chk_free(fft1_handle);
1958 wg_waterf=chk_free(wg_waterf);
1959 fft3_handle=chk_free(fft3_handle);
1960 hires_handle=chk_free(hires_handle);
1961 blanker_handle=chk_free(blanker_handle);
1962 afc_handle=chk_free(afc_handle);
1963 baseband_handle=chk_free(baseband_handle);
1964 dx=chk_free(dx);
1965 }
1966 
1967