Mercurial > hg > fxanalyse
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 } |