view DDS4xAD9912.c @ 174:d96f0b04f7fe

Make DDS addres configurable in configuration file. Modernize AD9912 driver.
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Fri, 21 Feb 2014 18:37:32 +0100
parents fd085d61e4ca
children 0e0282010be3
line wrap: on
line source

#include <toolbox.h>
#include <ansi_c.h>
#include <utility.h>
#include <userint.h>
#include <tcpsupp.h>

#include "DDS4xAD9912.h"


void DDS4xAD9912_Init(DDS4xAD9912_Data *dds, const char *host, double clock)
{
	memset(dds, 0, sizeof(DDS4xAD9912_Data));
	dds->port[0] = 6665;
	dds->port[1] = 6666;
	dds->port[2] = 6667;
	dds->port[3] = 6668;
	dds->host = StrDup(host);
	dds->clock = clock;
}
	

//==============================================================================
// DDS4xAD9912_SendCmd
//
// FUNC   : envoie une chaine de caracteres sur un port du serveur TCP/IP de la foxboard
// PARAM  : DDSNum contient le numero de la DDS (1,2,3 ou 4)
// PARAM  : Buffer contenant la chaîne de caractères à envoyer
// RETURN : 0 si la connexion et l'ecriture sur le serveur TCP/IP sont OK
//==============================================================================
static int DDS4xAD9912_SendCmd(DDS4xAD9912_Data *dds, int channel, char *buffer)
{
	int rv;
	unsigned int sock;
	
	rv = ConnectToTCPServer(&sock, dds->port[channel - 1], dds->host, NULL, 0, 0);
	if (rv < 0)
		return rv;
	
	rv = ClientTCPWrite(sock, buffer, strlen(buffer) + 1, 0);
	
	DisconnectFromTCPServer(sock);
	
	return rv;
}


//==============================================================================
// DDS4xAD9912_Reset
//
// FUNC   : reset des 4 DDS
// PARAM  :
// RETURN : 0 si le reset de la DDS 1 , DDS 2, DDS3 et DDS4 est OK
//==============================================================================
 int DDS4xAD9912_Reset(DDS4xAD9912_Data *dds)
 {
	int channel, rv;
	char request[256];
		
	sprintf(request, "set;%i;%i", 1, 17);
	
	for (channel = 1; channel < 5; channel++) {
		rv = DDS4xAD9912_SendCmd(dds, channel, request);
		if (rv < 0) {
			MessagePopup("DDS4xAD9912", "Reset failed");
			return -1;
		}
		dds->frequency[channel - 1] = 0.0;
	}
	return 0;
}


/* convert 64 bit integer into 6 bytes array */
static inline void tobytes(unsigned long long x, unsigned char* bytes)
{
	/* 64 bits integer */
	for (int i = 0; i < 6; i++)
		bytes[i] = (unsigned char)((x >> (i * 8)) & 0xFF);
}


#define WORD(freq, clock) ((double)(1ULL << 48) * (freq / clock))


//==============================================================================
// DDS4xAD9912_SetFreq
//
// FUNC   : sort une fréquence sur la DDS1 ,DDS2, DDS3 ou DDS4
// PARAM  : DDSNum contient le numero de la DDS (1, 2 , 3 ou 4)
// RETURN : 0 si la connexion et l'ecriture sur le serveur TCP/IP sont OK
//============================================================================== 
int DDS4xAD9912_SetFrequency(DDS4xAD9912_Data *dds, int channel, double frequency)
{
	int rv;
	char request[256];
	unsigned char b[6];
	unsigned long long ftw = WORD(frequency, dds->clock);
	
	tobytes(ftw, b);

	sprintf(request, "set;%i;%i;%i;%i;%i;%i;%i;%i", 0, 10, b[5], b[4], b[3], b[2], b[1], b[0]); 
	rv = DDS4xAD9912_SendCmd(dds, channel, request);
	if (rv < 0) {
		MessagePopup("DDS", "SetFrequency function failed");
		return -1;
	}

	sprintf(request, "set;%i;%i", 0, 18);
	rv = DDS4xAD9912_SendCmd(dds, channel, request) ;
	if (rv < 0) {
		MessagePopup("DDS", "IOUpdate function failed");
		return -1;
	}

	dds->frequency[channel - 1] = (double)ftw * dds->clock / (double)(1ULL << 48);
	return 0;
} 

 
/* 
 * ramp DDS frequency from `f1` to `f2` in steps of `fstep` 
 * with a delay of 0.01 seoconds after each step
 */
int DDS4xAD9912_RampFrequency2(DDS4xAD9912_Data *dds, int channel, double f1, double f2, double fstep)
{
	const double delay = 0.01;
	
	/* f2 > f1 */
	while ((f2 - f1) > fstep) {
		f1 += fstep;
		DDS4xAD9912_SetFrequency(dds, channel, f1);
		Delay(delay);
	}
	
	/* f2 < f1 */
	while ((f1 - f2) > fstep) {
		f1 -= fstep;
		DDS4xAD9912_SetFrequency(dds, channel, f1);
		Delay(delay);
	}
	
	/* final adjustment */
	DDS4xAD9912_SetFrequency(dds, channel, f2);
	return 0;
}


/* 
 * ramp DDS frequency from the current frequency to `f2` in steps
 * of `fstep` with a delay of 0.01 seoconds after each step
 */
int DDS4xAD9912_RampFrequency(DDS4xAD9912_Data *dds, int channel, double f2, double fstep)
{
	double f1 = DDS4xAD9912_GetFrequency(dds, channel);
	return DDS4xAD9912_RampFrequency2(dds, channel, f1, f2, fstep);
}


double DDS4xAD9912_GetFrequency(DDS4xAD9912_Data *dds, int channel)
{
	return dds->frequency[channel - 1];
}