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