#include #include "globdef.h" #include "uidef.h" #include "fft1def.h" #include "fft2def.h" #include "fft3def.h" #include "screendef.h" #include "seldef.h" #include "blnkdef.h" #include "sigdef.h" #include "sdrdef.h" #include "hwaredef.h" #define TIMF3_OSCILLOSCOPE_RATE 2 void fft1_block_timing(void) { fft1_interleave_ratio=(float)(fft1_interleave_points)/fft1_size; fft1_new_points=fft1_size-fft1_interleave_points; timf1_sampling_speed=ui.rx_ad_speed; if( (ui.rx_input_mode&IQ_DATA) == 0) { timf1_sampling_speed*=0.5; } fft1_blocktime=(float)(fft1_new_points)/timf1_sampling_speed; fft1_rate=1/fft1_blocktime; if(fft1_rate==0)fft1_rate=1; } void get_wideband_sizes(void) { float t1; int i, j, m, k, bwfac; if(fft1_handle != NULL) { lirerr(1002); return; } fft1mode=(ui.rx_input_mode&(TWO_CHANNELS+IQ_DATA))/2; // Before doing anything else, set output format information rx_daout_bytes=1+(genparm[OUTPUT_MODE]&1); //bit 0 rx_daout_channels=1+((genparm[OUTPUT_MODE]>>1)&1); //bit 1 if(rx_daout_channels < ui.rx_min_da_channels) { rx_daout_channels = ui.rx_min_da_channels; } // Tell assembly routines how many channels we have (so we make no // mistake when changing struct ui. rx_channels=ui.rx_rf_channels; twice_rxchan=2*ui.rx_rf_channels; // ********************************************************************* //First find size of first fft. //In case a window was selected we need more points for the bandwidth. //Make fft1_interleave_ratio the distance between the points where the //window function is 0.5. //Assume resolution is reduced by this factor. if(genparm[FIRST_FFT_SINPOW] != 0) { t1=pow(0.5,1.0/genparm[FIRST_FFT_SINPOW]); fft1_interleave_ratio=2*asin(t1)/PI_L; } else { fft1_interleave_ratio=0; } if( (ui.network_flag & NET_RXIN_FFT1) == 0) { if(genparm[FIRST_FFT_BANDWIDTH]==0) { bwfac=65536; } else { bwfac=(0.5*ui.rx_ad_speed)/ ((1-fft1_interleave_ratio)*genparm[FIRST_FFT_BANDWIDTH]); } j=bwfac; if( (ui.rx_input_mode&IQ_DATA) != 0)j*=2; //j is the number of points we need for the whole transform to get the //desired bandwidth. //Make j a power of two. fft1_n=1; i=j; while(j != 0) { j/=2; fft1_n++; } // Never make the size below n=7 (=128) // Note that i becomes small so we arrive at fft1_n=7 if(fft1_n < 8)fft1_n=8; fft1_size=1< 1.5) { reduce_fft1_size:; fft1_size/=2; fft1_n--; } } // Each channel output is 2*float (re, im) fft1_block=twice_rxchan*fft1_size; if(rx_mode == MODE_TUNE) { fft1_costab_size=fft1_size; fft1_permute_size=fft1_size; fft1_window_size=fft1_size; } else { fft1_costab_size=fft1_size/2; fft1_permute_size=fft1_size; fft1_window_size=fft1_size; if(fft_cntrl[FFT1_CURMODE].permute == 2) { fft1_costab_size*=2; fft1_permute_size*=2; fft1_window_size+=16; } // To save cash we use short int for the unscramble table. // Make sure the unscramble array is not too big. if(fft1_permute_size > 0x10000)goto reduce_fft1_size; if(genparm[FIRST_FFT_SINPOW] == 0)fft1_window_size=0; } fft1_blockbytes=fft1_block*sizeof(float); // Each channel input is 16 bit or 32 bit. bytes_per_fragment=2*ui.rx_ad_channels; if( (ui.rx_input_mode&DWORD_INPUT) != 0) bytes_per_fragment*=2; // Get number of points to overlap transforms so window function does // not drop below 0.5. // In this way all points contribute by approximately the same amount // to the averaged power spectrum. // We also need this to be able to use MMX for the back transform. fft1_interleave_points=1+fft1_interleave_ratio*fft1_size; fft1_interleave_points&=0xfffe; fft1_bandwidth=0.5*ui.rx_ad_speed/((1-fft1_interleave_ratio)*fft1_size); if( (ui.rx_input_mode&IQ_DATA) != 0)fft1_bandwidth*=2; // ******************************************************* // Get the sizes for the second fft and the first mixer // The first frequency mixer shifts the signal in timf1 or timf2 to // the baseband. // Rather tham multiplying with a sin/cos table of the selected frequency // we use the corresponding fourier transforms from which a group of lines // are selected, frequency shifted and back transformed. new_mix1_n:; mix1_n=fft1_n-genparm[MIX1_BANDWIDTH_REDUCTION_N]; if(genparm[SECOND_FFT_ENABLE] == 0) { fft2_size=0; timf2_size=0; // If we get signals from back transformation of fft1 // we use an interleave ratio that makes the interleave points // go even up in mix1_size. if(mix1_n < 3)mix1_n=3; mix1_size=1< 15)goto reduce_fft1_size; // Make the time constant for the blanker noise floor about 1 second. // The first fft outputs data in blocks of fft1_new_points fft1_block_timing(); j=(float)(ui.rx_ad_speed+fft1_new_points/2)/fft1_new_points; if(j<1)j=1; timf2_noise_floor_avgnum=j; blanker_info_update_counter=0; fft1_lowlevel_fraction=.75; j/=8; if(j<1)j=1; blanker_info_update_interval=j; timf2_display_interval=timf2_noise_floor_avgnum/10; if(timf2_display_interval < 2)timf2_display_interval=2; timf2_ovfl=0; timf2_display_counter=0; timf2_display_maxpoint=0; timf2_display_maxval_uint=0; timf2_display_maxval_float=0; if(genparm[SECOND_FFT_SINPOW] != 0) { t1=pow(0.5,1.0/genparm[SECOND_FFT_SINPOW]); fft2_interleave_ratio=2*asin(t1)/PI_L; } else fft2_interleave_ratio=0; j=1<<(genparm[SECOND_FFT_NINC]); fft2_n=fft1_n; fft2_sizeset:; fft2_size=1<0.1)min_delay_time=0.1; ad_read_fragments=min_delay_time*ui.rx_ad_speed; make_power_of_two(&ad_read_fragments); interrupt_rate=(float)(ui.rx_ad_speed)/ad_read_fragments; i=0; switch (os_flag) { case OS_FLAG_LINUX: i=32768; break; case OS_FLAG_WINDOWS: i=4096; if(ui.rx_addev_no > 255)i<<=1; break; case OS_FLAG_X: i=32768; break; default: lirerr(89231); return; } if( (ui.network_flag&NET_RX_INPUT)!=0) { ad_read_fragments=ad_read_bytes/bytes_per_fragment; interrupt_rate=(float)(ui.rx_ad_speed)/ad_read_fragments; } else { if(disksave_flag != 2 && (ui.rx_addev_no == SDR14_DEVICE_CODE || ui.rx_addev_no == SDRIQ_DEVICE_CODE )) { ad_read_bytes=8192; bytes_per_fragment=4; ad_read_fragments=2048; } else { ad_read_bytes=ad_read_fragments*bytes_per_fragment; // Set the interrupt rate high in case we write to the network. // This will spread out the packages in time and make them easier // to pick up on a slow computer. k=50; if( (ui.network_flag & NET_RXOUT_FFT1) != 0) { k=400; } if( (ui.network_flag&(NET_RXOUT_RAW16+NET_RXOUT_RAW18+NET_RXOUT_RAW24))!=0) { k=200; } // Set interrupt rate high if the transmit side is enabled. // This will reduce time jitter on the input from the morse hand key. if(ui.tx_enable != 0)k=400; while( interrupt_rate < k || ad_read_bytes > i) { ad_read_fragments/=2; ad_read_bytes/=2; interrupt_rate*=2; } while(ad_read_bytes < 32) { ad_read_fragments*=2; ad_read_bytes*=2; interrupt_rate/=2; } } } // With the Delta44 we save 18 bit out of the 32 bits we read. // Out of the 24 bits of data the last 6 contain only noise. // Allocate ad_read_bytes even if we use 16 bit format because // the network write may use this scratch area. save_rw_bytes=ad_read_bytes; if((ui.rx_input_mode&DWORD_INPUT) != 0)save_rw_bytes=18*ad_read_bytes/32; ad_bufmargin=ad_read_bytes+fft1_size*bytes_per_fragment; timf1_blockbytes=fft1_new_points*bytes_per_fragment; timf1_usebytes=fft1_size*bytes_per_fragment; fft1_hz_per_point=(float)ui.rx_ad_speed/fft1_size; if( (ui.rx_input_mode&IQ_DATA) == 0) { fft1_hz_per_point/=2; timf1_blockbytes*=2; timf1_usebytes*=2; } if( (ui.rx_input_mode&IQ_DATA) != 0) // In case the oscilloscope for timf3 is enabled we want to // update the screen at about TIMF3_OSCILLOSCOPE_RATE Hz. timf3_osc_interval=twice_rxchan*(int)(timf3_sampling_speed/ TIMF3_OSCILLOSCOPE_RATE); m=1+twice_rxchan; t1=screen_height/(2*m); for(i=0; i<8; i++)timf3_y0[i]=screen_height-(i+1)*t1; // Allow for genparm[MIX1_NO_OF_CHANNELS] signals // during the time for which we have transforms plus // the duration of a transform (with a 5 s margin) if( genparm[SECOND_FFT_ENABLE] == 0) { t1=genparm[FFT1_STORAGE_TIME]+fft1_size/timf1_sampling_speed; } else { t1=genparm[FFT2_STORAGE_TIME]+fft2_size/timf1_sampling_speed; } t1+=5; timf3inc:; timf3_size=t1*timf3_sampling_speed; make_power_of_two(&timf3_size); while(timf3_size < 2*screen_width)timf3_size *= 2; timf3_size*=twice_rxchan; timf3_mask=timf3_size-1; timf3_totsiz=genparm[MIX1_NO_OF_CHANNELS]*timf3_size; if(timf3_totsiz < 32000) { t1*=2; goto timf3inc; } mix1_new_points=mix1_size-mix1_interleave_points; timf3_block=twice_rxchan*mix1_new_points; timf3_pa=0; timf3_px=0; timf3_oscilloscope_limit=timf3_osc_interval+ twice_rxchan*(mix1_new_points+screen_width/2); // *********************************************************** // In case second fft is not enabled we need a buffer that can hold // transforms during the time we average over in the AFC process // in case it is enabled. max_fft1n=8; if(genparm[SECOND_FFT_ENABLE] == 0) { // Keep fft1 transforms for genparm[FFT1_STORAGE_TIME] seconds. max_fft1n=genparm[FFT1_STORAGE_TIME]/fft1_blocktime; make_power_of_two(&max_fft1n); } // Always allocate at least 8 buffers. // We may average over 5 buffers and use 2 for raw data processing. if(max_fft1n < 8)max_fft1n=8; fft1_bytes=max_fft1n*fft1_size; if(fft1_bytes < 8*ad_read_bytes)fft1_bytes=ad_read_bytes*8; max_fft1n=fft1_bytes/fft1_size; fft1n_mask=max_fft1n-1; fft1_bytes*=twice_rxchan; fft1_mask=fft1_bytes-1; fft1_bytes*=sizeof(float); // ****************************************************** // We store fft1 power spectra in memory for fast calculation of averages. // Check wide_graph.c for details. max_fft1_sumsq=(1.+genparm[FFT1_STORAGE_TIME])/fft1_blocktime; // We may group averages up to 5 to save time and space if avg time is long max_fft1_sumsq/=5; k=0; while(max_fft1_sumsq != 0) { max_fft1_sumsq/=2; k++; } max_fft1_sumsq=1< 2000000)timf1_bytes*=2; if(fft2_size > 8000000)timf1_bytes*=2; } make_power_of_two(&timf1_bytes); if(rx_mode== MODE_TUNE)timf1_bytes=2*fft1_bytes; timf1_bytemask=timf1_bytes-1; timf1p_pa=ad_read_bytes; timf1p_px=0; fft1_pa=fft1_block; fft1_na=1; fft1_pb=0; fft1net_pa=0; fft1net_px=0; fft1_px=0; fft1_nm=0; fft1_nb=0; fft1_nc=0; fft1_nx=0; // In case we use approximate conversion from real to complex data // we have to allocate memory and prepare for the assembly routines // in getiq.s // Set a value in case we run setup first fft1_sumsq_recalc=fft1_size/2; // To save time i.e. when oversampling we only compute spectrum between // the points actually used. // Set up values (full spectrum) for use in test modes. wg.first_xpoint=0; wg_last_point=fft1_size-1; fft1_tmp_bytes=fft1_blockbytes; if(genparm[SECOND_FFT_ENABLE] != 0 && fft_cntrl[FFT1_BCKCURMODE].mmx == 0) { fft1_tmp_bytes*=2; } if(fft1_tmp_bytes < ad_read_bytes)fft1_tmp_bytes=ad_read_bytes; // If second fft is enabled, we will calculate the noise floor // in liminfo_groups segments of the entire spectrum. // Start by assuming 500Hz is a reasonable bandwidth to get the // noise floor in. mix1_points_per_hz=1.0/fft1_hz_per_point; if(genparm[SECOND_FFT_ENABLE] != 0) { fftx_size=fft2_size; max_fftxn=max_fft2n; liminfo_groups=500./fft1_hz_per_point; make_power_of_two(&liminfo_groups); if(liminfo_groups<16)liminfo_groups=16; liminfo_group_points=fft1_size/liminfo_groups; fft2_att_limit=fft2_n-1-genparm[SECOND_FFT_ATT_N]; fft2_to_fft1_ratio=fft2_size/fft1_size; mix1_points_per_hz*=fft2_to_fft1_ratio; } else { fftx_size=fft1_size; max_fftxn=max_fft1n; liminfo_groups=0; } if(genparm[AFC_ENABLE]==0) genparm[MAX_NO_OF_SPURS] = 0; if(genparm[MAX_NO_OF_SPURS] != 0) { if(fft1_tmp_bytes < 8*max_fftxn)fft1_tmp_bytes = 8*max_fftxn; } while(fft1_tmp_bytes < screen_width*(int)(sizeof(float))) fft1_tmp_bytes*=2; fftn_tmp_bytes=fft1_tmp_bytes; if(2*ui.rx_rf_channels*mix1_size*sizeof(float) > (unsigned)(fftn_tmp_bytes)) { fftn_tmp_bytes=2*ui.rx_rf_channels*mix1_size*sizeof(float); } if(fft1_bytes < fft1_tmp_bytes)fft1_bytes=fft1_tmp_bytes; if(rx_mode == MODE_TXTEST) { if(mix1_size*fft1_hz_per_point > 5300) { genparm[MIX1_BANDWIDTH_REDUCTION_N]++; goto new_mix1_n; } if(mix1_size*fft1_hz_per_point < 2550) { genparm[MIX1_BANDWIDTH_REDUCTION_N]--; goto new_mix1_n; } } // Set the output block size to match the delay time min_delay_time. // under the assumption that we write 2 bytes for each sample. rx_daout_block=2*min_delay_time*genparm[DA_OUTPUT_SPEED]; make_power_of_two(&rx_daout_block); // make the minimum block 32 bytes in accordance with the minimum // fragment size of OSS (frag=4) if(rx_daout_block < 32)rx_daout_block=32; if(os_flag == OS_FLAG_WINDOWS && min_delay_time < 0.02)rx_daout_block*=4; rx_output_blockrate=genparm[DA_OUTPUT_SPEED]/rx_daout_block; daout_restart_counter=0; rxinput_posttime=0; } void get_buffers(int filldat) { int i,j,k; int split_size, afcbuf_size; float t1; int *inttab; short int ishort; afcbuf_size=0; // *************************************************************** // The memory allocation is essential to program speed. // Some time critical loops use several arrays. Place them next // to each other in memory space so cash works well (?). init_memalloc(fft1mem, MAX_FFT1_ARRAYS); mem( 2,&timf1_char,timf1_bytes,0); mem( 3,&fft1_window,fft1_window_size*sizeof(float),0); mem( 4,&fft1tab,fft1_costab_size*sizeof(COSIN_TABLE),16*sizeof(float)); mem( 5,&fft1_tmp,fft1_tmp_bytes,8*sizeof(float)); mem( 551,&fftw_tmp,2*fft1_tmp_bytes,8*sizeof(float)); mem( 552,&fftn_tmp,fftn_tmp_bytes,8*sizeof(float)); mem( 553,&rawsave_tmp,ad_read_bytes,0); mem( 6,&fft1_permute,fft1_permute_size*sizeof(short int),8*sizeof(int)); mem( 7,&fft1_filtercorr,fft1_blockbytes,8*sizeof(float)); mem( 8,&fft1_char,fft1_bytes,0); mem( 9,&wg_waterf_sum,fft1_size*sizeof(float),0); mem(10,&fft1_sumsq,fft1_sumsq_bufsize*sizeof(float),0); if(fft1afc_flag != 0) { // AFC based on fft1 !! if(ui.rx_rf_channels == 1) { mem(1011,&fft1_power,fft1_size*max_fft1n*sizeof(float),0); mem(1012,&fft1_powersum,fft1_size*sizeof(float),0); } else { mem(2011,&fft1_xypower,fft1_size*max_fft1n*sizeof(TWOCHAN_POWER),0); mem(2012,&fft1_xysum,fft1_size*sizeof(TWOCHAN_POWER),0); } } mem(13,&fft1_slowsum,fft1_size*sizeof(float),0); if( (ui.rx_input_mode&IQ_DATA) != 0) { mem(14,&fft1_foldcorr,twice_rxchan*fft1_size*sizeof(float),0); } mem(15,&fft1_spectrum,screen_width*sizeof(short int),0); mem(16,&fft1_desired,fft1_size*sizeof(float),0); mem(17,&wg_waterf_yfac,fft1_size*sizeof(float),0); mem(18,&mix1_permute,mix1_size*sizeof(short int),0); mem(19,&mix1_table,mix1_size*sizeof(COSIN_TABLE)/2,0); mem(20,&timf3_float,2*timf3_totsiz*sizeof(float),0); mem(21,&timf3_graph,ui.rx_rf_channels*screen_width*sizeof(short int),0); mem(22,&liminfo_wait,fft1_size*sizeof(char),0); mem(23,&liminfo,2*fft1_size*sizeof(float),0); mem(24,&liminfo_group_min,liminfo_groups*sizeof(float),0); if(genparm[SECOND_FFT_ENABLE] != 0) { split_size=4*ui.rx_rf_channels*fft1_size; swfloat=fft_cntrl[FFT1_BCKCURMODE].mmx == 0 && fft_cntrl[FFT2_CURMODE].mmx == 0; if(swfloat) { mem(25,&fft1_split_float, split_size*sizeof(float),0); } else { mem(25,&fft1_split_shi, split_size*sizeof(short int),4*sizeof(int)); } } mem(26,&mix1_fqwin,(mix1_size/2+16)*sizeof(float),0); mem(27,&mix1_cos2win,mix1_new_points*sizeof(float),0); mem(28,&mix1_sin2win,mix1_new_points*sizeof(float),0); if(genparm[SECOND_FFT_ENABLE] == 0) { if( genparm[FIRST_FFT_SINPOW]!=0 && (genparm[FIRST_FFT_SINPOW]!= 2 || rx_mode == MODE_TXTEST)) { mem(1029,&mix1_win,(mix1_size/2+16)*sizeof(float),0); } } else { if( genparm[FIRST_FFT_SINPOW]!= 2) { if( genparm[FIRST_FFT_SINPOW]!=0 && genparm[FIRST_FFT_SINPOW]!= 2) { if( fft_cntrl[FFT1_BCKCURMODE].mmx != 0) { mem(2029,&fft1_inverted_mmxwin,2*(16+fft1_size/2)*4*sizeof(short int),8); } else { mem(3029,&fft1_inverted_window,(16+fft1_size/2)*sizeof(float),0); } } } mem(30,&fft1_backbuffer,4*4*ui.rx_rf_channels*fft1_size*sizeof(short int),0); mem(31,&fft1_back_scramble,fft1_size*sizeof(short int),0); mem(3925,&hg_fft2_pwrsum,2*screen_width*sizeof(float),0); if(ui.rx_rf_channels == 2) { mem(3926,&hg_fft2_pwr,max_fft2n*2*screen_width*sizeof(float),0); } if(swfloat) { mem(32,&timf2_float,4*ui.rx_rf_channels*timf2_size*sizeof(float),0); mem(33,&timf2_pwr_float,timf2_size*sizeof(float),0); } else { mem(32,&timf2_shi,4*ui.rx_rf_channels*timf2_size*sizeof(short int),0); mem(33,&timf2_pwr_int,(timf2_size+8)*sizeof(int),4); } if( fft_cntrl[FFT1_CURMODE].permute == 2) { mem(34,&fft1_backtab,fft1_size*sizeof(COSIN_TABLE)/2,0); } if( fft_cntrl[FFT1_BCKCURMODE].mmx != 0) { mem(35,&fft1_mmxcosin, fft1_size*sizeof(MMX_COSIN_TABLE)/2, 8*sizeof(float)); } if(ui.rx_rf_channels == 1) { mem(1039,&fft2_power_float,fft2_size*max_fft2n*sizeof(float),0); mem(1040,&fft2_powersum_float,fft2_size*sizeof(float),0); } else { mem(2039,&fft2_xypower,fft2_size*max_fft2n*sizeof(TWOCHAN_POWER),0); mem(2040,&fft2_xysum,fft2_size*sizeof(TWOCHAN_POWER),0); } if(fft_cntrl[FFT2_CURMODE].mmx == 0) { mem(1036,&fft2_float,max_fft2n*2*fft2_size* ui.rx_rf_channels*sizeof(float),0); mem(1037,&fft2_permute,fft2_size*sizeof(short int),0); mem(1038,&fft2_tab,fft2_size*sizeof(COSIN_TABLE)/2,0); if(genparm[SECOND_FFT_SINPOW] != 0) { mem(1041,&fft2_window,fft2_size*sizeof(float),0); } } else { mem(3038,&fft2_short_int,max_fft2n*2*fft2_size* ui.rx_rf_channels*sizeof(short int),0); mem(3039,&fft2_bigpermute,fft2_size*sizeof(int),16*sizeof(int)); mem(3040,&fft2_mmxcosin, fft2_size*sizeof(MMX_COSIN_TABLE)/2, 16*sizeof(float)); mem(3041,&fft2_mmxwin,fft2_size*sizeof(short int),0); } if( genparm[SECOND_FFT_SINPOW]!= 0 && genparm[SECOND_FFT_SINPOW]!= 2) { mem(3042,&mix1_win,(mix1_size/2+16)*sizeof(float),0); } } if(genparm[SECOND_FFT_ENABLE] == 0) { afcbuf_size=max_fft1n*MAX_MIX1; } else { afcbuf_size=max_fft2n*MAX_MIX1; } if(genparm[AFC_ENABLE] != 0) { mem(43,&mix1_fq_mid,afcbuf_size*sizeof(float),0); mem(44,&mix1_fq_start,afcbuf_size*sizeof(float),0); mem(45,&mix1_fq_curv,afcbuf_size*sizeof(float),0); mem(46,&mix1_fq_slope,afcbuf_size*sizeof(float),0); mem(47,&mix1_eval_avgn,afcbuf_size*sizeof(short int),0); mem(48,&mix1_eval_fq,afcbuf_size*sizeof(float),0); mem(49,&mix1_eval_sigpwr,afcbuf_size*sizeof(float),0); mem(50,&mix1_eval_noise,afcbuf_size*sizeof(float),0); mem(51,&mix1_fitted_fq,afcbuf_size*sizeof(float),0); } // Allocate memory for automatic spur cancellation if(genparm[MAX_NO_OF_SPURS] != 0) { if(genparm[MAX_NO_OF_SPURS] > fftx_size/SPUR_WIDTH) { genparm[MAX_NO_OF_SPURS] = fftx_size/SPUR_WIDTH; } spur_block=SPUR_WIDTH*max_fftxn*twice_rxchan; if(genparm[SECOND_FFT_ENABLE] !=0 && fft_cntrl[FFT2_CURMODE].mmx != 0) { mem(1052,&spur_table_mmx, genparm[MAX_NO_OF_SPURS]*spur_block*sizeof(short int),0); } else { mem(2052,&spur_table, genparm[MAX_NO_OF_SPURS]*spur_block*sizeof(float),0); } mem(53,&spur_location, genparm[MAX_NO_OF_SPURS]*sizeof(int),0); mem(54,&spur_flag, genparm[MAX_NO_OF_SPURS]*sizeof(int),0); mem(55,&spur_power, SPUR_WIDTH*sizeof(float),0); mem(56,&spur_d0pha, genparm[MAX_NO_OF_SPURS]*sizeof(float),0); mem(57,&spur_d1pha, genparm[MAX_NO_OF_SPURS]*sizeof(float),0); mem(58,&spur_d2pha, genparm[MAX_NO_OF_SPURS]*sizeof(float),0); mem(59,&spur_ampl, genparm[MAX_NO_OF_SPURS]*sizeof(float),0); mem(60,&spur_noise, genparm[MAX_NO_OF_SPURS]*sizeof(float),0); mem(61,&spur_avgd2, genparm[MAX_NO_OF_SPURS]*sizeof(float),0); mem(62,&spur_pol,genparm[MAX_NO_OF_SPURS]*3*sizeof(float),0); mem(63,&spur_spectra,NO_OF_SPUR_SPECTRA*SPUR_SIZE*sizeof(float),0); mem(64,&spur_freq, genparm[MAX_NO_OF_SPURS]*sizeof(int),0); mem(65,&spur_ind, genparm[MAX_NO_OF_SPURS]*max_fftxn*sizeof(int),0); mem(66,&spur_signal, max_fftxn*twice_rxchan* genparm[MAX_NO_OF_SPURS]*sizeof(float),0); spur_speknum=0.1*genparm[SPUR_TIMECONSTANT]/fftx_blocktime; if(spur_speknum < 3)spur_speknum=3; if(spur_speknum > max_fftxn-2)spur_speknum=max_fftxn-2; if(spur_speknum < 3) { lir_status=LIR_SPURERR; return; } sp_numsub=spur_speknum-1; sp_avgnum=spur_speknum/3; if(sp_avgnum > 10)sp_avgnum=10; spur_max_d2=PI_L*spur_freq_factor/spur_speknum; // The spur signal is coherently averaged over spur_speknum transforms // while noise is non-coherent rms value. // Set the minimum S/N for at least 3dB in the narrower bandwidth for // the noise we would get if the noise vas evaluated at the // same bandwidth as the signal. spur_minston=1/sqrt(0.5*(float)(spur_speknum)); // Make spur_weiold/new These parameters prevent the second // derivative of the phase (frequency drift) to change rapidly. t1=0.5*spur_speknum; spur_weiold=t1/(1+t1); spur_weinew=1/(1+t1); // To fit a straight line to spur phase we need sum of squares. t1=-0.5*sp_numsub; spur_linefit=0; for(i=0; i0.1*t1) { i--; mix1_crossover_points++; } if(mix1_crossover_points > mix1_new_points/2) mix1_crossover_points=mix1_new_points/2; if(mix1_crossover_points > mix1_interleave_points/2) mix1_crossover_points=mix1_interleave_points/2; t1=0.25*PI_L/mix1_crossover_points; j=(mix1_size-mix1_new_points)/2; k=j; for(i=0; i0.033*buf2[0])blanker_pulsewidth++; // ******************************************************** // We now know refpul_size, the total length of the pulse response // for the current hardware and calibration. // Allocate memory for the clever (linear) noise blanker. // ******************************************************** // ******************************************************** // ******************************************************** // ******************************************************** mem(1,&blanker_refpulse,me01*sizeof(float),0); mem(2,&blanker_phasefunc,2*refpul_size*sizeof(float),0); mem(3,&blanker_pulindex,MAX_REFPULSES*sizeof(int),0); mem(4,&blanker_input,twice_rxchan*refpul_size*sizeof(float),0); mem(6,&blanker_flag,((ui.rx_rf_channels*timf2_mask/4+16)*sizeof(char)),0); i=memalloc((int*)(&blanker_handle),"blanker"); if(i == 0 || lir_status==LIR_MEMERR) { lirerr(1061); return; } // ************************** // Use fft1_desired to get time domain in fft1_size points. // Reduce to the number of points we actually want. // Produce MAX_REFPULSES standard pulses, all shifted differently in time. // The time shifted pulses are obtained by change of the phase slope. // To shift by one sample point in time, the phase slope has to change // by 2*pi/refpul_size. // Normalise the reference pulses so the amplitude = 1 and the phase = 0 // for the max point // ************************** for(i=0; i=MAX_REFPULSES)j=MAX_REFPULSES-1; blanker_pulindex[j]=k; } i=0; mkindex:; while(blanker_pulindex[i] != -1 && i=MAX_REFPULSES) { while(i=screen_height)timf2_ymax[i]=screen_height-1; } k=me04/sizeof(short int); for(i=0; i