1 | // Known problems / open tasks
|
2 | // - no time correlation between two results => create daemon
|
3 | // - write output to a given filename
|
4 | // - create string to send from of a one-byte-command
|
5 | // - reevaluate over border from dx10.log (30MB)
|
6 | // - reevaluate more than one call
|
7 | ///////////////////////////
|
8 | //
|
9 | // +----------------- unused (left) connector
|
10 | // | +---------- compensator (relative humidity, air temperature, barometric pressure)
|
11 | // | | +--- used (right) connector
|
12 | // | | |
|
13 | // v | v
|
14 | // +----\ v /----+
|
15 | // | \-----/ |
|
16 | // | AUX |
|
17 | // | TP I/O |
|
18 | // | |
|
19 | // | O ML10 O |
|
20 | // | EC10 |
|
21 | // \ /
|
22 | // \ O /
|
23 | // \ USB /
|
24 | // +---------+
|
25 | // A
|
26 | // |
|
27 | // +---------- USB connector
|
28 | //
|
29 | //
|
30 | // The PC sends commands down to the DX10 interface via pipe 0x01 and reads its answers back via pipe 0x81.
|
31 | // A 5Khz data-stream will be read from DX10 interface via pipe 0x82.
|
32 | // After reading anything via 0x81 or 0x82 the PC asks immediately for an acknowledge via pipe 0x00.
|
33 | // Before measuring dynamically the PC sends a command every 100ms (while measuring every 333ms).
|
34 | // The answer takes typically 31ms (maximum 79ms).
|
35 | //
|
36 |
|
37 | #include <usb.h>
|
38 | #include <stdio.h>
|
39 | #include <math.h>
|
40 | #include <process.h> // needed for _beginthread()
|
41 | #include <getopt.h> // needed for getopt
|
42 | #include "version.h"
|
43 |
|
44 | // this device's vendor and product id
|
45 | #define THIS_VID 0x0837
|
46 | #define THIS_PID 0x000b
|
47 |
|
48 | #define BOOTWAITCYCLES 22 // waiting time for green LED in 0,5 secs
|
49 | #define STANDARD_MEASURE_FREQUENCY 5000 // internal frequency of measurements (5kHz)
|
50 | #define WAVES_PER_MM 809078.31378724 // 1 / ( 0,0006328(wavelength) / 512(resolution) )
|
51 | #define DYNAMIC_RANGE 0x400000 // at this value the dynamic data overflows
|
52 |
|
53 | FILE *g_fp_out;
|
54 | FILE *g_fp_log;
|
55 | int g_iPkt_count=1;
|
56 | int g_iPkt_max=250; // 250 = 0.05 sec * 5kHz (default measuring-Time: -t0.05)
|
57 | int g_iReeval=0;
|
58 | int g_iWarning=0;
|
59 | int g_iCount=5; // 5 = 0.001 sec * 5kHz (default time-step-Interval: -i0.001)
|
60 | int g_iDbgLevel=0;
|
61 | usb_dev_handle *g_Dev = NULL; // the device handle
|
62 | unsigned short g_iPacket=0; // packet-counter
|
63 | int g_iSync=-1; // synchronisation with fifth short
|
64 | int g_iMode=-1; // counter within the 5 shorts
|
65 | int g_iUsb=0; // result = distance counter of wavelength/512
|
66 | int g_iLastusb=0; // last result
|
67 | int g_iReduce=g_iCount;
|
68 |
|
69 |
|
70 | #define ABS(x) ((x>0)?(x):(-(x)))
|
71 | #define NEXT_RING_INDEX(x, y) (((x+1)<y)?(x+1):(x+1-y))
|
72 |
|
73 |
|
74 | #define MAX_STREAM0x81 12
|
75 | #define BUFFLEN0x81 0x200
|
76 | struct { // data for 12 asynchronous streams
|
77 | void* async;
|
78 | int nos; // number of shorts
|
79 | unsigned int time0x81;
|
80 | unsigned int time0x00;
|
81 | int ret0x00;
|
82 | int fuel;
|
83 | unsigned short buff[BUFFLEN0x81];
|
84 | } g_sInterrupt0x81[MAX_STREAM0x81];
|
85 | int g_iInterrupt0x81_index_write; // active stream for writing
|
86 | int g_iInterrupt0x81_index_read; // active stream for reading
|
87 | int g_bInterrupt; // switch for interrupt
|
88 |
|
89 | #define MAX_STREAM0x82 20
|
90 | #define BUFFLEN0x82 0x1000
|
91 | struct { // data for 20 asynchronous streams
|
92 | void* async;
|
93 | int nos; // number of shorts
|
94 | unsigned short buff[BUFFLEN0x82];
|
95 | } g_sData0x82[MAX_STREAM0x82];
|
96 | int g_iData0x82_index; // active stream
|
97 |
|
98 |
|
99 |
|
100 | #define END_TOKEN (unsigned short)0xFEDC // end of token
|
101 |
|
102 | struct { // list of tokens
|
103 | unsigned short words[8];
|
104 | char name[15];
|
105 | } g_sTokenlist[]={
|
106 | {{0x8020, END_TOKEN}, "DOWN_Init8020"}, // 8000 8020
|
107 | {{0x8060, END_TOKEN}, "DOWN_Conf8060"}, // 8000 8060
|
108 | {{0x8030, END_TOKEN}, "DOWN_MSta8030"}, // 8000 8030
|
109 | {{0x8040, END_TOKEN}, "DOWN_MEnd8040"}, // 8000 8040 [8010 01ff 8020 0002]
|
110 | {{0x8011,0x01e2,0x0005,0x00e0,0x00c7,0x00ff, END_TOKEN}, "DOWN_Clear "}, // 8000 8011
|
111 | {{0x8010,0x01e2,0x0005,0x00e0,0x00c7,0x00ff, END_TOKEN}, "DOWN_Initial "}, // 8000 8010 (8010) 0857 09ba 0173 01ff
|
112 | {{0x8010,0x01e2,0x0005,0x00d3,0x00ba,0x00ff, END_TOKEN}, "DOWN_Zerosta "}, // 8000 8010 (8010) 00e1 0005 00f2 00d8 00ff
|
113 | {{0x8010,0x01e2,0x0005,0x00cc,0x00b3,0x00ff, END_TOKEN}, "DOWN_Zerodyn "}, // 8000 8010 (8010) 00e1 0005 00f2 00d8 00ff
|
114 | {{0x8010,0x01e2,0x0005,0x00d0,0x00b7,0x00ff, END_TOKEN}, "DOWN_Measure "}, // 8000 8010 (8010) 00e1 000e 00d0 0000 0000 0000 0000 0000 0010 0040 0000 0000 000f 00ff
|
115 | {{0x8010,0x01e2,0x0005,0x00cf,0x00b6,0x00ff, END_TOKEN}, "DOWN_Unkn3 "}, // 8000 8010 (8010) 00e1 0005 00f2 00d8 00ff
|
116 | {{0x8010,0x01e2,0x0006,0x00d8,0x0000,0x00c0,0x00ff, END_TOKEN}, "DOWN_Unkn5 "}, // 8000 8010 (8010) 00e1 0005 00f2 00d8 00ff
|
117 | {{0x8010,0x01e2,0x0005,0x00dc,0x00c3,0x00ff, END_TOKEN}, "DOWN_Unkn6 "}, // 8000 8010 (8010) 00e1 0005 00f2 00d8 00ff [8020 0002]
|
118 | {{0x8010,0x01e3,0x0005,0x00e0,0x00c8,0x00ff, END_TOKEN}, "DOWN_un_Init2"}, // 8000 8010
|
119 | {{0x8011,0x01e3,0x0005,0x00e0,0x00c8,0x00ff, END_TOKEN}, "DOWN_un_Sync "}, // 8000 8011
|
120 | };
|
121 | // sequence must have the SAME order!!!
|
122 | enum TOK {DOWN_Init8020
|
123 | =0, DOWN_Conf8060
|
124 | , DOWN_MSta8030
|
125 | , DOWN_MEnd8040
|
126 | , DOWN_Clear
|
127 | , DOWN_Initial
|
128 | , DOWN_Zerosta
|
129 | , DOWN_Zerodyn
|
130 | , DOWN_Measure
|
131 | , DOWN_Unkn3
|
132 | , DOWN_Unkn5
|
133 | , DOWN_Unkn6
|
134 | , DOWN_un_Init2
|
135 | , DOWN_un_Sync
|
136 | , DOWN_LAST//////////////////////////////
|
137 | , FUNCTION_WAIT // wait 1000 msec
|
138 | , FUNCTION_LOAD_PIPE // reset pipe 0x82, scheduling data transfer
|
139 | , FUNCTION_START_MEASURE
|
140 | , FUNCTION_STOP_MEASURE
|
141 | , END_PROGRAM
|
142 | };
|
143 |
|
144 | // Seen original order of commands:
|
145 | // DOWN_Zerosta, d3
|
146 | // DOWN_Zerodyn, cc
|
147 | // DOWN_Unkn3, cf
|
148 | // DOWN_Conf8060, %
|
149 | // DOWN_Unkn5, d800
|
150 | // DOWN_Unkn3, cf
|
151 |
|
152 |
|
153 |
|
154 | // milli secs since first call
|
155 | unsigned int msec(void)
|
156 | {
|
157 | unsigned int a, d;
|
158 | long long ticks;
|
159 | static unsigned int first = 0;
|
160 | static unsigned int mhz = 0;
|
161 |
|
162 | if (mhz==0) {
|
163 | unsigned char temp[10] = {""};
|
164 | unsigned long size = sizeof(temp);
|
165 | HKEY hKey;
|
166 |
|
167 | RegOpenKey(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey);
|
168 | RegQueryValueEx(hKey, "~MHz", NULL, NULL, temp, &size);
|
169 | RegCloseKey(hKey);
|
170 | mhz=*(int*)temp;
|
171 | __asm__ volatile("rdtsc" : "=a" (a), "=d" (d));
|
172 | ticks = ((unsigned long long)a) | (((unsigned long long)d) << 32);
|
173 | first=ticks/mhz/1000;
|
174 | return 0;
|
175 | }
|
176 | __asm__ volatile("rdtsc" : "=a" (a), "=d" (d));
|
177 | ticks = ((unsigned long long)a) | (((unsigned long long)d) << 32);
|
178 | return (ticks/mhz/1000)-first;
|
179 | }
|
180 |
|
181 | #define DBG9 9 // stdout: print endless data
|
182 | #define DBG3 3 // stdout:
|
183 | #define DBG2 2 // stdout:
|
184 | #define DBG1 1 // stdout: print only with option -d1
|
185 | #define ALL 0 // stdout: print always
|
186 | #define WARN -1 // stderr: warning, continue program
|
187 | #define EXIT -2 // stderr: error, stop program immediately
|
188 | void output(int mode, const char *fmt, ...)
|
189 | {
|
190 | va_list ap;
|
191 | char string[4096];
|
192 | FILE*fp=stdout;
|
193 |
|
194 | if (mode>g_iDbgLevel) // hide output because of low log-level
|
195 | return;
|
196 | if (mode<=WARN) {
|
197 | fflush(stdout);
|
198 | fp=stderr;
|
199 | }
|
200 | va_start(ap, fmt);
|
201 | vsprintf(string, fmt, ap);
|
202 | fprintf(fp, string);
|
203 | fflush(fp);
|
204 | va_end(ap);
|
205 | if (mode==WARN)
|
206 | g_iWarning++;
|
207 | if (mode==EXIT)
|
208 | exit(-1);
|
209 | return;
|
210 | }
|
211 |
|
212 |
|
213 |
|
214 | usb_dev_handle *open_dev(void)
|
215 | {
|
216 | struct usb_bus *bus;
|
217 | struct usb_device *dev;
|
218 |
|
219 | for(bus = usb_get_busses(); bus; bus = bus->next)
|
220 | for(dev = bus->devices; dev; dev = dev->next)
|
221 | if(dev->descriptor.idVendor == THIS_VID && dev->descriptor.idProduct == THIS_PID)
|
222 | return usb_open(dev);
|
223 | return NULL;
|
224 | }
|
225 |
|
226 |
|
227 |
|
228 | short read_pipe_0x00(void)
|
229 | {
|
230 | short tmp=0;
|
231 | int ret, i, iTime;
|
232 |
|
233 | if ((ret=usb_control_msg(
|
234 | g_Dev, // usb_dev_handle
|
235 | 0x80, // # int requesttype => 80: read data from device
|
236 | 0x00, // # int request
|
237 | 0x0000, // ## int value
|
238 | 0x0000, // ## int index
|
239 | (char*)&tmp, // char *bytes
|
240 | 0x0002, // ## int size
|
241 | 1000)) < 0) // int timeout
|
242 | output(EXIT, "ERROR usb_control_msg\n");
|
243 | if(tmp != 0x0000)
|
244 | output(WARN, "pipe00 returns value\n");
|
245 | return tmp;
|
246 | }
|
247 |
|
248 |
|
249 |
|
250 | void get_reeval_line(unsigned short *adr, int *nos)
|
251 | {
|
252 | int k, l, m;
|
253 | char sLine[9999];
|
254 | do {
|
255 | if(!fgets(sLine, 9999, g_fp_log)) // read data line
|
256 | output(EXIT, "ERROR no more data to simulate\n");
|
257 | } while ( (sLine[0]<'0') || (sLine[0]>'9') ); // skip comments...
|
258 | l=strlen(sLine);
|
259 | for (m=0, k=2; m<l; m++) // read time, dir+pipe
|
260 | if (sLine[m]==' ')
|
261 | if (!--k)
|
262 | break;
|
263 | if (adr)
|
264 | for (k=0, m++; m<l; m+=5, k++) // read all shorts
|
265 | sscanf(&sLine[m], "%04x", adr+k);
|
266 | if (nos)
|
267 | *nos=k;
|
268 | // sscanf(&sLine[0], "%d", iTime);
|
269 | }
|
270 |
|
271 |
|
272 |
|
273 | int write_command(unsigned short *words, int toklen)
|
274 | {
|
275 | int i, iTime;
|
276 | int ret=0;
|
277 | static int iCount=0;
|
278 |
|
279 | if (g_iReeval)
|
280 | get_reeval_line(NULL, NULL); // read line and skip
|
281 | else {
|
282 | int pos;
|
283 | char sString[32];
|
284 | fgetpos (g_fp_log, (fpos_t*)&pos);
|
285 | if (pos>30*1000*1000) {
|
286 | fclose(g_fp_log);
|
287 | sprintf(sString, "dx10_%06d.log", iCount++);
|
288 | remove(sString);
|
289 | rename("dx10.log", sString);
|
290 | g_fp_log=fopen("dx10.log", "w");
|
291 | }
|
292 | iTime=msec();
|
293 | fprintf(g_fp_log, "%d d01", iTime);
|
294 | for(i=0; i<toklen; i++)
|
295 | fprintf(g_fp_log, " %04x", words[i]);
|
296 | fprintf(g_fp_log, "\n");
|
297 | ret=usb_bulk_write(g_Dev, 0x01, (char*)words, toklen*2, 1000);
|
298 | }
|
299 | return ret;
|
300 | }
|
301 |
|
302 |
|
303 |
|
304 | void read_one_answer(void) // read from the actual read index
|
305 | {
|
306 | int i, iTime;
|
307 | if (g_iReeval) {
|
308 | get_reeval_line(&g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[0], &g_sInterrupt0x81[g_iInterrupt0x81_index_read].nos); // data line
|
309 | get_reeval_line(NULL, NULL); // skip pipe 0x00
|
310 | } else {
|
311 | while (g_iInterrupt0x81_index_write == g_iInterrupt0x81_index_read); // wait, till a new interrupt has been written
|
312 | // write BACK data from interruption log
|
313 | fprintf(g_fp_log, "//%d\n", g_sInterrupt0x81[g_iInterrupt0x81_index_read].fuel);
|
314 | iTime = g_sInterrupt0x81[g_iInterrupt0x81_index_read].time0x81;
|
315 | fprintf(g_fp_log, "%d b81", iTime);
|
316 | for(i=0; i<g_sInterrupt0x81[g_iInterrupt0x81_index_read].nos; i++)
|
317 | fprintf(g_fp_log, " %04x", g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[i]);
|
318 | fprintf(g_fp_log, "\n");
|
319 | iTime = g_sInterrupt0x81[g_iInterrupt0x81_index_read].time0x00;
|
320 | fprintf(g_fp_log, "%d b00 %04x\n", iTime, g_sInterrupt0x81[g_iInterrupt0x81_index_read].ret0x00);
|
321 | }
|
322 | }
|
323 |
|
324 |
|
325 |
|
326 | void read_data(void) // read from the actual data index
|
327 | {
|
328 | int i, j, iTime;
|
329 |
|
330 | if (g_iReeval) {
|
331 | get_reeval_line(&g_sData0x82[g_iData0x82_index].buff[0], &g_sData0x82[g_iData0x82_index].nos); // data line
|
332 | get_reeval_line(NULL, NULL); // skip pipe 0x00
|
333 | } else {
|
334 | if ((g_sData0x82[g_iData0x82_index].nos=usb_reap_async(g_sData0x82[g_iData0x82_index].async, 5000)/2) < 0)
|
335 | output(EXIT, "error reap02 %d\n", g_iData0x82_index);
|
336 |
|
337 | // write BACK data
|
338 | iTime = msec();
|
339 | fprintf(g_fp_log, "%d b82", iTime);
|
340 | for(j=0; j<g_sData0x82[g_iData0x82_index].nos; j++)
|
341 | fprintf(g_fp_log, " %04x", g_sData0x82[g_iData0x82_index].buff[j]);
|
342 | fprintf(g_fp_log, "\n");
|
343 | fprintf(g_fp_log, "%d b00 %04x\n", msec(), read_pipe_0x00());
|
344 |
|
345 | // submit this transfer and returns immediately
|
346 | if (usb_submit_async(g_sData0x82[g_iData0x82_index].async, (char*)&g_sData0x82[g_iData0x82_index].buff[0], BUFFLEN0x82) < 0)
|
347 | output(EXIT, "error usb_submit_async:\n%s\n", usb_strerror());
|
348 | }
|
349 | }
|
350 |
|
351 |
|
352 |
|
353 | void interrupt_routine(void *dummy)
|
354 | {
|
355 | int i, ret, fuel;
|
356 |
|
357 | // do once for setup
|
358 | for(i=0; i<MAX_STREAM0x81; i++)
|
359 | if (usb_bulk_setup_async(g_Dev, &g_sInterrupt0x81[i].async, 0x81) < 0)
|
360 | output(EXIT, "ERROR: no setup before interrupt:\n%s\n", usb_strerror());
|
361 |
|
362 | // submit this transfer and returns immediately
|
363 | for(i=0; i<MAX_STREAM0x81; i++) {
|
364 | if (usb_submit_async(g_sInterrupt0x81[i].async, (char*)&g_sInterrupt0x81[i].buff[0], BUFFLEN0x81) < 0)
|
365 | output(EXIT, "ERROR: no submit before interrupt:\n%s\n", usb_strerror());
|
366 | }
|
367 |
|
368 | // endless loop for interrupt
|
369 | while (g_bInterrupt) {
|
370 | // wait for the transfer to complete (no logging within interrupt)
|
371 | ret=usb_reap_async(g_sInterrupt0x81[g_iInterrupt0x81_index_write].async, 5000);
|
372 | if ((g_sInterrupt0x81[g_iInterrupt0x81_index_write].nos=ret/2) < 0) {
|
373 | if (g_bInterrupt) {
|
374 | for(i=0; i<MAX_STREAM0x81; i++)
|
375 | output(DBG1, "%d %d %d\n", i, g_sInterrupt0x81[i].time0x81, g_sInterrupt0x81[i].fuel);
|
376 | output(EXIT, "ERROR: no response in interrupt %d within time: %d\n"
|
377 | "Perhaps no cable between DX10 and laser\n"
|
378 | " or\n"
|
379 | "Replug USB cable\n", g_iInterrupt0x81_index_write, ret);
|
380 | } else
|
381 | break;
|
382 | }
|
383 | // store timervalue (log it later)
|
384 | g_sInterrupt0x81[g_iInterrupt0x81_index_write].time0x81=msec();
|
385 | g_sInterrupt0x81[g_iInterrupt0x81_index_write].ret0x00=read_pipe_0x00();
|
386 | g_sInterrupt0x81[g_iInterrupt0x81_index_write].time0x00=msec();
|
387 | // submit this transfer and returns immediately
|
388 | if (usb_submit_async(g_sInterrupt0x81[g_iInterrupt0x81_index_write].async,
|
389 | (char*)&g_sInterrupt0x81[g_iInterrupt0x81_index_write].buff[0], BUFFLEN0x81) < 0) {
|
390 | for(i=0; i<MAX_STREAM0x81; i++)
|
391 | output(DBG1, "%d %d %d\n", i, g_sInterrupt0x81[i].time0x81, g_sInterrupt0x81[i].fuel);
|
392 | output(EXIT, "ERROR: no submit in interrupt:\n%s\n", usb_strerror());
|
393 | }
|
394 | fuel=g_iInterrupt0x81_index_write-g_iInterrupt0x81_index_read;
|
395 | if (fuel<0)
|
396 | fuel+=MAX_STREAM0x81;
|
397 | g_sInterrupt0x81[g_iInterrupt0x81_index_write].fuel=fuel;
|
398 | g_iInterrupt0x81_index_write = NEXT_RING_INDEX(g_iInterrupt0x81_index_write, MAX_STREAM0x81);
|
399 |
|
400 | if (fuel > MAX_STREAM0x81-5) { // buffer overflow
|
401 | for(i=0; i<MAX_STREAM0x81; i++)
|
402 | output(DBG1, "%d %d %d\n", i, g_sInterrupt0x81[i].time0x81, g_sInterrupt0x81[i].fuel);
|
403 | output(EXIT, "ERROR: missing interrupt\nPerhaps type first <dx10 -b>\n");
|
404 | }
|
405 | Sleep(1);
|
406 | }
|
407 | }
|
408 |
|
409 |
|
410 |
|
411 | void evaluate_dynamic(int *offset)
|
412 | {
|
413 | int j;
|
414 |
|
415 | if (g_sData0x82[g_iData0x82_index].buff[0] == g_iPacket) {
|
416 | if (g_iSync == -1) {
|
417 | for(j=1; j<15; j++)
|
418 | if (g_sData0x82[g_iData0x82_index].buff[j] >= 0x80)
|
419 | break;
|
420 | if (g_iSync>13)
|
421 | output(EXIT, "ERROR: no sync\n");
|
422 | g_iSync=j+1;
|
423 | g_iMode=0;
|
424 | }
|
425 | //
|
426 | // Structure of datastream from 0x82:
|
427 | // - First short of every packet is the packet-counter.
|
428 | // - Then always 5 shorts for 1 distance (every 0,0002 sec = 5000 Hz).
|
429 | // - Only the fifth short has bit 7 set.
|
430 | //
|
431 | // mode| bit. ..98 7654 3210
|
432 | // ----+---------------------
|
433 | // 0 | 0000 0000 0?cc cccc 0: always 0
|
434 | // 1 | 0000 0000 0ccc cccc 1: always 1
|
435 | // 2 | 0000 0000 0ccc cccc c: counter (total 22 bit) for laser
|
436 | // 3 | 0000 0000 0p0i iiii i: intensity: 00-1F (00=0%, 1A=100%)
|
437 | // 4 | 0000 0000 1000 qcc? ?: unknown meaning (bit flickers)
|
438 | // q: non continuous beam
|
439 | // p: no interference
|
440 | //
|
441 | // +----+----+ +----+----+ +----+----+
|
442 | // |00cc|cccc| |cccc|cccc| |cccc|cccc| counter (total 22 bit) for laser
|
443 | // | 26|5432| |1016|5432| |1054|3210| bit no
|
444 | // | 42|2222| |2241|1111| |1100|0000| mode-byte
|
445 | // +----+----+ +----+----+ +----+----+
|
446 | //
|
447 | for(j=g_iSync; j<g_sData0x82[g_iData0x82_index].nos; j++) {
|
448 | switch(g_iMode++) {
|
449 | case 0:
|
450 | g_iUsb+=(g_sData0x82[g_iData0x82_index].buff[j]&0x3F) << 0; // bit 0-5
|
451 | if (g_sData0x82[g_iData0x82_index].buff[j]&~0x7F)
|
452 | output(WARN, "mode 0: not zero: %04X\n", g_sData0x82[g_iData0x82_index].buff[j]&~0x7F);
|
453 | break;
|
454 | case 1:
|
455 | g_iUsb+=(g_sData0x82[g_iData0x82_index].buff[j]&0x7F) << 6; // bit 6-12
|
456 | if (g_sData0x82[g_iData0x82_index].buff[j]&~0x7F)
|
457 | output(WARN, "mode 1: not zero: %04X\n", g_sData0x82[g_iData0x82_index].buff[j]&~0x7F);
|
458 | break;
|
459 | case 2:
|
460 | g_iUsb+=(g_sData0x82[g_iData0x82_index].buff[j]&0x7F) << 14; // bit 14-20
|
461 | if (g_sData0x82[g_iData0x82_index].buff[j]&~0x7F)
|
462 | output(WARN, "mode 2: not zero: %04X\n", g_sData0x82[g_iData0x82_index].buff[j]&~0x7F);
|
463 | break;
|
464 | case 3:
|
465 | if (g_sData0x82[g_iData0x82_index].buff[j]&~0x5F)
|
466 | output(WARN, "mode 3: not zero: %04X\n", g_sData0x82[g_iData0x82_index].buff[j]&~0x5F);
|
467 | if ((g_sData0x82[g_iData0x82_index].buff[j]&0x1F) < 4) // low < 15%
|
468 | output(EXIT, "ERROR: intensity too low\n");
|
469 | break;
|
470 | case 4:
|
471 | g_iUsb+=(g_sData0x82[g_iData0x82_index].buff[j]&0x02) << 13-1; // bit 13
|
472 | g_iUsb+=(g_sData0x82[g_iData0x82_index].buff[j]&0x04) << 21-2; // bit 21
|
473 | if ((g_sData0x82[g_iData0x82_index].buff[j]&~0x0F) != 0x80)
|
474 | output(WARN, "mode 4: not 0x0080: %04X\n", g_sData0x82[g_iData0x82_index].buff[j]&~0x0F);
|
475 | if (!((j==g_iSync+4)&&(g_iPacket==0))) { // for the very first value not output (only store lastusb)
|
476 | if ((j==g_iSync+9)&&(g_iPacket==0)) { // for the second value check direction and offset
|
477 | // For the very first time, offset is the 32bit static value.
|
478 | // After this calculation, offset is the 32bit value without the last 22bit (which comes from measurement)
|
479 | // Take the first two dynamic values (time-distance 1*0,0002) and calculate the value 500 time-steps before.
|
480 | // The difference of offset and this calculated value is the start value of offset.
|
481 | int off=0;
|
482 | if (g_iUsb-g_iLastusb > DYNAMIC_RANGE/2) off=-DYNAMIC_RANGE;
|
483 | if (g_iUsb-g_iLastusb < -DYNAMIC_RANGE/2) off= DYNAMIC_RANGE;
|
484 | output(DBG3, "last static value / %5.3f: %14.6f\n", DYNAMIC_RANGE/WAVES_PER_MM, 1.0*(*offset)/DYNAMIC_RANGE);
|
485 | output(DBG3, "calc dyn value : %14.6f\n", 1.0*((g_iLastusb-off)-(g_iUsb-(g_iLastusb-off))*500)/DYNAMIC_RANGE);
|
486 | output(DBG3, "first offset in double: %14.6f\n", 1.0*((*offset)-((g_iLastusb-off)-(g_iUsb-(g_iLastusb-off))*500))/DYNAMIC_RANGE);
|
487 | off=(int)floor( 1.0*((*offset)-((g_iLastusb-off)-(g_iUsb-(g_iLastusb-off))*500)+DYNAMIC_RANGE/2)/DYNAMIC_RANGE);
|
488 | output(DBG3, "first offset: %d\n", off);
|
489 | *offset=off * DYNAMIC_RANGE;
|
490 | }
|
491 | if (g_iUsb-g_iLastusb > DYNAMIC_RANGE/2) *offset-=DYNAMIC_RANGE;
|
492 | if (g_iUsb-g_iLastusb < -DYNAMIC_RANGE/2) *offset+=DYNAMIC_RANGE;
|
493 |
|
494 | int value=g_iUsb+*offset;
|
495 | if (g_sData0x82[g_iData0x82_index].buff[j]&0x08) // non continuous beam
|
496 | value=(int)(999.9999999*WAVES_PER_MM);
|
497 |
|
498 | if (!(--g_iReduce)) { // measuring always with 5kHz, output with given time-step
|
499 | g_iReduce=g_iCount;
|
500 | if (g_fp_out)
|
501 | fprintf(g_fp_out, "%.4f\t%f\n", (double)g_iPkt_count*g_iCount/STANDARD_MEASURE_FREQUENCY, value/WAVES_PER_MM);
|
502 | else
|
503 | output(ALL, "%f\n", value/WAVES_PER_MM);
|
504 | g_iPkt_count++;
|
505 | }
|
506 | }
|
507 | g_iLastusb=g_iUsb;
|
508 | g_iMode=0;
|
509 | g_iUsb=0;
|
510 | break;
|
511 | default:
|
512 | output(EXIT, "ERROR: impossible mode\n");
|
513 | }
|
514 | if (g_iPkt_count >= g_iPkt_max)
|
515 | break;
|
516 | }
|
517 | g_iSync=1;
|
518 | g_iPacket++;
|
519 | } else
|
520 | output(WARN, "ERROR wrong packet number in distance calculation\n");
|
521 | output(DBG1, "distadyn: (%f, %d) %f\n", g_iLastusb/WAVES_PER_MM, *offset/DYNAMIC_RANGE, (g_iLastusb+*offset)/WAVES_PER_MM);
|
522 | fflush(stdout);
|
523 | }
|
524 |
|
525 |
|
526 |
|
527 | int evaluate_static(int iAns, unsigned short *iAnswer, int mode)
|
528 | {
|
529 | int ret;
|
530 |
|
531 | if (iAns>13) // length
|
532 | // iAnswer[ 0] 8000
|
533 | // iAnswer[ 1] 8010
|
534 | // skip this: 8010
|
535 | if (iAnswer[2]==0xe1) // type1 with: len .... sum FF
|
536 | if (iAnswer[3]==0x0e) // length from [00e1 to 00ff]
|
537 | if (iAnswer[4]==0xd0) { // type2: measure
|
538 | // iAnswer[ 5] 0000 0000 s000 000? s: sign of counter, ?: after 82
|
539 | // iAnswer[ 6] 0000 0000 cccc cccc c(00-FF): counter
|
540 | // iAnswer[ 7] 0000 0000 cccc cccc c(00-FF): counter
|
541 | // iAnswer[ 8] 0000 0000 cccc cccc c(00-FF): counter
|
542 | // iAnswer[ 9] 0000 0000 cccc cccc c(00-FF): counter
|
543 | // iAnswer[10] 0000 0000 qp01 0000 q: non continuous beam, p: no interference
|
544 | // iAnswer[11] 0000 0000 0r00 000b r: red, b: booting=>no counter, no intensity
|
545 | // iAnswer[12] 0000 0000 000? 0000 ?:at p=0 for 4 ticks
|
546 | // iAnswer[13] 0000 0000 000i iiii i(00-1F): intensity
|
547 | // iAnswer[14] 0000 0000 xxxx xxxx sum of iAnswer[2]-iAnswer[13]
|
548 | // iAnswer[15] 0000 0000 1111 1111 00ff
|
549 |
|
550 | if ((mode==0)||(mode==1)) {
|
551 | int ret = (iAnswer[6]<<24)|(iAnswer[7]<<16)|(iAnswer[8]<<8)|iAnswer[9];
|
552 | if (iAnswer[5]&0x0080)
|
553 | ret=-ret;
|
554 | if (iAnswer[10]&0x0080) // non continuous beam
|
555 | ret=(int)(999.9999999*WAVES_PER_MM);
|
556 | if (mode) {
|
557 | if (g_fp_out)
|
558 | fprintf(g_fp_out, "%f\t%f\n", 0.0, ret/WAVES_PER_MM);
|
559 | else
|
560 | output(ALL, "distance: %11.6f\n", ret/WAVES_PER_MM);
|
561 | }
|
562 | return ret;
|
563 | } else {
|
564 | ret = ((iAnswer[5]&~0x80)<<24)|(((iAnswer[10]^0x10)&0x80)<<16)|(iAnswer[11]<<8)|iAnswer[12];
|
565 | return (iAnswer[13]&0x1F);
|
566 | }
|
567 | }
|
568 | return 0;
|
569 | }
|
570 |
|
571 |
|
572 |
|
573 | int command(int iCommand, unsigned short *iAnswer)
|
574 | {
|
575 | int i, stop, toklen;
|
576 | int iAns=0;
|
577 | unsigned short answer[32];
|
578 | if (!iAnswer)
|
579 | iAnswer=answer;
|
580 |
|
581 | // write command to usb
|
582 | for(toklen=0; g_sTokenlist[iCommand].words[toklen] != END_TOKEN; toklen++); // toklen: length of tokens
|
583 | output(DBG2, "%s ", g_sTokenlist[iCommand].name);
|
584 | if(write_command(&g_sTokenlist[iCommand].words[0], toklen)< 0)
|
585 | output(EXIT, "ERROR write\n");
|
586 |
|
587 | // read complete answer from usb
|
588 | for(iAns=0, stop=0; stop<1; ) {
|
589 | // read one answer from usb
|
590 | read_one_answer();
|
591 | //
|
592 | // Seen return values
|
593 | // ==================
|
594 | //
|
595 | // [800x, 8011] abort, skip further answer or parts of it
|
596 | // [8000, 8020] init
|
597 | // [8000, 8030] start dynamical measurement
|
598 | // [8000, 8060] config?
|
599 | // [8000, 8040] stop dynamical measurement, often with 8010 xxxx and/or 8020 0002
|
600 | // [8000, 8010] start of data
|
601 | // [8010, *] data with expected further data
|
602 | // [8010, *, ##ff] normal end of data
|
603 | // [8020, 0002] interrupt?
|
604 | // [*] not seen yet
|
605 | //
|
606 | // typical return value: 800x 80xx
|
607 | if (iAns==0) {
|
608 | if ((g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[0] & 0xFFFE) == 0x8000) { // new correct answer
|
609 | for(i=0; i<g_sInterrupt0x81[g_iInterrupt0x81_index_read].nos; i++)
|
610 | iAnswer[iAns++]=g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[i]; // fill complete answer
|
611 | if (g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[1]!=0x8010)
|
612 | stop=1;
|
613 | // additional data to skip: e.g 8020 0002 or 8010 ... (after 8000 8040 or after abortion)
|
614 | } else if (g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[0]==0x8020) {
|
615 | output(DBG1, "skip 8020 at %d (", g_sInterrupt0x81[g_iInterrupt0x81_index_read].time0x81);
|
616 | for(i=0; i<g_sInterrupt0x81[g_iInterrupt0x81_index_read].nos; i++)
|
617 | output(DBG1, " %04X", g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[i]);
|
618 | output(DBG1, ")\n");
|
619 | } else if (g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[0]==0x8010) {
|
620 | output(DBG1, "skip 8010 at %d (", g_sInterrupt0x81[g_iInterrupt0x81_index_read].time0x81);
|
621 | for(i=0; i<g_sInterrupt0x81[g_iInterrupt0x81_index_read].nos; i++)
|
622 | output(DBG1, " %04X", g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[i]);
|
623 | output(DBG1, ")\n");
|
624 | } else {
|
625 | output(WARN, "SKIP UNKNOWN at %d! (", g_sInterrupt0x81[g_iInterrupt0x81_index_read].time0x81);
|
626 | for(i=0; i<g_sInterrupt0x81[g_iInterrupt0x81_index_read].nos; i++)
|
627 | output(WARN, " %04X", g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[i]);
|
628 | output(WARN,")\n");
|
629 | }
|
630 | fflush(stdout);
|
631 | // all data: (8000 8010) 8010 .... xxFF
|
632 | // typical data: (8000 8010) 8010 00E1 00yy .... .. .... 00FF
|
633 | // 1 2 3 .. yy-1 yy
|
634 | } else {
|
635 | if (g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[0]==0x8010) { // korrekte Daten
|
636 | for(i=1; i<g_sInterrupt0x81[g_iInterrupt0x81_index_read].nos; i++)
|
637 | iAnswer[iAns++]=g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[i]; // fill complete answer
|
638 | if ((g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[i-1] & 0x00FF) == 0xFF) { // check last word == 0xFF
|
639 | if (iAnswer[2]==0x00e1) { // if typical answer with type: 0x00E1
|
640 | if ((iAnswer[3]+2==iAns) && (iAnswer[iAns-1]==0x00FF)) { // stop only, if 0x00FF appears after the correct length
|
641 | int sum=0;
|
642 | for(i=2; i<iAnswer[3]; i++) // calculate check sum
|
643 | sum+=iAnswer[i]&0x00FF;
|
644 | if ((sum&0x00FF) != iAnswer[iAns-2]) // check sum
|
645 | output(WARN, "WARNING: invalid checksum\n");
|
646 | stop=1;
|
647 | }
|
648 | } else
|
649 | stop=1; // stop for the very first answer of DOWN_Initial
|
650 | }
|
651 | // abortion with: 8000 8011
|
652 | } else if ( (g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[0]==0x8000) &&
|
653 | (g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[1]==0x8011) ) {
|
654 | output(WARN, "abort with 8000 8011 at %d\n", g_sInterrupt0x81[g_iInterrupt0x81_index_read].time0x81);
|
655 | stop=1;
|
656 | } else {
|
657 | output(WARN, "SKIP UNKNOWN DATA at %d! (", g_sInterrupt0x81[g_iInterrupt0x81_index_read].time0x81);
|
658 | for(i=0; i<g_sInterrupt0x81[g_iInterrupt0x81_index_read].nos; i++)
|
659 | output(WARN, " %04X", g_sInterrupt0x81[g_iInterrupt0x81_index_read].buff[i]);
|
660 | output(WARN, ")\n");
|
661 | stop=1;
|
662 | }
|
663 | fflush(stdout);
|
664 | }
|
665 | g_iInterrupt0x81_index_read = NEXT_RING_INDEX(g_iInterrupt0x81_index_read, MAX_STREAM0x81);
|
666 | }
|
667 | output(DBG2, " <<<");
|
668 | for(i=0; i<iAns; i++)
|
669 | if (i<20)
|
670 | output(DBG2, " %04x", iAnswer[i]);
|
671 | else
|
672 | output(DBG9, " %04x", iAnswer[i]);
|
673 | output(DBG2, "\n");
|
674 |
|
675 | return iAns;
|
676 | }
|
677 |
|
678 |
|
679 |
|
680 | void measure_dynamic(int iFirstvalue)
|
681 | {
|
682 | int i, j, iTime;
|
683 | output(DBG2, "START MEASURE\n");
|
684 | for(i=0; g_iPkt_count<g_iPkt_max; i++) { // number of packets
|
685 | // wait for the transfer to complete
|
686 | read_data();
|
687 | output(DBG2, " data");
|
688 | for(j=0; j<g_sData0x82[g_iData0x82_index].nos; j++)
|
689 | if (j<20)
|
690 | output(DBG2, " %04x", g_sData0x82[g_iData0x82_index].buff[j]);
|
691 | else
|
692 | output(DBG9, " %04x", g_sData0x82[g_iData0x82_index].buff[j]);
|
693 | output(DBG2, "\n");
|
694 |
|
695 | evaluate_dynamic(&iFirstvalue);
|
696 |
|
697 | g_iData0x82_index = NEXT_RING_INDEX(g_iData0x82_index, MAX_STREAM0x82);
|
698 | if((i%4)==0) // minimal communication during measurement
|
699 | command(DOWN_un_Sync, NULL);
|
700 | if ( (GetAsyncKeyState(VK_LCONTROL)) || // break this loop with Ctrl
|
701 | (GetAsyncKeyState(VK_RCONTROL)) ) break;
|
702 | }
|
703 | }
|
704 |
|
705 |
|
706 |
|
707 | int main(int argc, char**argv)
|
708 | {
|
709 | int c=0;
|
710 | int i;
|
711 | int iToken=-1;
|
712 | int bAlign=0;
|
713 | int bBoot=0;
|
714 | int bZero=0;
|
715 | int bPoint=0;
|
716 | double dTmp;
|
717 | g_fp_out=fopen("_out.txt", "w");
|
718 |
|
719 | // test of configuration
|
720 | if (sizeof(g_sTokenlist)/sizeof(g_sTokenlist[0]) != DOWN_LAST)
|
721 | output(EXIT, "error: wrong configuration!\n");
|
722 |
|
723 | while ( (c = getopt(argc, argv, "abcpovsht:k:d:i:r")) != -1 ) { // check options
|
724 | switch (c) {
|
725 | case 'o':
|
726 | g_fp_out=NULL;
|
727 | break;
|
728 | case 'a':
|
729 | bAlign=1;
|
730 | break;
|
731 | case 'b':
|
732 | bBoot=1;
|
733 | break;
|
734 | case 'c':
|
735 | bZero=1;
|
736 | break;
|
737 | case 'p':
|
738 | bPoint=1;
|
739 | break;
|
740 | case 'i':
|
741 | sscanf(optarg, "%lf", &dTmp);
|
742 | g_iCount=(int)(STANDARD_MEASURE_FREQUENCY*dTmp+0.5);
|
743 | break;
|
744 | case 't':
|
745 | sscanf(optarg, "%lf", &dTmp);
|
746 | g_iPkt_max=(int)(STANDARD_MEASURE_FREQUENCY*dTmp+0.5);
|
747 | break;
|
748 | case 'k':
|
749 | for (i=0; i<sizeof(g_sTokenlist)/sizeof(g_sTokenlist[0]); i++)
|
750 | if (!strncmp(g_sTokenlist[i].name, optarg, strlen(optarg)))
|
751 | break;
|
752 | if (i<sizeof(g_sTokenlist)/sizeof(g_sTokenlist[0]))
|
753 | iToken=i;
|
754 | else
|
755 | output(EXIT, "error: command not found!\n");
|
756 | break;
|
757 | case 'r':
|
758 | g_iReeval=1;
|
759 | break;
|
760 | case 'd':
|
761 | sscanf(optarg, "%d", &g_iDbgLevel);
|
762 | break;
|
763 | // last options
|
764 | case 'v':
|
765 | case 'h':
|
766 | default :
|
767 | output(ALL, "Version %s\n", "v0.67");
|
768 | if (c == 'v') return(0);
|
769 | output(ALL, "%s options:\n", "reni");
|
770 | output(ALL, " -h print this Help text\n");
|
771 | output(ALL, " -v print Version\n");
|
772 | output(ALL, " -o write Output to stdout instead of out.txt\n");
|
773 | output(ALL, " -t # measuring-Time # sec [0.05]\n");
|
774 | output(ALL, " -i # time-step-Interval # sec [0.001] (fit for possible values)\n");
|
775 | output(ALL, " -k # direct execution of dx10 toKen # [none]\n");
|
776 | output(ALL, " -a Align intensity (signal strength <17%:too low, <48%:low)\n");
|
777 | output(ALL, " -p measure one static Point\n");
|
778 | output(ALL, " -b Boot laser (red LED)\n");
|
779 | output(ALL, " -c initialize Counter (set zero)\n");
|
780 | output(ALL, " -r Reevaluate last action\n");
|
781 | output(ALL, " -d # Debugging level\n");
|
782 | return(0);
|
783 | }
|
784 | }
|
785 | g_iInterrupt0x81_index_write=0;
|
786 | g_iInterrupt0x81_index_read=0;
|
787 |
|
788 | g_iPkt_max=g_iPkt_max/g_iCount+1;
|
789 |
|
790 | if (g_iReeval) {
|
791 | char sLine[512];
|
792 | g_fp_log=fopen("dx10.log","r");
|
793 | fgets(sLine, 512, g_fp_log); // read first line with command line
|
794 | } else {
|
795 | g_fp_log=fopen("dx10.log","a");
|
796 | fprintf(g_fp_log, "#%s ", "reni");
|
797 | for(i=1; i<argc; i++)
|
798 | fprintf(g_fp_log, "%s ", argv[i]);
|
799 | fprintf(g_fp_log, "\n");
|
800 |
|
801 | msec(); // init time measure
|
802 |
|
803 | usb_init(); // initialize the library
|
804 | usb_find_busses(); // find all buses
|
805 | usb_find_devices(); // find all connected devices
|
806 |
|
807 | if(!(g_Dev = open_dev()))
|
808 | output(EXIT, "error: device not found!\nPlease plug in dx10 via USB.\n");
|
809 |
|
810 | if(usb_set_configuration(g_Dev, 1) < 0)
|
811 | output(EXIT, "error: setting config 1 failed\n");
|
812 |
|
813 | if(usb_claim_interface(g_Dev, 0) < 0) //-- URB_FUNCTION_SELECT_CONFIGURATION
|
814 | output(EXIT, "error: claiming interface 0 failed\n");
|
815 |
|
816 | if (usb_clear_halt(g_Dev, 0x81) < 0) //-- URB_FUNCTION_RESET_PIPE
|
817 | output(EXIT, "error: reset%s\n", usb_strerror());
|
818 |
|
819 | g_bInterrupt=1;
|
820 | int dummy;
|
821 | _beginthread( interrupt_routine, 0, &dummy ); // start a new thread
|
822 | }
|
823 |
|
824 | //
|
825 | // booting the laser
|
826 | //
|
827 | if (bBoot==1) { // initialize
|
828 | unsigned short iAnswer[32];
|
829 | int iAns;
|
830 | iAns=command(DOWN_Init8020, iAnswer);
|
831 | if ((iAns==2)&&(iAnswer[0]!=0x8000)&&(iAnswer[1]!=0x8020))
|
832 | output(EXIT, "ERROR: ret 8020\n");
|
833 | output(ALL, "Waiting for green LED ... "); fflush(stdout);
|
834 | if (!g_iReeval)
|
835 | Sleep(1000);
|
836 | for (i=0; i<4; i++) {
|
837 | iAns=command(DOWN_Clear, iAnswer);
|
838 | if ((iAns==2)&&(iAnswer[0]!=0x8000)&&(iAnswer[1]!=0x8011))
|
839 | output(EXIT, "ERROR: ret 8011 %d\n", i);
|
840 | }
|
841 | iAns=command(DOWN_Initial, iAnswer); // first init (no 00e1, not 00xx)
|
842 | iAns=command(DOWN_Initial, iAnswer); // second init
|
843 | for (i=0; i<BOOTWAITCYCLES; i++) { // wait for green laser-led
|
844 | Sleep(500);
|
845 | iAns=command(DOWN_Measure, iAnswer);
|
846 | if (iAnswer[11]==0)
|
847 | i=BOOTWAITCYCLES*2;
|
848 | }
|
849 | if (i<BOOTWAITCYCLES*2) // check for timeout
|
850 | output(EXIT, "ERROR: waiting too long for green\nPerhaps you have to wait for warming up the laser.");
|
851 | iAns=command(DOWN_Zerosta, iAnswer); // zero static value
|
852 | iAns=command(DOWN_Zerodyn, iAnswer); // zero dynamic value
|
853 | output(ALL, " finished!\n");
|
854 |
|
855 | //
|
856 | // show intensity to align laser
|
857 | //
|
858 | } else if (bAlign) { // show intensity
|
859 | unsigned short iAnswer[32];
|
860 | int iAns;
|
861 | int iIntensity;
|
862 | double dIntensity;
|
863 | while (1) {
|
864 | char sBar[] =" . . . . . . . . . . . . . . . . . . . . . . . . . .";
|
865 | iAns=command(DOWN_Measure, iAnswer);
|
866 | iIntensity=evaluate_static(iAns, iAnswer, 2);
|
867 | if (iIntensity > 26)
|
868 | iIntensity = 26;
|
869 | dIntensity=iIntensity/26.0*100.0; // in percent => too low < 15%, low < 46%
|
870 | output(ALL, "%3.0f ", dIntensity);
|
871 | if (iIntensity<=4) {
|
872 | for(i=0; i<iIntensity*2; i++)
|
873 | sBar[i] = '-';
|
874 | }else if (iIntensity<=12) {
|
875 | for(i=0; i<iIntensity*2; i++)
|
876 | sBar[i] = '~';
|
877 | }else{
|
878 | for(i=0; i<iIntensity*2; i++)
|
879 | sBar[i] = '+';
|
880 | }
|
881 | sBar[ 4*2-1] = '|';
|
882 | sBar[12*2-1] = '|';
|
883 | sBar[26*2 ] = 0;
|
884 | output(ALL, "%s\n", sBar);
|
885 | fflush(stdout);
|
886 | if ( (GetAsyncKeyState(VK_LCONTROL)) || // break this loop with Ctrl
|
887 | (GetAsyncKeyState(VK_RCONTROL)) ) break;
|
888 | Sleep(100);
|
889 | }
|
890 |
|
891 | //
|
892 | // one command for testing
|
893 | //
|
894 | } else if (iToken>=0) {
|
895 | int iAns;
|
896 | unsigned short iAnswer[32];
|
897 | output(DBG2, "one command: %s\n", g_sTokenlist[iToken].name);
|
898 | iAns=command(iToken, iAnswer);
|
899 | evaluate_static(iAns, iAnswer, 1);
|
900 |
|
901 | //
|
902 | // measure one static point
|
903 | //
|
904 | } else if (bPoint) { //
|
905 | unsigned short iAnswer[32];
|
906 | int iAns;
|
907 | output(DBG2, "one point\n", g_sTokenlist[iToken].name);
|
908 | iAns=command(DOWN_Measure, iAnswer);
|
909 | evaluate_static(iAns, iAnswer, 1);
|
910 |
|
911 | //
|
912 | // zero the laser for static and dynamic measurement
|
913 | //
|
914 | } else if (bZero) { // zero static+dynamic
|
915 | unsigned short iAnswer[32];
|
916 | int iAns;
|
917 | output(DBG2, "zero static+dynamic\n");
|
918 | iAns=command(DOWN_Zerosta, iAnswer); // zero static value
|
919 | iAns=command(DOWN_Zerodyn, iAnswer); // zero dynamic value
|
920 |
|
921 | //
|
922 | // standard dynamical measurement
|
923 | //
|
924 | } else { // measure dynamical
|
925 | unsigned short iAnswer[32];
|
926 | int iAns, iFirstvalue;
|
927 | output(DBG2, "measure dynamic\n");
|
928 | if (!g_iReeval) { // FUNCTION_LOAD_PIPE
|
929 | if (usb_clear_halt(g_Dev, 0x82) < 0)
|
930 | output(EXIT, "error: reset 82%s\n", usb_strerror());
|
931 | for(i=0; i<MAX_STREAM0x82; i++) // do once for setup
|
932 | if (usb_bulk_setup_async(g_Dev, &g_sData0x82[i].async, 0x82) < 0)
|
933 | output(EXIT, "error usb_bulk_setup_async:\n%s\n", usb_strerror());
|
934 | for(i=0; i<MAX_STREAM0x82; i++) // submit this transfer and returns immediately
|
935 | if (usb_submit_async(g_sData0x82[i].async, (char*)&g_sData0x82[i].buff[0], BUFFLEN0x82) < 0)
|
936 | output(EXIT, "error usb_submit_async:\n%s\n", usb_strerror());
|
937 | }
|
938 | Sleep(0);
|
939 | iAns=command(DOWN_Measure, iAnswer);
|
940 | iFirstvalue=evaluate_static(iAns, iAnswer, 0);
|
941 | iAns=command(DOWN_MSta8030, iAnswer);
|
942 | measure_dynamic(iFirstvalue);
|
943 | iAns=command(DOWN_MEnd8040, iAnswer);
|
944 | if (!g_iReeval)
|
945 | if (usb_resetep(g_Dev, 0x82) < 0)
|
946 | output(EXIT, "error: abort/reset 82%s\n", usb_strerror());
|
947 | iAns=command(DOWN_Measure, iAnswer); // do not skip this! system hangs sometimes... reason unknown?
|
948 | evaluate_static(iAns, iAnswer, 0);
|
949 | }
|
950 |
|
951 | if (!g_iReeval) {
|
952 | g_bInterrupt=0;
|
953 | if (usb_resetep(g_Dev, 0x81) < 0)
|
954 | output(EXIT, "error: abort/reset 81%s\n", usb_strerror());
|
955 | if (usb_resetep(g_Dev, 0x82) < 0)
|
956 | output(EXIT, "error: abort/reset 82%s\n", usb_strerror());
|
957 |
|
958 | usb_release_interface(g_Dev, 0);
|
959 | usb_close(g_Dev);
|
960 | }
|
961 | if (g_fp_out) {
|
962 | fclose(g_fp_out);
|
963 | remove("out.txt");
|
964 | rename("_out.txt", "out.txt");
|
965 | }
|
966 | fclose(g_fp_log);
|
967 |
|
968 | if ( (g_iWarning) || (g_iDbgLevel))
|
969 | output(ALL, "warnings: %d\n", g_iWarning);
|
970 |
|
971 | return 0;
|
972 | }
|