view DDS_Fox.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 e45d6e9544f5
children 7ab3fb870ef8
line wrap: on
line source

#include <tcpsupp.h>
#include <ansi_c.h>
#include "DDS_Fox.h"

//#define DDS_IP "192.168.0.3"
//#define TCP_PORT 6665

#define DIV 0			   // divided by 1
#define CMD_SEP ";"
#define BASE_TIME 0.01

#define CMD_CONFIG_REG1 1  // cmd d'acces direct au rergistre 1 de config de la DDS (voir datasheet)
#define CMD_CONFIG_REG2 2  // cmd d'acces direct au rergistre 1 de config de la DDS (voir datasheet)
#define CMD_SINGLE_FREQ_PROF0 7
#define CMD_PROFILE 15	   // cmd de choix du profile de fonctionnement de la DDS (voir datasheet)
#define CMD_ATTENUATION 16
#define CMD_RESET_DDS 17
#define CMD_NOP 20
#define CMD_FREQ_INF 21
#define CMD_FREQ_SUP 22
#define CMD_DF 23
#define CMD_DT 24
#define CMD_START_SWEEP 25
#define CMD_STOP_SWEEP 26
#define CMD_GET_FREQ 28
#define CMD_SWEEP_SIGN 29


/************************* Global variables ***********************************/ 
//static char  Request[255]; 

/************************* My own functions ***********************************/
/*DDSParameter DDSGetParam (int panel, int control) {
	DDSParameter Parameter ;
	
	GetCtrlVal (panel, CONTROL_DDS_IP, Parameter->ip) ;
	GetCtrlVal (panel, CONTROL_DDS_PORT, &(Parameter->Port)) ;
	GetCtrlVal (panel, CONTROL_DDS_CLOCK, &(Parameter->Clock)) ;
	GetCtrlVal (panel, CONTROL_DDS_RATE, &(Parameter->SweepRate)) ;
	GetCtrlVal (panel, CONTROL_DDS_DELTA_T, &(Parameter->Delta_T)) ;
	return(Parameter);
}*/


#define error(...) _error(__FILE__, __LINE__, __func__, __VA_ARGS__)

void _error(const char *file, int line, const char *func, const char *frmt, ...)
{
	va_list args;
	va_start(args, line);
	fprintf(stderr, "ERROR: %s:%d:%s: ", file, line, func);
	vfprintf(stderr, frmt, args);
	fprintf(stderr, "\n");
	va_end(args);
}


void DDS_Initialize (DDSParameter *Param) {
	char  Request[255]; 
	//send NOP command 
	sprintf(Request,"set;%i;%i",1,CMD_NOP);   
	SendCmd(Request, Param) ;
	//reset the DDS
	DDSFox_Reset(Param);
	
	//Set Profile Number 0 (only one used for soft frequecy sweep)
//	sprintf(Request,"set;%i;%i;%i",1,CMD_PROFILE,0);   
//	SendCmd(Request, Param) ; 
	
	//Set Profile Number 7 (only one used for soft frequecy sweep)
	sprintf(Request,"set;%i;%i;%i",1,CMD_PROFILE,7);   
	SendCmd(Request, Param) ; 


	//Set Clock Divider to 00b (which means 1)
	DDSFox_SetDiv(Param);
    //Set sweep rate at 0	
	DDSFox_SetFreqMax (Param);
	DDSFox_SetFreq (Param) ;
	DDSFox_SetDT (Param) ;
	DDSFox_SetDf (Param) ;
	DDSFox_StartSweep (Param) ;
	return ;
}

void DDS_ReInitialize (DDSParameter *Param) {
	char  Request[255]; 
	//send NOP command 
	sprintf(Request,"set;%i;%i",1,CMD_NOP);   
	SendCmd(Request, Param) ;
	//reset the DDS
	//DDSFox_Reset(Param);
	
	//Set Profile Number 0 (only one used for soft frequecy sweep)
//	sprintf(Request,"set;%i;%i;%i",1,CMD_PROFILE,0);   
//	SendCmd(Request, Param) ; 
	
	//Set Profile Number 7 (only one used for soft frequecy sweep)
	sprintf(Request,"set;%i;%i;%i",1,CMD_PROFILE,7);   
	SendCmd(Request, Param) ; 


	//Set Clock Divider to 00b (which means 1)
	DDSFox_SetDiv(Param);
    //Set sweep rate at 0	
	DDSFox_SetFreqMax (Param);
	DDSFox_SetFreq (Param) ;
	DDSFox_SetDT (Param) ;
	DDSFox_SetDf (Param) ;
	DDSFox_StartSweep (Param) ;
	return ;
}


