#include "globdef.h" #include "uidef.h" #include "fft1def.h" #include "sigdef.h" #include "screendef.h" #include "options.h" // ************************************************************ // ************************************************************ // These defines allow a lot of information to be written to dmp #if DUMPFILE == TRUE #define PR00 0 #define PR01 1 #define PR02 0 #define PR03 0 #define PR04 0 #define PR05 0 #else #define PR00 0 #define PR01 0 #define PR02 0 #define PR03 0 #define PR04 0 #define PR05 0 #endif #define PRT00 if(PR00 != 0)DEB #define PRT01 if(PR01 != 0)DEB #define PRT02 if(PR02 != 0)DEB #define PRT03 if(PR03 != 0)DEB #define PRT04 if(PR04 != 0)DEB #define PRT05 if(PR05 != 0)DEB // ************************************************************ // ************************************************************ #define ZZ 0.000000000000000001 #define MAX_CW_IDEAL_RISE 16 float cw_ideal_rise[MAX_CW_IDEAL_RISE]; void fit_dot(void) { int i,k,m,ss,pp,n1,n2,n3,trials; float t1,t2,t3,r1,r2; float im_1,im_2,im_3; float re_1,re_2,re_3; float p1,p2,p3,old_re,old_im; float midpoint[4],offset[4],ampl[4]; int ref[4],shift[4]; // Compare the current waveform to the waveform of a dot. // Set cg_wave_start to the position giving the best fit. // Set cg_wave_midpoint to the center of the waveform. // Return similarity of waveforms. trials=0; old_re=0; old_im=0; try_fit:; pp=cg_wave_start; ref[trials]=pp; ss=(cg_wave_start+dot_pts)&baseband_mask; re_1=0; re_2=0; re_3=0; im_1=0; im_2=0; im_3=0; p2=0; n2=pp; k=dot_pts/6; if(k<1)k=1; n1=(pp-k+baseband_size)&baseband_mask; n3=(pp+k)&baseband_mask; i=0; while(n2 != ss) { p2+=baseb_totpwr[n2]; re_1+=baseb[2*n1 ]*dot_waveform[2*i ]+ baseb[2*n1+1]*dot_waveform[2*i+1]; im_1+=baseb[2*n1 ]*dot_waveform[2*i+1]- baseb[2*n1+1]*dot_waveform[2*i ]; re_2+=baseb[2*n2 ]*dot_waveform[2*i ]+ baseb[2*n2+1]*dot_waveform[2*i+1]; im_2+=baseb[2*n2 ]*dot_waveform[2*i+1]- baseb[2*n2+1]*dot_waveform[2*i ]; re_3+=baseb[2*n3 ]*dot_waveform[2*i ]+ baseb[2*n3+1]*dot_waveform[2*i+1]; im_3+=baseb[2*n3 ]*dot_waveform[2*i+1]- baseb[2*n3+1]*dot_waveform[2*i ]; i++; n1=(n1+1)&baseband_mask; n2=(n2+1)&baseband_mask; n3=(n3+1)&baseband_mask; } p1=p2; p3=p2; n1=(pp-k+baseband_size)&baseband_mask; n3=(pp+k)&baseband_mask; while(n1 != pp) { p1+=baseb_totpwr[n1]; n1=(n1+1)&baseband_mask; } while(n1 != n3) { p3-=baseb_totpwr[n1]; n1=(n1+1)&baseband_mask; } n1=(ss-k+baseband_size)&baseband_mask; n3=(ss+k)&baseband_mask; while(n1 != ss) { p1-=baseb_totpwr[n1]; n1=(n1+1)&baseband_mask; } while(n1 != n3) { p3+=baseb_totpwr[n1]; n1=(n1+1)&baseband_mask; } t1=sqrt((re_1*re_1+im_1*im_1)/(p1*dot_sumsq)); t2=sqrt((re_2*re_2+im_2*im_2)/(p2*dot_sumsq)); t3=sqrt((re_3*re_3+im_3*im_3)/(p3*dot_sumsq)); r2=2*(t1+t3-2*t2); r1=(t1-t3); // t1,t2 and t3 reflect how well the current waveform fits to the reference // when shifted by -k,0 and +k. // These points should have a maximum close to t2. if(r2 >= 0) { // If the three points are on a straight line or a concave one // we have a bad fit. Skip by returning zero. goto skip; } if( (t1<0.33 && t2<0.33 && t3<0.33) ) { // If all points are really small, return zero to indicate an error. skip:; cg_wave_fit=0; return; } // Fit a parabola to the 3 points and get shift and best fit. m=0; r1=r1/r2; if(fabs(r1) > 2)r1=2*r1/fabs(r1); r1*=k; offset[trials]=r1; ampl[trials]=t2-r2*r1*r1*0.25; cg_wave_midpoint=cg_wave_start+0.5*dot_pts+r1; if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size; midpoint[trials]=cg_wave_midpoint; if(trials >= 3)goto skip; m=(fabs(r1)+0.5)*r1/fabs(r1); cg_wave_start=(cg_wave_start+m)&baseband_mask; shift[trials]=m; if(m == 0)goto pos_ok; if(trials != 0) { if(m*shift[trials-1] <0) { m=(m-shift[trials-1])/2; cg_wave_start=(cg_wave_start+m)&baseband_mask; shift[trials]=m; if(abs(m) <= 1)goto pos_ok; } for(i=0; i<=trials; i++) { if(ref[i] == cg_wave_start)goto pos_ok; } } trials++; old_re=re_2; old_im=im_2; goto try_fit; pos_ok:; cg_wave_re=re_2; cg_wave_im=im_2; if(trials != 0) { if(shift[trials]*shift[trials-1] < 0) { if(fabs(offset[trials]) > 2*fabs(offset[trials-1]) ) { if(fabs(offset[trials]) > 0.5*fabs(offset[trials-1]) ) { // The previous fit was much better. Use it !! cg_wave_re=old_re; cg_wave_im=old_im; trials--; } else { // We have two results, one from each side. // None is much better than the other. // Use the weighted average. t1=midpoint[trials]; t2=midpoint[trials-1]; if(t1-t2 > (baseband_size >>1))t1=t1-baseband_size; if(t1-t2 < -(baseband_size >>1))t1=t1+baseband_size; p1=offset[trials]; p2=offset[trials-1]; p1=1/(0.2+fabs(p1)); p2=1/(0.2+fabs(p2)); p1=p1*p1; p2=p2*p2; t1=(p1*t1+p2*t2)/(p1+p2); if(t1 >= baseband_size)t1-=baseband_size; if(t1<0)t1+=baseband_size; midpoint[trials]=t1; t1=ampl[trials]; t2=ampl[trials-1]; ampl[trials]=(p1*t1+p2*t2)/(p1+p2); cg_wave_re=(p1*re_2+p2*old_re)/(p1+p2); cg_wave_im=(p1*im_2+p2*old_im)/(p1+p2); } } } } cg_wave_midpoint=midpoint[trials]; cg_wave_fit=ampl[trials]; cg_wave_re/=dot_sumsq; cg_wave_im/=dot_sumsq; } void fit_dash(void) { int i,k,m,ss,pp,n1,n2,n3,trials; float t1,t2,t3,r1,r2; float im_1,im_2,im_3; float re_1,re_2,re_3; float p1,p2,p3,old_re,old_im; float midpoint[4],offset[4],ampl[4]; int ref[4],shift[4]; // Compare the current waveform to the waveform of a dash. // Set cg_wave_start to the position giving the best fit. // Set cg_wave_midpoint to the center of the waveform. // Return similarity of waveforms. trials=0; old_re=0; old_im=0; try_fit:; pp=cg_wave_start; ref[trials]=pp; ss=(cg_wave_start+dash_pts)&baseband_mask; re_1=0; re_2=0; re_3=0; im_1=0; im_2=0; im_3=0; p2=0; n2=pp; k=dot_pts/6; if(k<1)k=1; n1=(pp-k+baseband_size)&baseband_mask; n3=(pp+k)&baseband_mask; i=0; while(n2 != ss) { p2+=baseb_totpwr[n2]; re_1+=baseb[2*n1 ]*dash_waveform[2*i ]+ baseb[2*n1+1]*dash_waveform[2*i+1]; im_1+=baseb[2*n1 ]*dash_waveform[2*i+1]- baseb[2*n1+1]*dash_waveform[2*i ]; re_2+=baseb[2*n2 ]*dash_waveform[2*i ]+ baseb[2*n2+1]*dash_waveform[2*i+1]; im_2+=baseb[2*n2 ]*dash_waveform[2*i+1]- baseb[2*n2+1]*dash_waveform[2*i ]; re_3+=baseb[2*n3 ]*dash_waveform[2*i ]+ baseb[2*n3+1]*dash_waveform[2*i+1]; im_3+=baseb[2*n3 ]*dash_waveform[2*i+1]- baseb[2*n3+1]*dash_waveform[2*i ]; i++; n1=(n1+1)&baseband_mask; n2=(n2+1)&baseband_mask; n3=(n3+1)&baseband_mask; } p1=p2; p3=p2; n1=(pp-k+baseband_size)&baseband_mask; n3=(pp+k)&baseband_mask; while(n1 != pp) { p1+=baseb_totpwr[n1]; n1=(n1+1)&baseband_mask; } while(n1 != n3) { p3-=baseb_totpwr[n1]; n1=(n1+1)&baseband_mask; } n1=(ss-k+baseband_size)&baseband_mask; n3=(ss+k)&baseband_mask; while(n1 != ss) { p1-=baseb_totpwr[n1]; n1=(n1+1)&baseband_mask; } while(n1 != n3) { p3+=baseb_totpwr[n1]; n1=(n1+1)&baseband_mask; } t1=sqrt((re_1*re_1+im_1*im_1)/(p1*dash_sumsq)); t2=sqrt((re_2*re_2+im_2*im_2)/(p2*dash_sumsq)); t3=sqrt((re_3*re_3+im_3*im_3)/(p3*dash_sumsq)); r2=2*(t1+t3-2*t2); r1=(t1-t3); // t1,t2 and t3 reflect how well the current waveform fits to the reference // when shifted by -k,0 and +k. // These points should have a maximum close to t2. if(r2 >= 0) { // If the three points are on a straight line or a concave one // we have a bad fit. Skip by returning zero. goto skip; } if( (t1<0.33 && t2<0.33 && t3<0.33) ) { // If all points are really small, return zero to indicate an error. skip:; cg_wave_fit=0; return; } // Fit a parabola to the 3 points and get shift and best fit. m=0; r1=r1/r2; if(fabs(r1) > 2)r1=2*r1/fabs(r1); r1*=k; offset[trials]=r1; ampl[trials]=t2-r2*r1*r1*0.25; cg_wave_midpoint=cg_wave_start+0.5*dash_pts+r1; if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size; midpoint[trials]=cg_wave_midpoint; if(trials >= 3)goto skip; m=(fabs(r1)+0.5)*r1/fabs(r1); cg_wave_start=(cg_wave_start+m)&baseband_mask; shift[trials]=m; if(m==0)goto pos_ok; if(trials != 0) { if(m*shift[trials-1] <0) { m=(m-shift[trials-1])/2; cg_wave_start=(cg_wave_start+m)&baseband_mask; shift[trials]=m; if(abs(m) <= 1)goto pos_ok; } for(i=0; i<=trials; i++) { if(ref[i] == cg_wave_start)m/=2; } } trials++; old_re=re_2; old_im=im_2; goto try_fit; pos_ok:; cg_wave_re=re_2; cg_wave_im=im_2; if(trials != 0) { if(shift[trials]*shift[trials-1] < 0) { if(fabs(offset[trials]) > 2*fabs(offset[trials-1]) ) { if(fabs(offset[trials]) > 0.5*fabs(offset[trials-1]) ) { // The previous fit was much better. Use it !! cg_wave_re=old_re; cg_wave_im=old_im; trials--; } else { // We have two results, one from each side. // None is much better than the other. // Use the weighted average. t1=midpoint[trials]; t2=midpoint[trials-1]; if(t1-t2 > (baseband_size >>1))t1=t1-baseband_size; if(t1-t2 < -(baseband_size >>1))t1=t1+baseband_size; p1=offset[trials]; p2=offset[trials-1]; p1=1/(0.2+fabs(p1)); p2=1/(0.2+fabs(p2)); p1=p1*p1; p2=p2*p2; t1=(p1*t1+p2*t2)/(p1+p2); if(t1 >= baseband_size)t1-=baseband_size; if(t1<0)t1+=baseband_size; midpoint[trials]=t1; t1=ampl[trials]; t2=ampl[trials-1]; ampl[trials]=(p1*t1+p2*t2)/(p1+p2); cg_wave_re=(p1*re_2+p2*old_re)/(p1+p2); cg_wave_im=(p1*im_2+p2*old_im)/(p1+p2); } } } } cg_wave_midpoint=midpoint[trials]; cg_wave_fit=ampl[trials]; cg_wave_re/=dash_sumsq; cg_wave_im/=dash_sumsq; } int store_symmetry_adapted_dashdot(int ideal) { int i, j, k, ia, ib, ic, ih, im; float t1, t2, t3, r1, r2, r3, der1, der2, phmax, phslope; float maxpow, afac; // Knowing that the curve shape should be symmetrical around it's // midpoint, fold the signal over and form sums and differences. if(PR00 != 0) { for(j=0; j= 0) { ia-=2; ib+=2; t1=fftn_tmp[ia]*fftn_tmp[ia]+fftn_tmp[ia+1]*fftn_tmp[ia+1]; PRT00"\nA: %d %d %f",ia/2,ib/2,t1); if(maxpow < t1)maxpow=t1; if(maxpow > 4*t1)goto collect_power_x; t3=t1; r1+=t1; r2+=fftn_tmp[ib ]*fftn_tmp[ib ]; r3+=fftn_tmp[ib+1]*fftn_tmp[ib+1]; ib+=2; } collect_power_x:; PRT00"\nr1 %f ia %d ib %d %d %f",r1,ia/2,ib/2,(ib-ia)/2, 5*cwbit_pts); if(r1 == 0 || ib-ia < 7*cwbit_pts || ib-ia > 13*cwbit_pts ) { PRT01"Waveform error 1"); return FALSE; } r2/=r1; r3/=r1; if(r2 > 0.05 || r3>0.03) { PRT01"Waveform error 2"); return FALSE; } ih=ia; t2=0.05*maxpow; while(ia > 0 && t1 < t3 && t1 > t2 && fftn_tmp[ia]>0) { t3=t1; ia-=2; t1=fftn_tmp[ia]*fftn_tmp[ia]+fftn_tmp[ia+1]*fftn_tmp[ia+1]; } PRT00"\nia%d,ih%d",ia/2,ih/2); // The phase angle should vary linearly with time and go // through zero at the midpoint. // Normalize for a peak amplitude=1 // Store the power and the phase angle. afac=1/sqrt(maxpow); k=cw_avg_points+2; for(i=ia; i 0.05) { PRT01"Waveform error 3"); return FALSE; } phmax=phslope*(cw_avg_points-ih+1); cg_chirpx=cg_x0-1.5*cg_size*cos(phmax); cg_chirpy=cg_y0-1.5*cg_size*sin(phmax); // ih is the point of half amplitude or nearest below. // Our data may be corrupted by noise so it is perhaps not // very reliable at low amplitudes. // Remember the beginning of the curve in case we have an ideal // waveform as input. // We will use it for the beginning of the dot waveform // on the averaged data that is less accurate at low levels. if(PR00 != 0) { for(j=ia/2; j0 && fftn_tmp[im-2]*afac > 0.01) { im-=2; fftn_tmp[im]*=afac; } if(im > 0)im-=2; ib=im; while(ib >=0 ) { fftn_tmp[ib]=0; ib-=2; } if(PR00 != 0) { DEB"\nim%d,ia%d,ih%d",im/2,ia/2,ih/2); for(j=ia/2; j fabs(fftn_tmp[im+2]-0.5)) { im+=2; } t1=fftn_tmp[im]; ih=im; PRT00"\n im= %d %f",im/2,t1); // Point i to the first point in the ideal curve with a value // higher than the value on our average at im. i=0; while(cw_ideal_rise[i] < t1) { i++; } // Fit a parabola to the three points i-2,i-1 and i. der2=0; der1=cw_ideal_rise[i+1]-cw_ideal_rise[i]; next_ideal:; r3=cw_ideal_rise[i]; if(i > 1) { r2=cw_ideal_rise[i-1]; r1=cw_ideal_rise[i-2]; der2=r3+r1-2*r2; der1=r3-r1; } else { if(i > 0) { r2=cw_ideal_rise[i-1]; der2=0; der1=r3-r1; } } PRT00"\nder1 %f der2 %f",der1,der2); im-=2; i--; if(im < 0 || i< 1) { PRT01"Waveform error 8"); return FALSE; } t1-=der1-0.5*der2; fftn_tmp[im]=t1; PRT00"\nH: %d %f i=%d",im/2, fftn_tmp[im],i); if(t1 > 0)goto next_ideal; fftn_tmp[im]=0; // Put the imaginary part in place. for(i=im; i<=ih; i+=2) { fftn_tmp[i+1]=r1=fftn_tmp[i]*tan((cw_avg_points-i-1)*phslope); } } // Unfold the waveform to get the symmetry adapted original waveform back. ia=im; ib=2*(cw_avg_points-1)-im; while (ia < ib) { fftn_tmp[ib]=fftn_tmp[ia]; fftn_tmp[ib+1]=fftn_tmp[ia+1]; ia+=2; ib-=2; } ic=im; while(fftn_tmp[ic]==0)ic+=2; dash_pts=1; dash_waveform[0]=0; dash_waveform[1]=0; while(fftn_tmp[ic] != 0 ) { dash_waveform[2*dash_pts ]=fftn_tmp[ic ]; dash_waveform[2*dash_pts+1]=fftn_tmp[ic+1]; ic+=2; dash_pts++; if(dash_pts > cw_waveform_max-2) { PRT01"Waveform error 4"); return FALSE; } } dash_waveform[2*dash_pts ]=0; dash_waveform[2*dash_pts+1]=0; dash_pts++; t1=0; // Make a guess for the dot waveform. // Assume the amplitude rises and falls as for a dash, but that // the flat region in the center is shorter. // The separation between the 6dB points should be 3 and 1 code // units respectively. Including the full rise and fall, // the total lengths should be 4 and 2 units respectively. // Take the leading and ending zeroes into consideration and // construct the real part of the dot waveform from the real part // of the dashes. // Use the same phase slope to construct the imaginary part. ic=0; while(dash_waveform[2*ic]==0 && ic < (cw_waveform_max>>1)) { dot_waveform[2*ic]=0; dot_waveform[2*ic+1]=0; ic++; } k=dash_pts-2*ic; ib=ic+k/2; if(ib > (cw_waveform_max>>1)) { ib= (cw_waveform_max>>1)-1; ic=ib-k/2; if(ic < 0)ic=0; } j=ic; k=ib; while(ib>=ic) { dot_waveform[2*ic]=dash_waveform[2*ic]; dot_waveform[2*ib]=dash_waveform[2*ic]; r1=dash_waveform[2*ic]*tan((ib-ic)*phslope); dot_waveform[2*ic+1]=r1; dot_waveform[2*ib+1]=-r1; ic++; ib--; } j--; k++; while(j >=0 && k<(cw_waveform_max>>1)) { dot_waveform[2*k]=0; dot_waveform[2*k+1]=0; j--; k++; } dot_pts=k; k=2*dash_pts+2*dot_pts; dash_sumsq=0; t1=0; for(i=0; it1)cwbit_pts++; } cwbit_pts/=3; dot_pwrmax=0; dot_sumsq=0; for(i=0; i 0) { s_meter_avg=0; s_meter_avgnum=0; } lir_sched_yield(); }