view DDS4xAD9912.c @ 183:791ca26fee6a

Rewrite data writing to file Fmt() uses by default truncation to conver double arguments to their text representation. Rounding must be used. Rewrite using standard C functions to get rid of this problem (and probably make it more efficient). Extend to handle arbitrary number of channels and to report errors on opening the data files.
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Fri, 21 Feb 2014 18:42:30 +0100
parents d96f0b04f7fe
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];
}