view Allan.c @ 45:b47b97cfd050

Fix output frequency read back in DDS Fox driver The FTW registry value was read back wrong due to an integer overflow in the conversion from bytes string to double. This should fix the "jumps" seen in the application of the frequency dedrifting.
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Wed, 10 Oct 2012 12:14:01 +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;
}