view DDS_Fox.c @ 196:87dae6d62a61

New AD9912 client code to communicate with improved server code
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Mon, 31 Mar 2014 17:03:32 +0200
parents 12df3a2b18de
children
line wrap: on
line source

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

// #define DEBUG 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

typedef struct {
	char* action;
	char* canal;
	char* command;  
	char* value0;
	char* value1;
	char* value2;
	char* value3;
	char* value4;
	char* value5;
	char* value6;
	char* value7;
	char* value8;
	char* value9;
	char* value10;
	char* value11;
	char* value12;
	char* value13;
	char* value14;
	char* value15;
	char* value16;
	char* value17;
	char* value18;
	char* value19;
} Command;

static int SendCmd(char *Buffer, DDSParameter *Param);
static int RecvCmd(Command *Rd, char * Buffer, DDSParameter *Param);
static void init_command(Command *cmd);
static int parse_command(Command *cmd1, char *buf);
static void convert_double_6char (double fraction, unsigned char* octets);

#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, frmt);
	fprintf(stderr, "ERROR: %s:%d:%s: ", file, line, func);
	vfprintf(stderr, frmt, args);
	fprintf(stderr, "\n");
	va_end(args);
}

void DDSFox_Init(DDSParameter *Param, char *ip, int port)
{
	strcpy(Param->ip, ip); 
	Param->Port = 6665;
	Param->Profil = 7; // configuration profile: single freq=0, sweep=7
	Param->Clock = 200000000;
	Param->Delta_T = 0.01;
	Param->SweepRate = 0.0;
}

void DDSFox_Reset(DDSParameter *Param, double frequency)
{
	// set sweep rate to 0
	Param->SweepRate = 0.0;
	// reset the DDS
	DDSFox_DeviceReset(Param);
	// set profile number 7 soft frequecy sweep
	DDSFox_SetProfile(Param);
	// set clock divider to 1
	DDSFox_SetDiv(Param, 1);
	// set frequency
	DDSFox_SetFreqInf(Param, frequency);
	// set frequency upper bound to max value
	DDSFox_SetFreqMax(Param);
	// set sweep rate to 0
	DDSFox_SetDT(Param);
	DDSFox_SetDf(Param);
	DDSFox_SetSweepSign(Param);
	// start sweep
	DDSFox_StartSweep(Param);
	// set frequency lower bound to min value
	DDSFox_SetFreqMin(Param);
	
	return;
}

void DDSFox_SetSweepRate(DDSParameter *Param, double sweepRate)
{
	Param->SweepRate = sweepRate;
	DDSFox_SetDf(Param);
	DDSFox_SetSweepSign(Param);
}

void DDSFox_Set(DDSParameter *Param, double frequency, double sweepRate)
{
	// set desired frequency
	DDSFox_SetFreqInf(Param, frequency);
	// set frequency upper bound to max value
	DDSFox_SetFreqMax(Param);
	// set sweep rate to 0
	Param->SweepRate = 0.0;
	DDSFox_SetDT(Param);
	DDSFox_SetDf(Param);
	DDSFox_SetSweepSign(Param);
	// start sweep
	DDSFox_StartSweep(Param);
	// set frequency lower bound to min value
	DDSFox_SetFreqMin(Param);
	// set desired sweep rate
	Param->SweepRate = sweepRate;
	DDSFox_SetDf(Param);
	DDSFox_SetSweepSign(Param);
}

void DDSFox_Nop (DDSParameter *Param)
{
	// send NOP command
	char request[255];
	sprintf(request, "set;%i;%i", 1, CMD_NOP);
	SendCmd(request, Param);
}

void DDSFox_SetProfile (DDSParameter *Param)
{
	char request[255];
	sprintf(request, "set;%i;%i;%i", 1, CMD_PROFILE, Param->Profil);
	SendCmd(request, Param);
}