void DDSFox_Reset(DDSParameter *Param) {
	char  Request[255]; 
	sprintf(Request,"set;%i;%i",1,CMD_NOP);   
	SendCmd(Request, Param) ;
	sprintf(Request,"set;%i;%i",1,CMD_RESET_DDS);   
	SendCmd(Request, Param) ;
	return ;
}


void DDSFox_StopSweep(DDSParameter *Param) {
	char  Request[255];
    sprintf(Request,"set;%i;%i;%i",1,CMD_STOP_SWEEP,1); 
  	SendCmd(Request, Param);
	return ;
}


void DDSFox_StartSweep(DDSParameter *Param) {
	char  Request[255];
    sprintf(Request,"set;%i;%i;%i",1,CMD_START_SWEEP,1); 
  	SendCmd(Request, Param);
	return ;
}

void DDSFox_SetFreqMax (DDSParameter *Param) {
	double word ;
	unsigned char octets[6];
	char  Request[255]; 
	convert_double_6char(pow(2,48)/2,octets);	 // borne sup : clock / 2
	sprintf(Request,"set;%i;%i;%i;%i;%i;%i;%i;%i",1,CMD_FREQ_SUP,
		*(octets+5),*(octets+4),*(octets+3),*(octets+2),*(octets+1),*octets); 
	SendCmd(Request, Param);
	DDSFox_SetSweepSign (Param);
	return ;
}

void DDSFox_SetFreqMin (DDSParameter *Param) {
	double word ;
	unsigned char octets[6];
	char  Request[255]; 
	convert_double_6char(1,octets);	 // borne inf : ~0
	sprintf(Request,"set;%i;%i;%i;%i;%i;%i;%i;%i",1,CMD_FREQ_INF,
		*(octets+5),*(octets+4),*(octets+3),*(octets+2),*(octets+1),*octets); 
	SendCmd(Request, Param);
	DDSFox_SetSweepSign (Param);
	return ;
}

void DDSFox_SetFreq (DDSParameter *Param) {
	double word ;
	unsigned char octets[6];
	int SweepSign = -1 ;
	char  Request[255]; 
	if (Param->Profil == 0) {
		word = pow(2,48)*(Param->Frequency/Param->Clock);
		convert_double_6char(word, octets);			// borne inf : la freq voulu	
		sprintf(Request,"set;%i;%i;%i;%i;%i;%i;%i;%i",1,CMD_FREQ_INF,
			*(octets+5),*(octets+4),*(octets+3),*(octets+2),*(octets+1),*octets); 
		SendCmd(Request, Param);
	}
	else if(Param->Profil == 7) {
		SweepSign = DDSFox_GetSweepSign(Param) ;
		if(SweepSign == 0){								// sweep positif
			word = pow(2,48)*(Param->Frequency/Param->Clock);
			convert_double_6char(word, octets);			// borne inf : la freq voulu	
			sprintf(Request,"set;%i;%i;%i;%i;%i;%i;%i;%i",1,CMD_FREQ_INF,
				*(octets+5),*(octets+4),*(octets+3),*(octets+2),*(octets+1),*octets); 
			SendCmd(Request, Param);
			DDSFox_SetFreqMax (Param);
		}
		else {											// sweep neg
			word = pow(2,48)*(Param->Frequency/Param->Clock);
			convert_double_6char(word, octets);				// borne sup : la freq voulue	
			sprintf(Request,"set;%i;%i;%i;%i;%i;%i;%i;%i",1,CMD_FREQ_SUP,
				*(octets+5),*(octets+4),*(octets+3),*(octets+2),*(octets+1),*octets); 
			SendCmd(Request, Param);
			DDSFox_SetFreqMin (Param);
		}
	}
	return ;
}


// Change le signe de sweep en frequence. Argument: struct de param de la DDS
void DDSFox_SetSweepSign(DDSParameter *Param) {
	char  Request[255] ; 
	int SweepSign ;
	SweepSign = DDSFox_GetSweepSign(Param) ;
	sprintf(Request,"set;%i;%i;%i",1,CMD_SWEEP_SIGN, SweepSign) ; 
	SendCmd(Request, Param) ;
	return ;
}

/*void DDSFox_SetSweepSign(DDSParameter *Param) {
	char  Request[255] ; 
	int SweepSign ;
	if (Param->Profil == 7)
		Param->Frequency = DDSFox_ReadFreq(Param) ;
	DDSFox_SetFreq (Param) ;
	SweepSign = DDSFox_GetSweepSign(Param) ;
	sprintf(Request,"set;%i;%i;%i",1,CMD_SWEEP_SIGN, SweepSign) ; 
	SendCmd(Request, Param) ;
	return ;
}*/


