comparison ad9912.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
children f8118b90490e
comparison
equal deleted inserted replaced
195:d841dfb30b0b 196:87dae6d62a61
1 #ifdef _CVI_
2 #include <ansi_c.h>
3 #include <toolbox.h>
4 #include <tcpsupp.h>
5 #define TIMEOUT 0
6 #define send(fd, buf, len, f) ClientTCPWrite(fd, buf, len, TIMEOUT)
7 #define recv(fd, buf, len, f) ClientTCPRead(fd, buf, len, TIMEOUT)
8 #define usleep(t) Delay(t / 1000000.0)
9 #define strdup(s) StrDup(s)
10 #else
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <string.h>
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20 #include <netdb.h>
21 #include <ctype.h>
22 #include <math.h>
23 #include <stdarg.h>
24 #endif
25
26 #include "ad9912.h"
27
28 #define streq(x, y) (strcmp((x), (y)) == 0)
29
30 typedef unsigned long long uint64;
31
32
33 static inline uint64 ftw(double clock, double freq)
34 {
35 uint64 ftw = freq * ((double)(1 << 48) / clock);
36 ftw = ftw & ~1ULL;
37 return ftw;
38 }
39
40
41 static inline double freq(double clock, uint64 ftw)
42 {
43 double freq = (double)ftw * (clock / (double)(1ULL << 48));
44 return freq;
45 }
46
47
48 static inline int strtouint64(const char *str, uint64 *v)
49 {
50 char *end;
51 *v = strtoull(str, &end, 0);
52 if (*end != '\0')
53 return -1;
54 return 0;
55 }
56
57
58 static int msend(int fd, char *buffer, int n)
59 {
60 int r;
61
62 buffer[n++] = '\r';
63 buffer[n++] = '\n';
64
65 r = send(fd, buffer, n, 0);
66 if (r < 0)
67 return r;
68
69 return 0;
70 }
71
72
73 static int mrecv(int fd, char *buffer, int len)
74 {
75 int n;
76
77 n = recv(fd, buffer, len, 0);
78 if (n < 0)
79 return n;
80
81 if ((buffer[--n] != '\n') || (buffer[--n] != '\r'))
82 return -1;
83
84 buffer[n] = '\0';
85
86 return n;
87 }
88
89
90 static int command(int fd, char *frmt, ...)
91 {
92 int r, n;
93 char buffer[1024];
94 va_list v;
95
96 va_start(v, frmt);
97 n = vsnprintf(buffer, sizeof(buffer) - 2, frmt, v);
98 va_end(v);
99
100 r = msend(fd, buffer, n);
101 if (r < 0)
102 return r;
103
104 r = mrecv(fd, buffer, sizeof(buffer));
105 if (r < 0)
106 return r;
107
108 if (! streq(buffer, "OK"))
109 return -1;
110
111 return 0;
112 }
113
114
115 int ad9912_init(struct ad9912 *d, const char *hostname, double clock)
116 {
117 int n, r;
118 char buffer[256];
119
120 d->hostname = StrDup(hostname);
121 d->port = 1234;
122 d->clock = clock;
123
124 #ifdef _CVI_
125 unsigned int sock;
126 r = ConnectToTCPServer(&sock, d->port, d->hostname, NULL, NULL, TIMEOUT);
127 if (r < 0)
128 return -1;
129 #else
130 int sock;
131 struct sockaddr_in addr;
132 struct hostent* host;
133
134 host = gethostbyname(hostname);
135 if (host == NULL)
136 return -1;
137
138 sock = socket(AF_INET, SOCK_STREAM, 0);
139 if (sock < 0)
140 return -2;
141
142 addr.sin_family = host->h_addrtype;
143 memcpy(&addr.sin_addr.s_addr, host->h_addr_list[0], host->h_length);
144 addr.sin_port = htons(port);
145
146 r = connect(sock, (struct sockaddr*)&addr, sizeof(addr));
147 if (r < 0)
148 return -3;
149 #endif
150
151 d->fd = sock;
152
153 /* check compatibility */
154 n = snprintf(buffer, sizeof(buffer), "REVISION");
155 r = msend(d->fd, buffer, n);
156 if (r < 0)
157 return r;
158 r = mrecv(d->fd, buffer, sizeof(buffer));
159 if (r < 0)
160 return r;
161 if (atoi(buffer) != REVISION)
162 return -1;
163
164 return 0;
165 }
166
167
168 int ad9912_set_frequency(struct ad9912 *d, unsigned channel, double f)
169 {
170 int r;
171 uint64 value = ftw(d->clock, f);
172
173 r = command(d->fd, "SET CH%d:FTW0 0x%llX", channel, f);
174 if (r < 0)
175 return r;
176
177 d->frequency[channel] = freq(d->clock, value);
178
179 return 0;
180 }
181
182
183 int ad9912_get_frequency(struct ad9912 *d, unsigned channel, double *f)
184 {
185 int r, n;
186 uint64 value;
187 char buffer[256];
188
189 n = snprintf(buffer, sizeof(buffer), "GET CH%d:FTW0", channel);
190
191 r = msend(d->fd, buffer, n);
192 if (r < 0)
193 return r;
194
195 r = mrecv(d->fd, buffer, sizeof(buffer));
196 if (r < 0)
197 return r;
198
199 r = strtouint64(buffer, &value);
200 if (r < 0)
201 return r;
202
203 d->frequency[channel] = freq(d->clock, value);
204 if (f)
205 *f = d->frequency[channel];
206
207 return 0;
208 }
209
210
211 /**
212 * Ramp DDS frequency from @f1 to @f2 in steps @fstep with 0.01
213 * seconds delay after each step.
214 */
215 int ad9912_ramp_frequency2(struct ad9912 *d, unsigned channel, double f1, double f2, double fstep)
216 {
217 const int delay = 10000;
218
219 /* f2 > f1 */
220 while ((f2 - f1) > fstep) {
221 f1 += fstep;
222 ad9912_set_frequency(d, channel, f1);
223 usleep(delay);
224 }
225
226 /* f2 < f1 */
227 while ((f1 - f2) > fstep) {
228 f1 -= fstep;
229 ad9912_set_frequency(d, channel, f1);
230 usleep(delay);
231 }
232
233 /* final adjustment */
234 ad9912_set_frequency(d, channel, f2);
235 return 0;
236 }
237
238
239 int ad9912_ramp_frequency(struct ad9912 *d, unsigned channel, double f, double fstep)
240 {
241 return ad9912_ramp_frequency2(d, channel, d->frequency[channel], f, fstep);
242 }