1 | #include <usb.h>
|
2 | #include <stdio.h>
|
3 | #include <getopt.h> // needed for getopt
|
4 | #include "version.h"
|
5 |
|
6 | typedef struct transdata { // data from laser for one USB packet
|
7 | int bAlign; // 0: distance, 1: intensity
|
8 | int n;
|
9 | long long lldata[100];
|
10 | } TransData;
|
11 |
|
12 | extern void dx10_start_seq1();
|
13 | extern void dx10_zero_seq234();
|
14 | extern void dx10_pre_loop_seq2();
|
15 | extern int dx10_read_loop_seq3();
|
16 | extern void dx10_post_loop_seq4();
|
17 | extern void dx10_end_seq5();
|
18 | extern int dx10_eval(int len, int iStep, TransData *transdata);
|
19 |
|
20 | extern void xl80_start_seq1();
|
21 | extern void xl80_zero_seq234();
|
22 | extern void xl80_pre_loop_seq2();
|
23 | extern int xl80_read_loop_seq3();
|
24 | extern void xl80_post_loop_seq4();
|
25 | extern void xl80_end_seq5();
|
26 | extern int xl80_eval(int len, int iStep, TransData *transdata);
|
27 |
|
28 | #define WARMINGUP 0x01
|
29 | #define NO_BEAM 0x02
|
30 | #define INTERRUPTED_BEAM 0x04
|
31 | #define KEYBOARD 0x08
|
32 |
|
33 | //only this file////////////////////////////////////////////////
|
34 |
|
35 | // this device's vendor and product id
|
36 | #define VID_RENISHAW 0x0837 // 0x0837: Renishaw
|
37 | #define PID_DX10 0x000b // 0x000b: DX-10 adaptor with ML-10
|
38 | #define PID_XL80 0x0012 // 0x0012: XL-80
|
39 |
|
40 | int g_iDbgLevel;
|
41 | usb_dev_handle *g_Dev = NULL; // the device handle
|
42 | int g_iFlags=0;
|
43 |
|
44 | void abort(const char *fmt, ...)
|
45 | {
|
46 | va_list ap;
|
47 | char string[4096];
|
48 |
|
49 | va_start(ap, fmt);
|
50 | vsprintf(string, fmt, ap);
|
51 | printf("%s", string);
|
52 | fflush(stdout);
|
53 | va_end(ap);
|
54 | exit(-1);
|
55 | }
|
56 |
|
57 | usb_dev_handle *open_dev_dx10(void)
|
58 | {
|
59 | struct usb_bus *bus;
|
60 | struct usb_device *dev;
|
61 |
|
62 | for(bus = usb_get_busses(); bus; bus = bus->next)
|
63 | for(dev = bus->devices; dev; dev = dev->next)
|
64 | if(dev->descriptor.idVendor == VID_RENISHAW && dev->descriptor.idProduct == PID_DX10)
|
65 | return usb_open(dev);
|
66 | return NULL;
|
67 | }
|
68 |
|
69 | usb_dev_handle *open_dev_xl80(void)
|
70 | {
|
71 | struct usb_bus *bus;
|
72 | struct usb_device *dev;
|
73 |
|
74 | for(bus = usb_get_busses(); bus; bus = bus->next)
|
75 | for(dev = bus->devices; dev; dev = dev->next)
|
76 | if(dev->descriptor.idVendor == VID_RENISHAW && dev->descriptor.idProduct == PID_XL80)
|
77 | return usb_open(dev);
|
78 | return NULL;
|
79 | }
|
80 |
|
81 | char* bargraph(int percent)
|
82 | {
|
83 | static char sBar[50+4]; // 50 chars for 100%
|
84 | int j;
|
85 | strcpy(sBar, " . . . . . . . . . . . . . . . . . . . . . . . . .");
|
86 | if (percent > 100)
|
87 | percent = 100;
|
88 | if (percent<=16) { // in percent => too low < 16%, low < 50%
|
89 | for(j=0; j<percent/2; j++)
|
90 | sBar[j] = '-';
|
91 | }else if (percent<=50) {
|
92 | for(j=0; j<percent/2; j++)
|
93 | sBar[j] = '~';
|
94 | }else{
|
95 | for(j=0; j<percent/2; j++)
|
96 | sBar[j] = '+';
|
97 | }
|
98 | sBar[ 16/2] = '|';
|
99 | sBar[ 50/2] = '|';
|
100 | sBar[100/2] = 0;
|
101 | return sBar;
|
102 | }
|
103 |
|
104 | #define STANDARD_MEASURE_FREQUENCY 5000
|
105 | #define WAVELENGTH_IN_MM 0.000632818840000 // ~633nm
|
106 | #define DEFAULT_DURATION 0.05 // in sec
|
107 | #define DEFAULT_TIMESTEP 0.001 // in sec
|
108 |
|
109 | int main(int argc, char**argv)
|
110 | {
|
111 | int c, len, nmbr, i;
|
112 | char bZero=0;
|
113 | char bOut=0;
|
114 | char sDevice[32]="";
|
115 | double time=0;
|
116 | double mode_factor=1.0;
|
117 | double endtime=DEFAULT_DURATION;
|
118 | double dTmp;
|
119 | char sOutFile[1024];
|
120 | int iStep=(int)(0.5+STANDARD_MEASURE_FREQUENCY*DEFAULT_TIMESTEP); // default for -i0.001
|
121 | FILE *fp;
|
122 | TransData transdata;
|
123 | transdata.bAlign=0;
|
124 | char sDevices[2][32];
|
125 | int iDevices=0;
|
126 |
|
127 | void (*usb_seq1)();
|
128 | void (*usb_seq2)();
|
129 | int (*usb_seq3)();
|
130 | void (*usb_seq4)();
|
131 | void (*usb_seq5)();
|
132 | void (*usb_seq234)();
|
133 | int (*usb_eval)(int len, int iStep, TransData *transdata);
|
134 |
|
135 |
|
136 |
|
137 | while ( (c = getopt(argc, argv, "acsd:t:i:o:m:vh")) != -1 ) { // check options
|
138 | switch (c) {
|
139 | case 'a':
|
140 | transdata.bAlign=1;
|
141 | break;
|
142 | case 'd':
|
143 | strcpy(sDevice, optarg);
|
144 | break;
|
145 | case 'c':
|
146 | bZero=1;
|
147 | break;
|
148 | case 't':
|
149 | sscanf(optarg, "%lf", &endtime);
|
150 | break;
|
151 | case 'i':
|
152 | sscanf(optarg, "%lf", &dTmp);
|
153 | iStep=(int)(0.5+STANDARD_MEASURE_FREQUENCY*dTmp);
|
154 | break;
|
155 | case 'm':
|
156 | if (optarg[0]=='a') mode_factor=33333.3333;
|
157 | if (optarg[0]=='p') mode_factor=0.5;
|
158 | if (optarg[0]=='w') mode_factor=44.248;
|
159 | break;
|
160 | case 'o':
|
161 | strcpy(sOutFile, optarg);
|
162 | bOut=1;
|
163 | break;
|
164 |
|
165 | case 'v':
|
166 | case 'h':
|
167 | default :
|
168 | printf("Version %s", "v0.77");
|
169 | if (c == 'v') return(0);
|
170 | printf("\n%s options:", "reni");
|
171 | printf("\n(no option) measure dynamic profile with given t- and i-parameters");
|
172 | printf("\n -h print this Help text");
|
173 | printf("\n -v print Version");
|
174 | printf("\n -d # use Device # (dx-10 or xl-80)");
|
175 | printf("\n -o # write Output to file # [stdout]");
|
176 | printf("\n -t # measuring-Time # sec [%g]", DEFAULT_DURATION);
|
177 | printf("\n -i # time-step-Interval # sec [%g] (fit for possible values)", DEFAULT_TIMESTEP);
|
178 | printf("\n -a Align intensity (signal strength <16%:too low, <50%:low)");
|
179 | printf("\n -c initialize Counter and Clear errors (set zero)");
|
180 | printf("\n -m # Mode listed below: [s],a,p,w");
|
181 | printf("\n The given values have to be multiplied with a factor to get a result:");
|
182 | printf("\n # (S)tandard linear reflector * 1.0 => mm");
|
183 | printf("\n # (A)ngular double reflector * 33333.3 => µm/m");
|
184 | printf("\n # (P)lane mirror with two beams * 0.5 => mm");
|
185 | printf("\n # (W)ollaston prisma short * 44.248 => mm");
|
186 | printf("\n");
|
187 | return(0);
|
188 | }
|
189 | }
|
190 |
|
191 | usb_init(); // initialize the library
|
192 | usb_find_busses(); // find all buses
|
193 | usb_find_devices(); // find all connected devices [GET_DESCRIPTOR_FROM_DEVICE:80 06 0100 0000 0012
|
194 | // GET_DESCRIPTOR_FROM_DEVICE:80 06 0200 0000 0008
|
195 | // GET_DESCRIPTOR_FROM_DEVICE:80 06 0200 0000 00xx]
|
196 | // test all possible devices and build a list
|
197 | if (open_dev_dx10())
|
198 | strcpy(&sDevices[iDevices++][0], "dx-10");
|
199 | if (open_dev_xl80())
|
200 | strcpy(&sDevices[iDevices++][0], "xl-80");
|
201 |
|
202 | if (iDevices==0)
|
203 | abort("\nERROR: no device not found!\nPlease plug in one USB-device");
|
204 |
|
205 | if (strlen(sDevice)) { // sDevice chosen
|
206 | for(i=0; i<iDevices; i++) {
|
207 | if (!strncmp(sDevice, &sDevices[i][0], 1)) // check only 1 character
|
208 | break;
|
209 | }
|
210 | if (i>=iDevices) { // not found
|
211 | for(i=0; i<iDevices; i++)
|
212 | printf("%d: %s\n", i, &sDevices[i][0]);
|
213 | abort("\nERROR: Please choose one device from list with -d option");
|
214 | }
|
215 | } else { // no sDevice chosen
|
216 | if (iDevices==1) // only one sDevice exists
|
217 | i=0;
|
218 | else { // more sDevice exist
|
219 | for(i=0; i<iDevices; i++)
|
220 | printf("%d: %s\n", i, &sDevices[i][0]);
|
221 | abort("\nERROR: Please choose one device from list with -d option.");
|
222 | }
|
223 | }
|
224 |
|
225 | // bind functions to the chosen device
|
226 | if (!strcmp(&sDevices[i][0], "dx-10")) {
|
227 | if (!(g_Dev = open_dev_dx10()))
|
228 | abort("\nERROR: device not found!\nPlease plug in USB.");
|
229 | usb_seq1=dx10_start_seq1;
|
230 | usb_seq2=dx10_pre_loop_seq2;
|
231 | usb_seq3=dx10_read_loop_seq3;
|
232 | usb_seq4=dx10_post_loop_seq4;
|
233 | usb_seq5=dx10_end_seq5;
|
234 | usb_seq234=dx10_zero_seq234;
|
235 | usb_eval=dx10_eval;
|
236 | } else if (!strcmp(&sDevices[i][0], "xl-80")) {
|
237 | if (!(g_Dev = open_dev_xl80()))
|
238 | abort("\nERROR: device not found!\nPlease plug in USB.");
|
239 | usb_seq1=xl80_start_seq1;
|
240 | usb_seq2=xl80_pre_loop_seq2;
|
241 | usb_seq3=xl80_read_loop_seq3;
|
242 | usb_seq4=xl80_post_loop_seq4;
|
243 | usb_seq5=xl80_end_seq5;
|
244 | usb_seq234=xl80_zero_seq234;
|
245 | usb_eval=xl80_eval;
|
246 | } else
|
247 | abort("\nERROR: device not found!\nPlease plug in USB..");
|
248 |
|
249 | // unconfigure first before configure
|
250 | if (usb_set_configuration(g_Dev, 0) < 0) // select configuration [GET_DESCRIPTOR_FROM_DEVICE:80 06 0100 0000 0012
|
251 | abort("\nERROR: setting config 0 failed"); // GET_DESCRIPTOR_FROM_DEVICE:80 06 0200 0000 0009
|
252 | // GET_DESCRIPTOR_FROM_DEVICE:80 06 0200 0000 00xx
|
253 | // SELECT_CONFIGURATION:(unconfigured)]
|
254 |
|
255 | if (usb_set_configuration(g_Dev, 1) < 0) // select configuration [GET_DESCRIPTOR_FROM_DEVICE:80 06 0100 0000 0012
|
256 | abort("\nERROR: setting config 1 failed"); // GET_DESCRIPTOR_FROM_DEVICE:80 06 0200 0000 0009
|
257 | // GET_DESCRIPTOR_FROM_DEVICE:80 06 0200 0000 00xx
|
258 | // SELECT_CONFIGURATION:(configured)]
|
259 |
|
260 | if (usb_claim_interface(g_Dev, 0) < 0)
|
261 | abort("\nERROR: claiming interface 0 failed");
|
262 |
|
263 | if (transdata.bAlign) { // change parameters for alignment
|
264 | endtime=60*10; // maximum 10 minutes alignment
|
265 | iStep=(int)(0.5+STANDARD_MEASURE_FREQUENCY*0.1); // alignment always with step of 0.1 sec
|
266 | }
|
267 | if (bOut)
|
268 | fp=fopen(sOutFile, "w");
|
269 | transdata.n=iStep-1;
|
270 |
|
271 | usb_seq1();
|
272 | if (bZero) { // --> either set laser to zero
|
273 | usb_seq234();
|
274 | } else { // --> or measure dynamically
|
275 |
|
276 | // We read all USB-packages which have the data for the maximum of resolution (5MHz).
|
277 | // The procedure "eval" will give back (in transdata) only the data in THAT resolution, which will be displayed (every iStep data point).
|
278 | // In the measuring loop here, all data from transdata will be displayed.
|
279 |
|
280 | usb_seq2();
|
281 | time=1.0/STANDARD_MEASURE_FREQUENCY*iStep-0.000001;
|
282 | do { // measuring loop
|
283 | len=usb_seq3(); // read complete USB-package (len is lenght of this package)
|
284 | nmbr=usb_eval(len, iStep, &transdata); // fill every iStep point in transdata (nmbr is number of points to output)
|
285 | for (i=0; (i<nmbr) && (time<=endtime); i++) {
|
286 | if (transdata.bAlign==0) {
|
287 | if (bOut)
|
288 | fprintf(fp, "%.8f\n", transdata.lldata[i]*WAVELENGTH_IN_MM/32768*mode_factor);// 32768: interpolation
|
289 | else
|
290 | printf("%.4f %.8f\n", time, transdata.lldata[i]*WAVELENGTH_IN_MM/32768*mode_factor);// 32768: interpolation
|
291 | } else
|
292 | printf("%3d%% %s\n", (unsigned char)transdata.lldata[i], bargraph((unsigned char)transdata.lldata[i]));
|
293 | fflush(stdout);
|
294 | time+=1.0/STANDARD_MEASURE_FREQUENCY*iStep;
|
295 | }
|
296 | if (transdata.bAlign) {
|
297 | g_iFlags=0; // for alignment ignore all earlier errors
|
298 | if ( GetAsyncKeyState(VK_LCONTROL) ) // for alignment break also with left control key
|
299 | g_iFlags=g_iFlags|KEYBOARD;
|
300 | }
|
301 | if ( GetAsyncKeyState(VK_RCONTROL) ) // always break with right control key
|
302 | g_iFlags=g_iFlags|KEYBOARD;
|
303 | } while( (time<endtime)&&(g_iFlags==0) );
|
304 | usb_seq4();
|
305 | }
|
306 | usb_seq5();
|
307 |
|
308 | usb_release_interface(g_Dev, 0);
|
309 | usb_close(g_Dev);
|
310 |
|
311 | if (bOut)
|
312 | fclose(fp);
|
313 |
|
314 | if (g_iFlags&WARMINGUP)
|
315 | printf("ERROR: Warming up\n");
|
316 | else {
|
317 | if (g_iFlags&NO_BEAM)
|
318 | printf("ERROR: No beam at all\n");
|
319 | else if (g_iFlags&INTERRUPTED_BEAM)
|
320 | printf("ERROR: Interrupted beam, please use -c option\n");
|
321 | }
|
322 | return 0;
|
323 | }
|