// Change la valeur de la base pour 'lincrement de frequence (sweep). Argument: delta T x 10ms, retourne rien.
void DDSFox_SetDT(DDSParameter *Param) {
	char  Request[255]; 
	int dt= 0;
	char FTW0[255]="0";	   /**** sinon le fichier inf.xx est faux 	   ***/
	dt = ((Param->Delta_T)/BASE_TIME) - 1 ;
	sprintf(FTW0,"%ims",dt);
	sprintf(Request,"set;%i;%i;%i;%s",1,CMD_DT, dt ,FTW0);
	SendCmd(Request, Param) ; 
	return ;
}


// Change le facteur de division de la clock. Argument: facteur de div, retourne rien 
void DDSFox_SetDiv(DDSParameter *Param) {
	char  Request[255]; 
	int Div = DIV ;
	Command Rd;
	char  temp;
	init_command(&Rd);
	sprintf(Request,"get;%i;%i",1,CMD_CONFIG_REG2);      
	if (RecvCmd(&Rd, Request, Param) < 0)
		return;
	temp = atoi(Rd.value2) ;
	temp = temp & 0x9F ; 
	temp = temp | Div << 5 ;
	sprintf(Request,"set;%i;%i;%i;%i;%i;%i;%i",1,CMD_CONFIG_REG2,atoi(Rd.value0),
			atoi(Rd.value1),temp,atoi(Rd.value3),atoi(Rd.value4)) ;
	SendCmd(Request, Param) ;
	return ;
}



void DDSFox_SetDf(DDSParameter *Param) {
	char  Request[255]; 
	double word ;
	unsigned char *octets;
	word = pow(2,48)*(fabs(Param->SweepRate)*Param->Delta_T/Param->Clock);
	octets=malloc(6*sizeof(unsigned char));
	convert_double_6char(word, octets);	
	sprintf(Request,"set;%i;%i;%i;%i;%i;%i;%i;%i",1,CMD_DF,
		*(octets+5),*(octets+4),*(octets+3),*(octets+2),*(octets+1),*octets); 
	SendCmd(Request, Param);
	free(octets);
	return ;
}

int DDSFox_GetSweepSign(DDSParameter *Param) {
	if (Param->SweepRate >= 0) return(0);
	else return(1);
}


double DDSFox_ReadFreq(DDSParameter *Param) {
	char  Request[255]; 
	unsigned int OctetA, OctetB, OctetC, OctetD, OctetE, OctetF ;
	double FreqRead ;
	int cmd[20];
	Command Rd;
	init_command(&Rd);
	sprintf(Request,"get;%i;%i",1,CMD_GET_FREQ); 
	if (RecvCmd(&Rd, Request, Param) == -1)
		return -1.;
	OctetA=atoi(Rd.value0);
	OctetB=atoi(Rd.value1); 
	OctetC=atoi(Rd.value2); 
	OctetD=atoi(Rd.value3); 
	OctetE=atoi(Rd.value4); 
	OctetF=atoi(Rd.value5);
	FreqRead = 1099511627776.0 * OctetA + 4294967296.0 * OctetB + 16777216.0 * OctetC + 65536.0 * OctetD + 256.0 * OctetE + 1.0 * OctetF;
	FreqRead = FreqRead * Param->Clock / pow(2,48);
	return(FreqRead);
}


/************************ Fonction de communications TCP ******************/
static const double timeout = 0.5;


int SendCmd(char *Buffer, DDSParameter *Param) {
	unsigned int hConv=0;
	char  Response[255];
	char parsebuf[255];
	if (ConnectToTCPServer (&hConv, Param->Port, Param->ip, OnTCPEvent, Response, 0) < 0) {
		error("Connect failed");
		return -1;
	}
	if (ClientTCPWrite (hConv, Buffer, strlen(Buffer)+1, 0) < 0) {
		error("Write failed");
		return -1;
	}
	sprintf(Response,"                              ");
	if (ClientTCPRead (hConv, Response, 255, 0) < 0) {
		error("Read failed");
		return -1;
	}
	if (strncmp("OK",Response,2)) {
		error("Response failed %s %s", Buffer, Response);
		return -1;
	}
	return 0;
}


int RecvCmd(Command *Rd, char * Buffer, DDSParameter *Param) {
	unsigned int hConv=0;
	char parsebuf[255];
	char  Response[255];
	if (ConnectToTCPServer (&hConv, Param->Port, Param->ip, OnTCPEvent, Response, 0) < 0) {
		error("Connect failed");
		return -1;     
	}
	if (ClientTCPWrite (hConv, Buffer, strlen(Buffer)+1, 0) < 0) {
		error("Write failed");
		return -1;
	}
	sprintf(Response,"                              ");     
	if (ClientTCPRead (hConv, Response, 255, 0) < 0) {
		error("Read failed");
		return -1;
	}

	if (strncmp(Buffer,Response,strlen(Buffer))) {
		error("Response failed %s %s", Buffer, Response);
		return -1;
	}
	
	sprintf(parsebuf,"%s",Response) ;	 
	parse_command(Rd, parsebuf) ; 	 
	return 0;
}


