view Allan.c @ 23:65e277fdf01f

Correct DDS3 frequency adjustement on N3 measurement We need to take into account the phase locked loop divisor factor that links DDS1 frequency change to repetition rate change.
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Fri, 20 Jul 2012 16:50:11 +0200
parents d9aae7d7f2c6
children 0e9f95525a8f
line wrap: on
line source

#include <ansi_c.h>
#include <userint.h>

#include "YLCStuff.h"

#include "FXAllan.h"   // Auto generated panel definitions and protypes
#include "Allan.h"	   // My own .h file, containing prototypes and definitions for the class Allan...



// ******************* Member functions : constructor and destructor *************************

int Allan_InitPanel(Allan_Data * Instance, char * title, double Normalizer, void (*OnCloseFunc)(int)) {
	
	int i ;
	
	if ((Instance->AllanPanel = LoadPanel (0, "FXAllan.uir", ALLANPANEL)) < 0)
	return -1;
	SetPanelAttribute(Instance->AllanPanel, ATTR_TITLE, title) ; 
	SetPanelAttribute (Instance->AllanPanel, ATTR_CALLBACK_DATA, (void *)Instance); // the panel callback therefore knows which data structure it is associated to
	Instance->OnClosePanel = OnCloseFunc ;
	for (i=0 ; i<ALLAN_MAXPOINTSNUMBER ; i++) {
		Instance->AllanVar[i] = 0 ;
		Instance->LastMean[i] = 0 ; 
		Instance->BlocksNumber[i] = 0 ;
		Instance->CurrentAverage[i] = 0 ; 
		Instance->NbCurrentAverage[i] = 0 ;
	} ;
	Instance->Drift = 0 ;
	DisplayPanel (Instance->AllanPanel);
	SetCtrlVal(Instance->AllanPanel, ALLANPANEL_NORMALIZER, Normalizer) ;
	return 0 ;
	}



int Allan_ClosePanel(Allan_Data * Instance) {
	Instance->OnClosePanel(Instance->AllanPanel) ;
	DiscardPanel (Instance->AllanPanel); 
	return 0;
	}

	

// ******************** Member functions, callbacks (private) *******************************    


int  CVICALLBACK Allan_CB_Reset(int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	int i ;
	Allan_Data * Instance = NULL;
	
	switch(event) {

		case EVENT_COMMIT:
			GetPanelAttribute (panel, ATTR_CALLBACK_DATA, &Instance);
			Allan_Reset(Instance) ;	
			break;
			
		case EVENT_RIGHT_CLICK:

			break;
		}
		
	return 0;
}