void DDSFox_DeviceReset(DDSParameter *Param)
{
	char request[255];
	sprintf(request, "set;%i;%i", 1, CMD_RESET_DDS);
	SendCmd(request, Param);
}

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)
{
	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)
{
	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_SetFreqInf (DDSParameter *Param, double frequency)
{
	double word ;
	unsigned char octets[6];
	char Request[255];
	word = pow(2,48)*(frequency / Param->Clock);
	convert_double_6char(word, octets);
	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);
}

void DDSFox_SetFreqSup (DDSParameter *Param, double frequency)
{
	double word ;
	unsigned char octets[6];
	char Request[255];
	word = pow(2,48)*(frequency / Param->Clock);
	convert_double_6char(word, octets);
	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);
}

static int GetSweepSign(DDSParameter *Param)
{
	if (Param->SweepRate >= 0.0)
		return 0;
	return 1;
}

void DDSFox_SetSweepSign(DDSParameter *Param)
{
	char Request[255] ; 
	int SweepSign ;
	SweepSign = GetSweepSign(Param) ;
	sprintf(Request, "set;%i;%i;%i", 1, CMD_SWEEP_SIGN, SweepSign);
	SendCmd(Request, Param) ;
	return ;
}

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, int div)
{
	char Request[255]; 
	Command Rd;
	char temp;
	
	int Div = 0;
	// Div = log2(div)
	while ((div >>= 1) > 1)
		Div++;
	
	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 ;
}

double DDSFox_ReadFreq(DDSParameter *Param)
{
	char  Request[255]; 
	unsigned int OctetA, OctetB, OctetC, OctetD, OctetE, OctetF ;
	double FreqRead ;
	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);
}

// TCP communication

static unsigned int timeout = 0; // milliseconds


static int SendCmd(char *Buffer, DDSParameter *Param)
{
	unsigned int hConv=0;
	char  Response[255];
#ifdef DEBUG
	fprintf(stderr, "> %s\n", Buffer);
#endif
	if (ConnectToTCPServer (&hConv, Param->Port, Param->ip, NULL, NULL, timeout) < 0) {
		error("Connect failed");
		return -1;
	}
	if (ClientTCPWrite (hConv, Buffer, strlen(Buffer)+1, timeout) < 0) {
		error("Write failed");
		return -1;
	}
	sprintf(Response,"                              ");
	if (ClientTCPRead (hConv, Response, 255, timeout) < 0) {
		error("Read failed");
		return -1;
	}
#ifdef DEBUG
	fprintf(stderr, "< %s\n", Response);
#endif
	if (strncmp("OK",Response,2)) {
		error("Response failed %s %s", Buffer, Response);
		return -1;
	}
	return 0;
}

static int RecvCmd(Command *Rd, char * Buffer, DDSParameter *Param)
{
	unsigned int hConv=0;
	char parsebuf[255];
	char  Response[255];
#ifdef DEBUG
	fprintf(stderr, "> %s\n", Buffer);
#endif
	if (ConnectToTCPServer (&hConv, Param->Port, Param->ip, NULL, NULL, timeout) < 0) {
		error("Connect failed");
		return -1;     
	}
	if (ClientTCPWrite (hConv, Buffer, strlen(Buffer)+1, timeout) < 0) {
		error("Write failed");
		return -1;
	}
	sprintf(Response,"                              ");     
	if (ClientTCPRead (hConv, Response, 255, timeout) < 0) {
		error("Read failed");
		return -1;
	}
#ifdef DEBUG
	fprintf(stderr, "< %s\n", Response);
#endif
	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;
}

static void init_command(Command *cmd)
{
	memset(cmd, 0, sizeof(Command));
}

static 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;
}

// convert double into 6 bytes sent back by an unsigned char pointer
static void convert_double_6char (double fraction, unsigned char* octets)
{
	// 64 bits integer
	unsigned long long x = fraction;
	for (int i = 0; i < 6; i++)
		octets[i] = (unsigned char)((x >> (i * 8)) & 0xFF);
}