int OnTCPEvent(unsigned handle, int xType, int errCode, void *callbackData) {
	//char* Response = (char*)(callbackData);
	//char Response[255];
	//switch(xType) {
	//	case TCP_DISCONNECT :
			//printf("Server disconnected\n");
	//		break;
	//	case TCP_DATAREADY :
			//printf("Server data ready\n");
			//ClientTCPRead (handle, Response, 255, 5);
	//		break;
	//}
	return 0;
}

/************************ Fonction de mise en forme des données pour le transfert ******************/

void parse_command2(int* cmd, char* buf)
{
	char* pointer;
	int c = 0;
	
	pointer = strtok( buf, CMD_SEP );
	while( pointer ){
		if ((c > 2) && ( c < 19 ))
		{
			cmd[c-3] = atoi(pointer);
			printf("%i", cmd[c-3]);
		}
			
			
		pointer = strtok( NULL, CMD_SEP );
		c++;
	}
}


int parse_command(Command *cmd1, char *buf){
	char* pointer;
	int c = 0;
	
	pointer = strtok( buf, CMD_SEP );
	while( pointer ){
		if( c == 0 ){
			cmd1->action = pointer;
		}
		else if( c == 1 ){
			cmd1->canal = pointer;
		}
		else if( c == 2 ){
			cmd1->command = pointer;
		}
		else if( c == 3 ){
			cmd1->value0 = pointer;
		}
		else if( c == 4 ){
			cmd1->value1 = pointer;
		}
		else if( c == 5 ){
			cmd1->value2 = pointer;
		}
		else if( c == 6 ){
			cmd1->value3 = pointer;
		}
		else if( c == 7 ){
			cmd1->value4 = pointer;
		}				 
		else if( c == 8 ){
			cmd1->value5 = pointer;
		}
		else if( c == 9 ){
			cmd1->value6 = pointer;
		}
		else if( c == 10 ){
			cmd1->value7 = pointer;
		}
		pointer = strtok( NULL, CMD_SEP );
		c++;
	}
	return 0;
}


int init_command(Command *cmd1){
	cmd1->action = NULL;
	cmd1->canal = NULL;
	cmd1->command = NULL;
	cmd1->value0 = NULL;
	cmd1->value1 = NULL;
	cmd1->value2 = NULL;
	cmd1->value3 = NULL;
	cmd1->value4 = NULL;
	cmd1->value5 = NULL;
	cmd1->value6 = NULL;
	cmd1->value7 = NULL;
	cmd1->value8 = NULL;
	cmd1->value9 = NULL;
	cmd1->value10 = NULL;
	cmd1->value11 = NULL;
	cmd1->value12 = NULL;
	cmd1->value13 = NULL;
	cmd1->value14 = NULL;
	cmd1->value15 = NULL;
	cmd1->value16 = NULL;
	cmd1->value17 = NULL;
	cmd1->value18 = NULL;
	cmd1->value19 = NULL;
	return 0;
}


//Convert double into 6 bytes sent back by an unsigned char pointer
int convert_double_6char (double fraction, unsigned char* octets) {
	double  bita, bitb, bitc, bitd, bite, bitf;
	bitf= fraction/(1099511627776.0); 
	*(octets+5)=(unsigned char)bitf;
	bite= (fraction-1099511627776.0*(*(octets+5)))/(4294967296.0);
	*(octets+4)=(unsigned char)bite;
	bitd=(fraction-1099511627776.0*(*(octets+5))- 4294967296.0*(*(octets+4)))/( 16777216.0);
	*(octets+3)=(unsigned char)bitd;
	bitc=(fraction-1099511627776.0*(*(octets+5))- 4294967296.0*(*(octets+4))-16777216.0*(*(octets+3)))/( 65536.0);
	*(octets+2)=(unsigned char)bitc;
	bitb= (fraction-1099511627776.0*(*(octets+5))- 4294967296.0*(*(octets+4))-16777216.0*(*(octets+3))-65536*(*(octets+2)))/ 256.0;
	*(octets+1)=(unsigned char)bitb;
	bita= (fraction-1099511627776.0*(*(octets+5))- 4294967296.0*(*(octets+4))-16777216.0*(*(octets+3))-65536*(*(octets+2))-256.0*(*(octets+1)))/ 1.0;  
	*(octets)=(unsigned char)bita;
	return 0;
}