int CVICALLBACK Allan_CB_ChangeMax (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{  
	int YMin, YMax ;

	switch (event)
		{
		case EVENT_COMMIT:
			GetCtrlVal(panel, ALLANPANEL_MIN, &YMin) ;
			GetCtrlVal(panel, ALLANPANEL_MAX, &YMax) ;
			if (YMin<YMax) {
				SetAxisScalingMode(panel, ALLANPANEL_ALLANPLOT, VAL_LEFT_YAXIS, VAL_MANUAL, pow(10,(double)YMin), pow(10,(double)YMax) ) ;
				SetCtrlVal(panel, ALLANPANEL_CHECKBOX_AUTOSCALE, FALSE) ; 
				} ;
			break;
			
		case EVENT_RIGHT_CLICK:

			break;
		}	
	return 0;
}

int CVICALLBACK Allan_CB_ChangeMin (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{   
	int YMin, YMax ;
	
	switch (event)
		{
		case EVENT_COMMIT:
				GetCtrlVal(panel, ALLANPANEL_MIN, &YMin) ;
				GetCtrlVal(panel, ALLANPANEL_MAX, &YMax) ;
				if (YMin<YMax ) {     
					SetAxisScalingMode(panel, ALLANPANEL_ALLANPLOT, VAL_LEFT_YAXIS, VAL_MANUAL, pow(10,(double)YMin), pow(10,(double)YMax) ) ;
					SetCtrlVal(panel, ALLANPANEL_CHECKBOX_AUTOSCALE, FALSE) ;
					} ;
			break;
			
		case EVENT_RIGHT_CLICK:

			break;
		}	  
	return 0;
}


int CVICALLBACK Allan_CB_ChangeAutoScale (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{  
	return 0; 
} 


int CVICALLBACK Allan_CB_ChangeNormalizer (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{  /*
	bool AutoScale = FALSE;
	int NotCare  = 20000000 ;
	double YMin = 10000000 , YMax = 64000000 ;
	
	switch (event)
		{
		case EVENT_COMMIT:
			GetCtrlVal(panel, ALLANPANEL_CHECKBOX_AUTOSCALE, &AutoScale) ;
			if (AutoScale) {
				SetAxisScalingMode(panel, ALLANPANEL_ALLANPLOT, VAL_LEFT_YAXIS, VAL_AUTOSCALE, YMin, YMax) ;
				GetAxisScalingMode(panel, ALLANPANEL_ALLANPLOT,VAL_LEFT_YAXIS, &NotCare, &YMin, &YMax ) ;
				SetCtrlVal(panel, ALLANPANEL_MIN, YMin);
				SetCtrlVal(panel, ALLANPANEL_MAX, YMax);
				}
			else {
				GetCtrlVal(panel, ALLANPANEL_MIN, &YMin);
				GetCtrlVal(panel, ALLANPANEL_MAX, &YMax);
				SetAxisScalingMode(panel, ALLANPANEL_ALLANPLOT, VAL_LEFT_YAXIS, VAL_MANUAL, YMin, YMax) ;
				} ;
			break;
		case EVENT_RIGHT_CLICK:

			break;
		}	 */
	return 0; 
} 



// ******************** Member functions, public *****************************************    

int Allan_Reset(Allan_Data * Instance) {
	
	int i ;
	
	for (i=0 ; i<ALLAN_MAXPOINTSNUMBER ; i++) {
		Instance->AllanVar[i] = 0 ;
		Instance->LastMean[i] = 0 ; 
		Instance->BlocksNumber[i] = 0 ;
		Instance->CurrentAverage[i] = 0 ; 
		Instance->NbCurrentAverage[i] = 0 ;
	} ;
	
	return 0 ;

}


int Allan_AddFrequency(Allan_Data * Instance, double Freq) {

	int i, N;  
	double CurrentMean, LastMean, Drift, Mean, Normalizer ;
	
	N = Instance->BlocksNumber[0]+1 ;	   // the total number of points used, usefull to calculate drift rate
	Mean = Instance->Mean ;
	Drift = Instance->Drift ;
	
	GetCtrlVal(Instance->AllanPanel, ALLANPANEL_NORMALIZER, &Normalizer);
	
	if (N > 1) {   // Drift measure needs at least 2 values !
		Instance->Drift = (Drift*(N-2) + 6*(Freq-Mean)/N)/(N+1) ;
		SetCtrlVal(Instance->AllanPanel, ALLANPANEL_DRIFT, Instance->Drift/Normalizer ) ;
	}
	
	// update mean value (usefull to calculate drift rate with linear regression incremental algorithm...)
	Instance->Mean = (Mean*(N-1)+Freq)/N ; 
	
	
	for (i=0 ; i<ALLAN_MAXPOINTSNUMBER ; i++) {
		Instance->CurrentAverage[i] = (Instance->CurrentAverage[i]*Instance->NbCurrentAverage[i] + Freq)
											/(Instance->NbCurrentAverage[i]+1) ;
		Instance->NbCurrentAverage[i] +=1 ;
		
		if (Instance->NbCurrentAverage[i] >= pow(2,i) ) {

			CurrentMean = Instance->CurrentAverage[i];
			LastMean = Instance->LastMean[i] ;
			N = Instance->BlocksNumber[i] ;
			N++ ;
			Instance->CurrentAverage[i] = 0 ;
			Instance->NbCurrentAverage[i] = 0 ;
			if (N>1) {
				Instance->AllanVar[i] = (Instance->AllanVar[i]*(N-2)
										+0.5*pow(CurrentMean-LastMean,2))/(N-1)  ;
			}
			else { // ie if N=1, which is realized for the first completed block
				Instance->FirstMean[i] = CurrentMean ;
			} ;
			Instance->LastMean[i] = CurrentMean ;
			Instance->BlocksNumber[i] = N ;
		} ;
	} ;
	
	Allan_Display(Instance, VAL_WHITE, VAL_BLUE) ;
	
	return 0 ;
}

int Allan_Display (Allan_Data * Instance, int ColorPt, int ColorErrorBar){

	int PointsNumber = ALLAN_MAXPOINTSNUMBER ;
	int i, N ;
	double X[ALLAN_MAXPOINTSNUMBER] ;
	double Y[ALLAN_MAXPOINTSNUMBER] ;
	double Normalizer, DriftTau, FirstFreq, LastFreq, Error ;
	bool DeDrift ;
	
	GetCtrlVal(Instance->AllanPanel, ALLANPANEL_NORMALIZER, &Normalizer) ;
	GetCtrlVal(Instance->AllanPanel, ALLANPANEL_DEDRIFT, &DeDrift) ;
	
	for (i=0 ; i<PointsNumber ; i++) {
		X[i] = pow(2,i) ;
		if (!DeDrift) { Y[i] = sqrt(Instance->AllanVar[i])/Normalizer ;}
		else { 
			DriftTau = Instance->Drift*X[i] ;
			N = Instance->BlocksNumber[i] ;
			if (N>=2) { // if enough data to calculate AVAR for tau = 2^i*tau0, and therefore, AllanVar[i] is meaningful
				FirstFreq = Instance->FirstMean[i] ;
				LastFreq = Instance->LastMean[i] ;
				Y[i] = sqrt(Instance->AllanVar[i]+DriftTau*(DriftTau/2-(LastFreq-FirstFreq)/(N-1)))/Normalizer ;
				// Not totaly sure it works... to be checked thoroughly   
				}
			else { Y[i] = 0 ; } ;
			} ;
	} ;
	
	DeleteGraphPlot(Instance->AllanPanel, ALLANPANEL_ALLANPLOT, -1, VAL_IMMEDIATE_DRAW) ; 
	PlotXY (Instance->AllanPanel, ALLANPANEL_ALLANPLOT, X, Y, PointsNumber,
			VAL_DOUBLE, VAL_DOUBLE, VAL_SCATTER, VAL_SOLID_SQUARE, VAL_SOLID, 1, ColorPt);
	
	for (i=0 ; i<PointsNumber ; i++) {
		Error = 1/sqrt(Instance->BlocksNumber[i]) ;
		PlotLine  (Instance->AllanPanel, ALLANPANEL_ALLANPLOT, X[i], Y[i]*(1-Error), X[i], Y[i]*(1+Error), ColorErrorBar);
	} ;
 
	
	return 0 ;
}

int Allan_DisplayErrorBars (Allan_Data * Instance, int color){

	int i;
	double X[ALLAN_MAXPOINTSNUMBER] ;
	double Val, Error, Normalizer;
	
	GetCtrlVal(Instance->AllanPanel, ALLANPANEL_NORMALIZER, &Normalizer) ;
	for (i=0 ; i<ALLAN_MAXPOINTSNUMBER ; i++) {
		X[i] = pow(2,i) ;
		Val = sqrt(Instance->AllanVar[i])/Normalizer ;
		Error = 1/sqrt(Instance->BlocksNumber[i]) ;      
		PlotLine  (Instance->AllanPanel, ALLANPANEL_ALLANPLOT, X[i], Val*(1-Error), X[i], Val*(1+Error), color);
	} ;
	
	return 0 ;
}

int CVICALLBACK CB_GeneralAllanPanel (int panel, int event, void *callbackData,
		int eventData1, int eventData2)
{
	Allan_Data * Instance = NULL;
	
	
	switch (event)
		{
		case EVENT_GOT_FOCUS:

			break;
		case EVENT_LOST_FOCUS:

			break;
		case EVENT_CLOSE:
			GetPanelAttribute (panel, ATTR_CALLBACK_DATA, &Instance);
			Allan_ClosePanel(Instance) ;
			
			break;
		}
	return 0;
}