#include #include #include "globdef.h" #include "uidef.h" #include "fft1def.h" #include "fft2def.h" #include "caldef.h" #include "thrdef.h" #define INFOLINE 3 void cal_initscreen(void) { int i; char s[80]; clear_screen(); sprintf(s,"Calibration routine for %s. Press F1 for info.",rxmodes[rx_mode]); for(i=0; i= 0) { wrbuf[0]=fft1_n; wrbuf[1]=fft1_size; wrbuf[7]=siz; } else { wrbuf[0]=fft2_n; wrbuf[1]=fft2_size; wrbuf[7]=0; } for(i=8; i<10; i++)wrbuf[i]=0; fwrite(wrbuf, sizeof(int),10,file); if(siz < 0) { fwrite(cal_fft1_filtercorr, 2*ui.rx_rf_channels*sizeof(float),fft2_size, file); fwrite(cal_fft1_desired,sizeof(float),fft2_size,file); } else { if(siz == 0) { normalise_fft1_filtercorr(cal_tmp); fwrite(cal_tmp, twice_rxchan*sizeof(float),fft1_size, file); fwrite(fft1_desired,sizeof(float),fft1_size,file); } else { fwrite(cal_buf, 2*ui.rx_rf_channels*sizeof(float),siz, file); // Store fft1_desired in siz points in cal_buf2 resize_fft1_desired(fft1_size, fft1_desired, siz, cal_buf2); fwrite(cal_buf2,sizeof(float),siz,file); } } fwrite(wrbuf, sizeof(int),10,file); fclose(file); } void do_cal_interval(void) { int i, j, k, l, m, n, color,wid,first_pulse; int p0, ia, ib, ic, ja, jb; int imode, lim, overflow_flag; int rawbytes; int maxval[MAX_ADCHAN],minval[MAX_ADCHAN]; int old_end; int points, mask; int textend,ysiz,ytop; char s[80]; float *filpwr; float pwr_l, pwr_h; float old_trig_power,trig_power,dc[MAX_ADCHAN],ampmax; float noise_floor; float t1,t2,t3; // Collect 0.5 seconds of raw data. rawbytes=ui.rx_ad_speed*bytes_per_fragment; if(rawbytes > timf1_bytes-3*timf1_blockbytes) rawbytes=timf1_bytes-3*timf1_blockbytes; if(rawbytes < 0.25*ui.rx_ad_speed*bytes_per_fragment) { lirerr(1241); goto calint_error_exit; } points=rawbytes/bytes_per_fragment; make_power_of_two(&points); points >>= 1; rawbytes=points*bytes_per_fragment; filpwr=&fft1_float[points]; old_trig_power=1; old_end=-1; cal_ygain=1; cal_xgain=1; cal_interval=0; imode=ui.rx_input_mode&(DWORD_INPUT+TWO_CHANNELS+IQ_DATA); restart:; cal_signal_level=0; cal_initscreen(); lir_text(3, 1,"Connect pulse generator to all antenna inputs"); lir_text(3, 2,"Press ENTER when OK. (+),(-) for y-scale E,C for x-scale"); lir_text(0,INFOLINE,"DC offset"); lir_text(5,INFOLINE+1,"Min"); lir_text(5,INFOLINE+2,"Max"); lir_text(3,INFOLINE+3,"Level"); lir_refresh_screen(); timf1p_px=timf1p_pa; thread_status_flag[THREAD_CAL_INTERVAL]=THRFLAG_ACTIVE; while(thread_command_flag[THREAD_CAL_INTERVAL] == THRFLAG_ACTIVE) { // Get power as a function of time. // The A/D converters are AC coupled so we remove DC components. for(i=0; itimf1_short_int[k])minval[0]=timf1_short_int[k]; if(maxval[0]timf1_int[k])minval[0]=timf1_int[k]; if(maxval[0]timf1_short_int[k+j])minval[j]=timf1_short_int[k+j]; if(maxval[j]timf1_int[k+j])minval[j]=timf1_int[k+j]; if(maxval[j]timf1_short_int[k+j])minval[j]=timf1_short_int[k+j]; if(maxval[j]timf1_int[k+j])minval[j]=timf1_int[k+j]; if(maxval[j]timf1_short_int[k+j])minval[j]=timf1_short_int[k+j]; if(maxval[j]timf1_int[k+j])minval[j]=timf1_int[k+j]; if(maxval[j]= lim) { overflow_flag=1; lir_text(10+15*j,INFOLINE+3,"OVERFLOW"); t1=1; } else { t1/=lim; sprintf(s," %1.6f%% ",100*t1); lir_text(10+15*j,INFOLINE+3,s); } } cal_signal_level/=lim; // Find the largest power value and point wid to it. trig_power=0; wid=0; for(i=0; i= trig_power/20 || fft1_float[i+1] >= trig_power/20 || fft1_float[i+2] >= trig_power/20 || fft1_float[i+3] >= trig_power/20 ))i++; while( wid>2 && (fft1_float[wid] >= trig_power/20 || fft1_float[wid-1] >= trig_power/20 || fft1_float[wid-2] >= trig_power/20 || fft1_float[wid-3] >= trig_power/20 ))wid--; wid=(i-wid); wid=wid/2+1; // Low pass filter the power function and store in filpwr for(i=wid; i old_trig_power)old_trig_power=trig_power; trig_power=old_trig_power/31.6; // Remember trig_power for the next set of data. old_trig_power/=2; ia=0; i=wid; if(wid < points/16) { // find the position of the first pulse interval_init:; while( i= trig_power/20)i++; if(ja==wid)goto interval_init; jb=i; t1=0; for(k=ja; k t1) { t1=fft1_float[k]; ia=k; } } first_pulse=ia; // Find sucessive pulses and store the intervals in cal_tmp k=0; cal_interval=0; j=0; find_interval:; while( i= trig_power/20)i++; jb=i; t1=0; ib=i; for(k=ja; k t1) { t1=fft1_float[k]; ib=k; } } if(i0) { for(i=0; i0.7*cal_tmp[i]) { t1+=cal_tmp[i]; i++; } i-=(j/4+1); if(i != 0) { t1/=i; k=0; for(i=0; i0.8*t1 && cal_tmp[i]<1.2*t1) { cal_interval+=cal_tmp[i]; k++; } else { if(cal_tmp[i]>1.8*t1 && cal_tmp[i]<2.2*t1) { cal_interval+=cal_tmp[i]; k+=2; } else { if(cal_tmp[i]>2.7*t1 && cal_tmp[i]<3.3*t1) { cal_interval+=cal_tmp[i]; k+=3; } } } } cal_interval/=k; // Get the noise floor. // First locate the smallest power value in the filtered power vs time curve. pwr_l=BIG; pwr_h=0; for(i=wid; ifilpwr[i])pwr_l=filpwr[i]; if(pwr_h 0.1*pwr_h)pwr_l=0.1*pwr_h; // Count the number of points above the noise floor and // get the average value of the points below the noise floor. j=0; get_floor:; t2=0; k=0; j++; if(j < 10) { for(i=wid; i 0.6*(points-2*wid)) { if(pwr_l > 4*t2) { pwr_l=3*t2; goto get_floor; } else { if(pwr_l < 2*t2) { pwr_l/=2; goto get_floor; } } } } else { t2=pwr_h; } noise_floor=pwr_h/t2; // Show one of the pulses. while(first_pulse+7*(screen_width>>3) > points) first_pulse -= cal_interval; while(first_pulse < (screen_width>>3)) first_pulse += cal_interval; if(first_pulse+7*(screen_width>>3) <= points) { ic=first_pulse+7*(screen_width>>3); ia=first_pulse-(screen_width>>3); for(j=0; j<=ui.rx_ad_channels; j++) { m=screen_width*j; n=screen_width*(ui.rx_ad_channels+1); for(i=1; i<=old_end; i++) { lir_line(cal_graph[n+i-1], cal_graph[m+i-1], cal_graph[n+i ], cal_graph[m+i ],0); if(kill_all_flag) goto calint_error_exit; } } textend=(INFOLINE+4)*text_height; ytop=textend+screen_height*0.3; ysiz=screen_height-ytop; n=-1; for(j=ia; j>3)+cal_xgain*(j-first_pulse); if(i>=0 && i0.45)t2=0.45; cal_graph[screen_width+n]=ytop+ysiz*(0.5-t2); m=1; break; // One channel 32 bit case 1: k=(p0+j)&mask; t2=0.4*cal_ygain*timf1_int[k]/ampmax; if(t2 <-0.45)t2=-0.45; if(t2 >0.45)t2=0.45; cal_graph[screen_width+n]=ytop+ysiz*(0.5-t2); m=1; break; // Two channels 16 bit real data case 2: k=(p0+2*j)&mask; for(m=0; m<2; m++) { t2=2*6553.6*cal_ygain*timf1_short_int[k+m]/ampmax; if(t2 <-0.22)t2=-0.22; if(t2 >0.22)t2=0.22; if(m == 1)t2-=0.5; cal_graph[screen_width*(m+1)+n]=ytop+ysiz*(0.25-t2); } m=2; break; // Two channels 32 bit real data case 3: k=(p0+2*j)&mask; for(m=0; m<2; m++) { t2=0.4*cal_ygain*timf1_int[k+m]/ampmax; if(t2 <-0.22)t2=-0.22; if(t2 >0.22)t2=0.22; if(m == 1)t2-=0.5; cal_graph[screen_width*(m+1)+n]=ytop+ysiz*(0.25-t2); } m=2; break; // One channel 16 bit IQ data case 4: k=(p0+2*j)&mask; for(m=0; m<2; m++) { t2=4*6553.6*cal_ygain*timf1_short_int[k+m]/ampmax; if(t2 <-0.45)t2=-0.45; if(t2 >0.45)t2=0.45; cal_graph[screen_width*(m+1)+n]=ytop+ysiz*(0.5-t2); } m=2; break; // One channel 32 bit IQ data case 5: k=(p0+2*j)&mask; for(m=0; m<2; m++) { t2=0.4*cal_ygain*timf1_int[k+m]/ampmax; if(t2 <-0.45)t2=-0.45; if(t2 >0.45)t2=0.45; cal_graph[screen_width*(m+1)+n]=ytop+ysiz*(0.5-t2); } m=2; break; // Two channels 16 bit IQ data case 6: k=(p0+4*j)&mask; t3=4*6553.6*cal_ygain/ampmax; for(m=0; m<4; m++) { t2=t3*timf1_short_int[k+m]; if(t2 <-0.22)t2=-0.22; if(t2 >0.22)t2=0.22; if(m > 1)t2-=0.5; cal_graph[screen_width*(m+1)+n]=ytop+ysiz*(0.25-t2); } m=4; break; // Two channels 32 bit IQ data case 7: k=(p0+4*j)&mask; for(m=0; m<4; m++) { t2=0.4*cal_ygain*timf1_int[k+m]/ampmax; if(t2 <-0.22)t2=-0.22; if(t2 >0.22)t2=0.22; if(m > 1)t2-=0.5; cal_graph[screen_width*(m+1)+n]=ytop+ysiz*(0.25-t2); } m=4; break; default: m=0; } if(n>0) { lir_line(cal_graph[screen_width*(ui.rx_ad_channels+1)+n-1], cal_graph[n-1],i,cal_graph[n],15); if(kill_all_flag) goto calint_error_exit; for(l=0; l