| gclib 2.0.7 Communications API for Galil controllers and PLCs |

gcl_datarecord.cpp
Go to the documentation of this file.
1
4 #include "gcl_galil.h"
5 using namespace std;
6
7 vector<std::string> Galil::sources()
8 {
9 vector<std::string> s;
10 for (auto it = d->map.begin(); it != d->map.end(); ++it)
11 s.push_back(it->first);
12
13 std::sort(s.begin(), s.end());
14
15 return s;
16 }
17
18 void Galil::recordsStart(double period_ms)
19 {
20 ec(GRecordRate(d->g, period_ms));
21 }
22
23 vector<char> Galil::record(const std::string& method)
24 {
25 GDataRecord record;
26 ec(GRecord(d->g, &record, method == "QR" ? G_QR : G_DR));
27 vector <char> record_vector;
28 for (int i = 0; i < sizeof(GDataRecord); i++)
29 record_vector.push_back(record.byte_array[i]);
30
31 return record_vector;
32 }
33
34 double Galil::sourceValue(const std::vector<char>& record, const std::string& source)
35 {
36
37 try
38 {
39 const Source& s = d->map.at(source); //use at() function so silent insert does not occur if bad source string is used.
40 int return_value = 0;
41 if (s.type[0] == 'U') //unsigned
42 switch (s.type[1])
43 {
44 case 'B': return_value = *(unsigned char*)(&record[0] + s.byte); break;
45 case 'W': return_value = *(unsigned short*)(&record[0] + s.byte); break;
46 case 'L': return_value = *(unsigned int*)(&record[0] + s.byte); break;
47 }
48 else //s.type[0] == 'S' //signed
49 switch (s.type[1])
50 {
51 case 'B': return_value = *(char*)(&record[0] + s.byte); break;
52 case 'W': return_value = *(short*)(&record[0] + s.byte); break;
53 case 'L': return_value = *(int*)(&record[0] + s.byte); break;
54 }
55
56 if (s.bit >= 0) //this is a bit field
57 {
58 bool bTRUE = s.scale > 0; //invert logic if scale is <= 0
59 return return_value & (1 << s.bit) ? bTRUE : !bTRUE; //check the bit
60 }
61 else
62 return (return_value / s.scale) + s.offset;
63
64 }
65 catch (const std::out_of_range& e) //bad source
66 {
67 (void)e; //unused
68 return 0.0;
69 }
70
71 }
72
73 string Galil::source(const std::string& field, const std::string& source)
74 {
75 try
76 {
77 const Source& s = d->map.at(source); //use at() function so silent insert does not occur if bad source string is used.
78 if (field == "Description")
79 return s.description;
80
81 if (field == "Units")
82 return s.units;
83
84 if (field == "Scale")
85 return to_string(s.scale);
86
87 if (field == "Offset")
88 return to_string(s.offset);
89
90 return ""; //no matches
91 }
92 catch (const std::out_of_range& e) //bad source
93 {
94 (void)e;//unused
95 return ""; //no matches
96 }
97
98 }
99
100 void Galil::setSource(const std::string& field, const std::string& source, const std::string& to)
101 {
102 try
103 {
104 Source& s = d->map.at(source); //use at() function so silent insert does not occur if bad source string is used.
105 if (field == "Description")
106 {
107 s.description = to;
108 return;
109 }
110
111 if (field == "Units")
112 {
113 s.units = to;
114 return;
115 }
116
117 if (field == "Scale")
118 {
119 s.scale = stod(to);
120 return;
121 }
122
123 if (field == "Offset")
124 {
125 s.offset = stod(to);
126 return;
127 }
128 }
129 catch (const std::out_of_range& e) //bad source
130 {
131 (void)e;//unused
132 return;
133 }
134 }
135
136
137
138 void GalilPrivate::InitializeDataRecord()
139 {
140 map.clear(); //clear the map if thre is anything in it
141
142 //infer data record structure from QZ
143 string qz = q->command("QZ");
144 vector<int> qz_split;
145 size_t start = 0;
146 for (size_t i = 0; i < qz.length(); i++) //ad hoc split
147 {
148 if (qz[i] == ',')
149 {
150 qz_split.push_back(stoi(qz.substr(start, i - start)));
151 start = i + 1; //jump over delim
152 continue;
153 }
154
155 if (i == qz.length() - 1) //last token
156 {
157 qz_split.push_back(stoi(qz.substr(start)));
158 break;
159 }
160 }
161
162 if (4 != qz_split.size()) return; //parsing error or bad response
163
164 int axes = qz_split[0];
165
166
167 //weed out PCI cards
168 string rv = q->command("\x12\x16"); //^R^V
169 if (rv.find("DMC18") != string::npos) //PCI-based card
170 {
171 if (rv.length() >= 7)
172 {
173 if (rv[6] == '6') return Init1806(axes);
174 if (rv[6] == '0') return Init1800(axes, false);
175 if (rv[6] == '2') return Init1800(axes, true);
176 }
177 }
178
179 int gen_status = qz_split[1];
180 if (gen_status == 18) return Init30010(rv.find("DMC31") != string::npos); // DMC300x0 returns 1 18 16 36, search for "DMC31" in ^R^V to determine 16bit ADC
181
182 int axis_block = qz_split[3]; //size of the axis block data in data record
183 if (axis_block == 36) return Init4000(axes); //DMC40x0/DMC41x3/DMC50000 8 52 26 36
184 if (axis_block == 28) return Init2103(axes); //DMC14x5/2xxx/ 8 24 16 28 //also Optima
185
186 //if here, should be an RIO
187 if (axis_block != 0) return; //RIO has a 0 in the axis block data
188
189 //Determine the RIO type
190 int io_block = qz_split[2];
191
192 //RIO-47300 has 4 extra bytes in the I/O block
193 bool rio3 = ((io_block == 52) || (io_block == 60) || (io_block == 68)); // RIO-47300 Standard, with Exteneded I/O, with Quad/Biss/SSi
194
195 //SER tacks 4 longs on the end of the data record (4 encoders)
196 bool rioser = ((io_block == 64) || (io_block == 68)); // 471x2,472x2 OR 47300 with SER
197
198 //Extended I/O tacks 8 bytes on the end of the data rrecord, three bytes of each of I/O, one padding for each
199 bool rio3ex = (io_block == 60); // RIO-47300 with extended I/O. Mutually exclusive with SER
200
201
202 InitRio(rio3);
203
204 if (rio3ex) InitRio3_24Ex();
205 if (rioser) InitRioSer(rio3);
206
207 }
208
209 string GalilPrivate::ax(string prefix, int axis, string suffix)
210 {
211 return prefix + (char)('A' + axis) + suffix;
212 }
213
214 void GalilPrivate::input_bits(int byte, int num)
215 {
216 stringstream ss;
217
218 for (int i = 0; i < 8; i++)
219 {
220 ss << "@IN[";
221 ss << setw(2) << setfill('0') << right << num;
222 ss << "]";
223 map[ss.str()] = Source(byte, "UB", i, "Boolean", "Digital input " + to_string(num));
224 ss.str("");
225 num++;
226 }
227 }
228
229 void GalilPrivate::output_bits(int byte, int num)
230 {
231 stringstream ss;
232
233 for (int i = 0; i < 8; i++)
234 {
235 ss << "@OUT[";
236 ss << setw(2) << setfill('0') << right << num;
237 ss << "]";
238 map[ss.str()] = Source(byte, "UB", i, "Boolean", "Digital output " + to_string(num));
239 ss.str("");
240 num++;
241 }
242 }
243
244 void GalilPrivate::aq_analog(int byte, int input_num)
245 {
246 //When analog voltage decoding depends upon AQ setting.
247 string type; //for interpreting analog as signed/unsigned
248 double divisor; //for dividing ADC counts to calc volts
249 int val;
250 string command = "MG{Z10.0}_AQ" + to_string(input_num);
251 if (GCmdI(g, command.c_str(), &val) == G_NO_ERROR) //don't add analog if error on AQ
252 {
253 switch (val)
254 {
255 case 1: case -1: divisor = 32768.0 / 5; type = "SW"; break; // -5 to 5 V -32768 to 32767
256 case 3: case -3: divisor = 65536.0 / 5; type = "UW"; break; // 0 to 5 V 0 to 65535
257 case 4: case -4: divisor = 65536.0 / 10; type = "UW"; break; // 0 to 10 V 0 to 65535
258 case 2: case -2: default: //AQ 2 is the default value
259 divisor = 32768.0 / 10; type = "SW"; break; // -10 to 10 V -32768 to 32767
260 }
261 map["@AN[" + to_string(input_num + 1) + "]"] = Source(byte, type, -1, "V", "Analog input " + to_string(input_num), divisor);
262 }
263 }
264
265 void GalilPrivate::dq_analog(int byte, int input_num)
266 {
267 //When analog voltage decoding depends upon DQ setting.
268 string type; //for interpreting analog as signed/unsigned
269 double divisor; //for dividing ADC counts to calc volts
270 int val;
271 string command = "MG{Z10.0}_DQ" + to_string(input_num);
272 if (GCmdI(g, command.c_str(), &val) == G_NO_ERROR) //don't add analog if error on AQ
273 {
274 switch (val)
275 {
276 case 3: divisor = 32768.0 / 5; type = "SW"; break; // -5 to 5 V -32768 to 32767
277 case 1: divisor = 65536.0 / 5; type = "UW"; break; // 0 to 5 V 0 to 65535
278 case 2: divisor = 65536.0 / 10; type = "UW"; break; // 0 to 10 V 0 to 65535
279 case 4: default: //DQ 4 is the default value
280 divisor = 32768.0 / 10; type = "SW"; break; // -10 to 10 V -32768 to 32767
281 }
282 map["@AO[" + to_string(input_num + 1) + "]"] = Source(byte, type, -1, "V", "Analog output " + to_string(input_num), divisor);
283 }
284 }
285
286 void GalilPrivate::Init4000(int axes)
287 {
288 //0-3 Header is ignored in GCL
289
290 map["TIME"] = Source(4, "UW", -1, "samples", "Sample counter");
291
292 //Digital Inputs
293 map["_TI0"] = Source(6, "UB", -1, "", "Digital inputs 1 to 8");
294 input_bits(6, 1);
295
296 map["_TI1"] = Source(7, "UB", -1, "", "Digital inputs 9 to 16"); //TI always included
297 if (axes > 4) //9-16 depend on axes 5-8
298 input_bits(7, 9);
299
300 //Digital outputs
301 map["_OP0"] = Source(16, "UW", -1, "", "Digital outputs 1 to 16");
302 output_bits(16, 1);
303
304 if (axes > 4) //9-16 depend on axes 5-8
305 output_bits(17, 9);
306
307 //Extended I/O
308 int co = -1;
309 if (GCmdI(g, "MG_CO", &co) == G_NO_ERROR) //41x3 will ? here
310 {
311 map["_TI2"] = Source(8, "UB", -1, "", "Digital inputs 17 to 24"); //TI always included in gcl
312 map["_TI3"] = Source(9, "UB", -1, "", "Digital inputs 25 to 32");
313 map["_TI4"] = Source(10, "UB", -1, "", "Digital inputs 33 to 40");
314 map["_TI5"] = Source(11, "UB", -1, "", "Digital inputs 41 to 48");
315
316 map["_OP1"] = Source(18, "UW", -1, "", "Digital outputs 17 to 32"); //OP always included in gcl
317 map["_OP2"] = Source(20, "UW", -1, "", "Digital outputs 33 to 48");
318
319 if (co & 0x00000001) //bank 2 is output
320 output_bits(18, 17);
321 else //bank 2 in input
322 input_bits(8, 17);
323
324 if (co & 0x00000002) //bank 3 is output
325 output_bits(19, 25);
326 else //bank 3 is input
327 input_bits(9, 25);
328
329 if (co & 0x00000004) //bank 4 is output
330 output_bits(20, 33);
331 else //bank 4 is input
332 input_bits(10, 33);
333
334 if (co & 0x00000008) //bank 5 is output
335 output_bits(21, 41);
336 else
337 input_bits(11, 41);
338 }
339
340 //Ethernet Handle Status
341 map["_IHA2"] = Source(42, "UB", -1, "", "Handle A Ethernet status");
342 map["_IHB2"] = Source(43, "UB", -1, "", "Handle B Ethernet status");
343 map["_IHC2"] = Source(44, "UB", -1, "", "Handle C Ethernet status");
344 map["_IHD2"] = Source(45, "UB", -1, "", "Handle D Ethernet status");
345 map["_IHE2"] = Source(46, "UB", -1, "", "Handle E Ethernet status");
346 map["_IHF2"] = Source(47, "UB", -1, "", "Handle F Ethernet status");
347 map["_IHG2"] = Source(48, "UB", -1, "", "Handle G Ethernet status");
348 map["_IHH2"] = Source(49, "UB", -1, "", "Handle H Ethernet status");
349
350 map["_TC"] = Source(50, "UB", -1, "", "Error code");
351
352 //Thread status
353 map["NO0"] = Source(51, "UB", 0, "Boolean", "Thread 0 running");
354 map["NO1"] = Source(51, "UB", 1, "Boolean", "Thread 1 running");
355 map["NO2"] = Source(51, "UB", 2, "Boolean", "Thread 2 running");
356 map["NO3"] = Source(51, "UB", 3, "Boolean", "Thread 3 running");
357 map["NO4"] = Source(51, "UB", 4, "Boolean", "Thread 4 running");
358 map["NO5"] = Source(51, "UB", 5, "Boolean", "Thread 5 running");
359 map["NO6"] = Source(51, "UB", 6, "Boolean", "Thread 6 running");
360 map["NO7"] = Source(51, "UB", 7, "Boolean", "Thread 7 running");
361
362 //Amplifier error status
363 map["TA00"] = Source(52, "UB", 0, "Boolean", "Axis A-D over current");
364 map["TA01"] = Source(52, "UB", 1, "Boolean", "Axis A-D over voltage");
365 map["TA02"] = Source(52, "UB", 2, "Boolean", "Axis A-D over temperature");
366 map["TA03"] = Source(52, "UB", 3, "Boolean", "Axis A-D under voltage");
367 map["TA04"] = Source(52, "UB", 4, "Boolean", "Axis E-H over current");
368 map["TA05"] = Source(52, "UB", 5, "Boolean", "Axis E-H over voltage");
369 map["TA06"] = Source(52, "UB", 6, "Boolean", "Axis E-H over temperature");
370 map["TA07"] = Source(52, "UB", 7, "Boolean", "Axis E-H under voltage");
371
372 map["TA1A"] = Source(53, "UB", 0, "Boolean", "Axis A hall error");
373 map["TA1B"] = Source(53, "UB", 1, "Boolean", "Axis B hall error");
374 map["TA1C"] = Source(53, "UB", 2, "Boolean", "Axis C hall error");
375 map["TA1D"] = Source(53, "UB", 3, "Boolean", "Axis D hall error");
376 map["TA1E"] = Source(53, "UB", 4, "Boolean", "Axis E hall error");
377 map["TA1F"] = Source(53, "UB", 5, "Boolean", "Axis F hall error");
378 map["TA1G"] = Source(53, "UB", 6, "Boolean", "Axis G hall error");
379 map["TA1H"] = Source(53, "UB", 7, "Boolean", "Axis H hall error");
380
381 map["TA2A"] = Source(54, "UB", 0, "Boolean", "Axis A at _TKA peak current");
382 map["TA2B"] = Source(54, "UB", 1, "Boolean", "Axis B at _TKB peak current");
383 map["TA2C"] = Source(54, "UB", 2, "Boolean", "Axis C at _TVC peak current");
384 map["TA2D"] = Source(54, "UB", 3, "Boolean", "Axis D at _TKD peak current");
385 map["TA2E"] = Source(54, "UB", 4, "Boolean", "Axis E at _TKE peak current");
386 map["TA2F"] = Source(54, "UB", 5, "Boolean", "Axis F at _TKF peak current");
387 map["TA2G"] = Source(54, "UB", 6, "Boolean", "Axis G at _TKG peak current");
388 map["TA2H"] = Source(54, "UB", 7, "Boolean", "Axis H at _TKH peak current");
389
390 map["TA3AD"] = Source(55, "UB", 0, "Boolean", "Axis A-D ELO active");
391 map["TA3EH"] = Source(55, "UB", 1, "Boolean", "Axis E-H ELO active");
392
393 //contour mode
394 map["CD"] = Source(56, "UL", -1, "segments", "Contour segment count");
395 map["_CM"] = Source(60, "UW", -1, "elements", "Contour buffer space");
396
397 //S plane
398 map["_CSS"] = Source(62, "UW", -1, "segments", "Axis S segment count");
399 map["VDS"] = Source(64, "UB", 3, "Boolean", "Axis S final deceleration");
400 map["STS"] = Source(64, "UB", 4, "Boolean", "Axis S stopping");
401 map["VSS"] = Source(64, "UB", 5, "Boolean", "Axis S slewing");
402 map["_BGS"] = Source(65, "UB", 7, "Boolean", "Axis S moving");
403 map["_AVS"] = Source(66, "SL", -1, "counts", "Axis S length");
404 map["_LMS"] = Source(70, "UW", -1, "elements", "Axis S buffer speace");
405
406 //T plane
407 map["_CST"] = Source(72, "UW", -1, "segments", "Axis T segment count");
408 map["VDT"] = Source(74, "UB", 3, "Boolean", "Axis T final deceleration");
409 map["STT"] = Source(74, "UB", 4, "Boolean", "Axis T stopping");
410 map["VST"] = Source(74, "UB", 5, "Boolean", "Axis T slewing");
411 map["_BGT"] = Source(75, "UB", 7, "Boolean", "Axis T moving");
412 map["_AVT"] = Source(76, "SL", -1, "counts", "Axis T length");
413 map["_LMT"] = Source(80, "UW", -1, "elements", "Axis T buffer speace");
414
415 //per-axis data
416 int base = 82; //start of A axis data
417 for (int i = 0; i < axes; i++)
418 {
419 map[ax("_MO", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " motor off"));
420 map[ax("HM", i, "3")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " found index"));
421 map[ax("_AL", i, "")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " latch armed"));
422 map[ax("DC", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " began deceleration"));
423 map[ax("ST", i, "")] = Source(base, "UW", 4, "Boolean", ax("Axis ", i, " began stop"));
424 map[ax("SP", i, "")] = Source(base, "UW", 5, "Boolean", ax("Axis ", i, " began slew"));
425 map[ax("CM", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " in contour mode"));
426 map[ax("JG", i, "-")] = Source(base, "UW", 7, "Boolean", ax("Axis ", i, " negative move"));
427 ++base; //83
428 map[ax("VM", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " in VM or LI mode"));
429 map[ax("HM", i, "2")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " finding index"));
430 map[ax("HM", i, "1")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " coming off home switch"));
431 map[ax("HM", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " home command issued"));
432 map[ax("FE", i, "")] = Source(base, "UW", 4, "Boolean", ax("Axis ", i, " find edge issued"));
433 map[ax("PA", i, "")] = Source(base, "UW", 5, "Boolean", ax("Axis ", i, " in PA mode"));
434 map[ax("PR", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " in PA or PR mode"));
435 map[ax("_BG", i, "")] = Source(base, "UW", 7, "Boolean", ax("Axis ", i, " move in progress"));
436 ++base; //84
437 map[ax("MT", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " in stepper mode"));
438 map[ax("_HM", i, "")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " home switch"));
439 map[ax("_LR", i, "")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " reverse limit switch"));
440 map[ax("_LF", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " forward limit switch"));
441 //4 and 5 reserved
442 map[ax("AL", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " latch digital input"));
443 map[ax("_AL", i, "=0")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " latch occurred"));
444 ++base; //85
445 map[ax("_SC", i, "")] = Source(base, "UB", -1, "", ax("Axis ", i, " stop code"));
446 ++base; //86
447 map[ax("_RP", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " reference position"));
448 base += 4; //90
449 map[ax("_TP", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " encoder position"));
450 base += 4; //94
451 map[ax("_TE", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " position error"));
452 base += 4; //98
453 map[ax("_TD", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " dual encoder position"));
454 base += 4; //102
455 map[ax("_TV", i, "")] = Source(base, "SL", -1, "counts/s", ax("Axis ", i, " filtered velocity"), 64);
456 base += 4; //106
457 map[ax("_TT", i, "")] = Source(base, "SL", -1, "V", ax("Axis ", i, " torque (DAC)"), 3255);
458 base += 4; //110
459
460 //Analog voltage decoding depends upon AQ setting.
461 aq_analog(base, i + 1);
462 base += 2; //112
463
464 map[ax("_QH", i, "")] = Source(base, "UB", -1, "", ax("Axis ", i, " hall sensors"));
465 base += 1; //113 reserved
466 base += 1; //114
467 map[ax("_ZA", i, "")] = Source(base, "SL", -1, "", ax("Axis ", i, " user variable"));
468 base += 4; //118
469
470 }// for, axis data
471 }
472
473 void GalilPrivate::Init1806(int axes)
474 {
475 map["TIME"] = Source(0, "UW", -1, "samples", "Sample counter");
476
477 //Digital inputs
478 map["_TI0"] = Source(2, "UB", -1, "", "Digital inputs 1 to 8");
479 input_bits(2, 1);
480
481 map["_TI1"] = Source(3, "UB", -1, "", "Digital inputs 9 to 16"); //TI always included
482 if (axes > 4) //9-16 depend on axes 5-8
483 input_bits(3, 9);
484
485
486 //Digital outputs
487 map["_OP0"] = Source(12, "UW", -1, "", "Digital outputs 1 to 16");
488 output_bits(12, 1);
489
490 if (axes > 4) //9-16 depend on axes 5-8
491 output_bits(13, 9);
492
493
494 //Extended I/O
495 int co = -1;
496 if (GCmdI(g, "MG_CO", &co) == G_NO_ERROR)
497 {
498 map["_TI2"] = Source(4, "UB", -1, "", "Digital inputs 17 to 24"); //TI always included in gcl
499 map["_TI3"] = Source(5, "UB", -1, "", "Digital inputs 25 to 32");
500 map["_TI4"] = Source(6, "UB", -1, "", "Digital inputs 33 to 40");
501 map["_TI5"] = Source(7, "UB", -1, "", "Digital inputs 41 to 48");
502 map["_TI6"] = Source(8, "UB", -1, "", "Digital inputs 49 to 56");
503 map["_TI7"] = Source(9, "UB", -1, "", "Digital inputs 57 to 64");
504 map["_TI8"] = Source(10, "UB", -1, "", "Digital inputs 65 to 72");
505 map["_TI9"] = Source(11, "UB", -1, "", "Digital inputs 73 to 80");
506
507 map["_OP1"] = Source(14, "UW", -1, "", "Digital outputs 17 to 32"); //OP always included in gcl
508 map["_OP2"] = Source(16, "UW", -1, "", "Digital outputs 33 to 48");
509 map["_OP3"] = Source(18, "UW", -1, "", "Digital outputs 49 to 64");
510 map["_OP4"] = Source(20, "UW", -1, "", "Digital outputs 65 to 80");
511
512 if (co & 0x00000001) //bank 2 is output
513 output_bits(14, 17);
514 else //input
515 input_bits(4, 17);
516
517 if (co & 0x00000002) //bank 3 is output
518 output_bits(15, 25);
519 else //input
520 input_bits(5, 25);
521
522 if (co & 0x00000004) //bank 4 is output
523 output_bits(16, 33);
524 else //input
525 input_bits(6, 33);
526
527 if (co & 0x00000008) //bank 5 is output
528 output_bits(17, 41);
529 else //input
530 input_bits(7, 41);
531
532 if (co & 0x00000010) //bank 6 is output
533 output_bits(18, 49);
534 else //input
535 input_bits(8, 49);
536
537 if (co & 0x00000020) //bank 7 is output
538 output_bits(19, 57);
539 else //input
540 input_bits(9, 57);
541
542 if (co & 0x00000040) //bank 8 is output
543 output_bits(20, 65);
544 else //input
545 input_bits(10, 65);
546
547 if (co & 0x00000080) //bank 9 is output
548 output_bits(21, 73);
549 else //input
550 input_bits(11, 73);
551 } //extended io
552
553 map["_TC"] = Source(46, "UB", -1, "", "Error code");
554
555 //Thread status
556 map["NO0"] = Source(47, "UB", 0, "Boolean", "Thread 0 running");
557 map["NO1"] = Source(47, "UB", 1, "Boolean", "Thread 1 running");
558 map["NO2"] = Source(47, "UB", 2, "Boolean", "Thread 2 running");
559 map["NO3"] = Source(47, "UB", 3, "Boolean", "Thread 3 running");
560 map["NO4"] = Source(47, "UB", 4, "Boolean", "Thread 4 running");
561 map["NO5"] = Source(47, "UB", 5, "Boolean", "Thread 5 running");
562 map["NO6"] = Source(47, "UB", 6, "Boolean", "Thread 6 running");
563 map["NO7"] = Source(47, "UB", 7, "Boolean", "Thread 7 running");
564
565 //contour mode
566 map["CD"] = Source(52, "UL", -1, "segments", "Contour segment count");
567 map["_CM"] = Source(56, "UW", -1, "elements", "Contour buffer space");
568
569 //S plane
570 map["_CSS"] = Source(58, "UW", -1, "segments", "Axis S segment count");
571 map["VDS"] = Source(60, "UB", 3, "Boolean", "Axis S final deceleration");
572 map["STS"] = Source(60, "UB", 4, "Boolean", "Axis S stopping");
573 map["VSS"] = Source(60, "UB", 5, "Boolean", "Axis S slewing");
574 map["_BGS"] = Source(61, "UB", 7, "Boolean", "Axis S moving");
575 map["_AVS"] = Source(62, "SL", -1, "counts", "Axis S length");
576 map["_LMS"] = Source(66, "UW", -1, "elements", "Axis S buffer speace");
577
578 //T plane
579 map["_CST"] = Source(68, "UW", -1, "segments", "Axis T segment count");
580 map["VDT"] = Source(70, "UB", 3, "Boolean", "Axis T final deceleration");
581 map["STT"] = Source(70, "UB", 4, "Boolean", "Axis T stopping");
582 map["VST"] = Source(70, "UB", 5, "Boolean", "Axis T slewing");
583 map["_BGT"] = Source(71, "UB", 7, "Boolean", "Axis T moving");
584 map["_AVT"] = Source(72, "SL", -1, "counts", "Axis T length");
585 map["_LMT"] = Source(76, "UW", -1, "elements", "Axis T buffer speace");
586
587 //per-axis data
588 int base = 78; //start of A axis data
589 for (int i = 0; i < axes; i++)
590 {
591 map[ax("_MO", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " motor off"));
592 map[ax("HM", i, "3")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " found index"));
593 map[ax("_AL", i, "")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " latch armed"));
594 map[ax("DC", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " began deceleration"));
595 map[ax("ST", i, "")] = Source(base, "UW", 4, "Boolean", ax("Axis ", i, " began stop"));
596 map[ax("SP", i, "")] = Source(base, "UW", 5, "Boolean", ax("Axis ", i, " began slew"));
597 map[ax("CM", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " in contour mode"));
598 map[ax("JG", i, "-")] = Source(base, "UW", 7, "Boolean", ax("Axis ", i, " negative move"));
599 ++base; //79
600 map[ax("VM", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " in VM or LI mode"));
601 map[ax("HM", i, "2")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " finding index"));
602 map[ax("HM", i, "1")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " coming off home switch"));
603 map[ax("HM", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " home command issued"));
604 map[ax("FE", i, "")] = Source(base, "UW", 4, "Boolean", ax("Axis ", i, " find edge issued"));
605 map[ax("PA", i, "")] = Source(base, "UW", 5, "Boolean", ax("Axis ", i, " in PA mode"));
606 map[ax("PR", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " in PA or PR mode"));
607 map[ax("_BG", i, "")] = Source(base, "UW", 7, "Boolean", ax("Axis ", i, " move in progress"));
608 ++base; //80
609 map[ax("MT", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " in stepper mode"));
610 map[ax("_HM", i, "")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " home switch"));
611 map[ax("_LR", i, "")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " reverse limit switch"));
612 map[ax("_LF", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " forward limit switch"));
613 //4 and 5 reserved
614 map[ax("AL", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " latch digital input"));
615 map[ax("_AL", i, "=0")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " latch occurred"));
616 ++base; //81
617 map[ax("_SC", i, "")] = Source(base, "UB", -1, "", ax("Axis ", i, " stop code"));
618 ++base; //82
619 map[ax("_RP", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " reference position"));
620 base += 4; //86
621 map[ax("_TP", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " encoder position"));
622 base += 4; //90
623 map[ax("_TE", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " position error"));
624 base += 4; //94
625 map[ax("_TD", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " dual encoder position"));
626 base += 4; //98
627 map[ax("_TV", i, "")] = Source(base, "SL", -1, "counts/s", ax("Axis ", i, " filtered velocity"), 64);
628 base += 4; //102
629 map[ax("_TT", i, "")] = Source(base, "SL", -1, "V", ax("Axis ", i, " torque (DAC)"), 3255);
630 base += 4; //106
631
632 map["@AN[" + to_string(i + 1) + "]"] = Source(base, "SW", -1, "V", "Analog input " + to_string(i + 1), 3276.8);
633
634 base += 2; //108 reserved
635 base += 1; //109 reserved
636 base += 1; //110
637 map[ax("_ZA", i, "")] = Source(base, "SL", -1, "", ax("Axis ", i, " user variable"));
638 base += 4; //114
639 }// for, axis data
640 }
641
642 void GalilPrivate::Init1800(int axes, bool dmc1802)
643 {
644
645 map["TIME"] = Source(0, "UW", -1, "samples", "Sample counter");
646
647 //Digital Inputs
648 map["_TI0"] = Source(2, "UB", -1, "", "Digital inputs 1 to 8");
649 input_bits(2, 1);
650
651 map["_TI1"] = Source(3, "UB", -1, "", "Digital inputs 9 to 16"); //TI always included
652 if (axes > 4) //9-16 depend on axes 5-8
653 input_bits(3, 9);
654
655 //Digital outputs
656 map["_OP0"] = Source(12, "UW", -1, "", "Digital outputs 1 to 16");
657 output_bits(12, 1);
658 if (axes > 4) //9-16 depend on axes 5-8
659 output_bits(13, 9);
660
661 //Extended I/O
662 int co = -1;
663 if (GCmdI(g, "MG_CO", &co) == G_NO_ERROR)
664 {
665 map["_TI2"] = Source(4, "UB", -1, "", "Digital inputs 17 to 24"); //TI always included in gcl
666 map["_TI3"] = Source(5, "UB", -1, "", "Digital inputs 25 to 32");
667 map["_TI4"] = Source(6, "UB", -1, "", "Digital inputs 33 to 40");
668 map["_TI5"] = Source(7, "UB", -1, "", "Digital inputs 41 to 48");
669 map["_TI6"] = Source(8, "UB", -1, "", "Digital inputs 49 to 56");
670 map["_TI7"] = Source(9, "UB", -1, "", "Digital inputs 57 to 64");
671 map["_TI8"] = Source(10, "UB", -1, "", "Digital inputs 65 to 72");
672 map["_TI9"] = Source(11, "UB", -1, "", "Digital inputs 73 to 80");
673
674 map["_OP1"] = Source(14, "UW", -1, "", "Digital outputs 17 to 32"); //OP always included in gcl
675 map["_OP2"] = Source(16, "UW", -1, "", "Digital outputs 33 to 48");
676 map["_OP3"] = Source(18, "UW", -1, "", "Digital outputs 49 to 64");
677 map["_OP4"] = Source(20, "UW", -1, "", "Digital outputs 65 to 80");
678
679 if (co & 0x00000001) //bank 2 is output
680 output_bits(14, 17);
681 else //input
682 input_bits(4, 17);
683
684 if (co & 0x00000002) //bank 3 is output
685 output_bits(15, 25);
686 else //input
687 input_bits(5, 25);
688
689 if (co & 0x00000004) //bank 4 is output
690 output_bits(16, 33);
691 else //input
692 input_bits(6, 33);
693
694 if (co & 0x00000008) //bank 5 is output
695 output_bits(17, 41);
696 else //input
697 input_bits(7, 41);
698
699 if (co & 0x00000010) //bank 6 is output
700 output_bits(18, 49);
701 else //input
702 input_bits(8, 49);
703
704 if (co & 0x00000020) //bank 7 is output
705 output_bits(19, 57);
706 else //input
707 input_bits(9, 57);
708
709 if (co & 0x00000040) //bank 8 is output
710 output_bits(20, 65);
711 else //input
712 input_bits(10, 65);
713
714 if (co & 0x00000080) //bank 9 is output
715 output_bits(21, 73);
716 else //input
717 input_bits(11, 73);
718 } //extended io
719
720 map["_TC"] = Source(22, "UB", -1, "", "Error code");
721
722 //general status
723 map["_EO"] = Source(23, "UB", 0, "Boolean", "Echo on");
724 map["TR"] = Source(23, "UB", 1, "Boolean", "Trace on");
725 map["IN"] = Source(23, "UB", 2, "Boolean", "IN waiting for user input");
726 map["XQ"] = Source(23, "UB", 7, "Boolean", "Program running");
727
728 //S plane
729 map["_CSS"] = Source(24, "UW", -1, "segments", "Axis S segment count");
730 map["VDS"] = Source(26, "UB", 3, "Boolean", "Axis S final deceleration");
731 map["STS"] = Source(26, "UB", 4, "Boolean", "Axis S stopping");
732 map["VSS"] = Source(26, "UB", 5, "Boolean", "Axis S slewing");
733 map["_BGS"] = Source(27, "UB", 7, "Boolean", "Axis S moving");
734 map["_AVS"] = Source(28, "SL", -1, "counts", "Axis S length");
735
736 //T plane
737 map["_CST"] = Source(32, "UW", -1, "segments", "Axis T segment count");
738 map["VDT"] = Source(34, "UB", 3, "Boolean", "Axis T final deceleration");
739 map["STT"] = Source(34, "UB", 4, "Boolean", "Axis T stopping");
740 map["VST"] = Source(34, "UB", 5, "Boolean", "Axis T slewing");
741 map["_BGT"] = Source(35, "UB", 7, "Boolean", "Axis T moving");
742 map["_AVT"] = Source(36, "SL", -1, "counts", "Axis T length");
743
744 //per-axis data
745 int base = 40; //start of A axis data
746 for (int i = 0; i < axes; i++)
747 {
748 map[ax("_MO", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " motor off"));
749 map[ax("_OE", i, "")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " off-on-error set"));
750 map[ax("_AL", i, "")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " latch armed"));
751 map[ax("DC", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " began deceleration"));
752 map[ax("ST", i, "")] = Source(base, "UW", 4, "Boolean", ax("Axis ", i, " began stop"));
753 map[ax("SP", i, "")] = Source(base, "UW", 5, "Boolean", ax("Axis ", i, " began slew"));
754 map[ax("CM", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " in contour mode"));
755 map[ax("JG", i, "-")] = Source(base, "UW", 7, "Boolean", ax("Axis ", i, " negative move"));
756 ++base; //41
757 map[ax("VM", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " in VM or LI mode"));
758 map[ax("HM", i, "2")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " finding index"));
759 map[ax("HM", i, "1")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " coming off home switch"));
760 map[ax("HM", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " home command issued"));
761 map[ax("FE", i, "")] = Source(base, "UW", 4, "Boolean", ax("Axis ", i, " find edge issued"));
762 map[ax("PA", i, "")] = Source(base, "UW", 5, "Boolean", ax("Axis ", i, " in PA mode"));
763 map[ax("PR", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " in PA or PR mode"));
764 map[ax("_BG", i, "")] = Source(base, "UW", 7, "Boolean", ax("Axis ", i, " move in progress"));
765 ++base; //42
766 map[ax("SM", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " stepper jumper installed"));
767 map[ax("_HM", i, "")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " home switch"));
768 map[ax("_LR", i, "")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " reverse limit switch"));
769 map[ax("_LF", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " forward limit switch"));
770 //4 and 5 reserved
771 map[ax("AL", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " latch digital input"));
772 map[ax("_AL", i, "=0")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " latch occurred"));
773 ++base; //43
774 map[ax("_SC", i, "")] = Source(base, "UB", -1, "", ax("Axis ", i, " stop code"));
775 ++base; //44
776 map[ax("_RP", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " reference position"));
777 base += 4; //48
778 map[ax("_TP", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " encoder position"));
779 base += 4; //52
780 map[ax("_TE", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " position error"));
781 base += 4; //56
782 map[ax("_TD", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " dual encoder position"));
783 base += 4; //60
784 map[ax("_TV", i, "")] = Source(base, "SL", -1, "counts/s", ax("Axis ", i, " filtered velocity"), 64);
785 base += 4; //64
786 map[ax("_TT", i, "")] = Source(base, "SW", -1, "V", ax("Axis ", i, " torque (DAC)"), 3255);
787 base += 2; //66
788
789 if (!dmc1802) //1800 has onboard Analog inputs
790 map["@AN[" + to_string(i + 1) + "]"] = Source(base, "SW", -1, "V", "Analog input " + to_string(i + 1), 3276.8);
791
792 base += 2; //68, pointing to next axis
793 } //for
794 }
795
796
797 void GalilPrivate::Init30010(bool dmc31010)
798 {
799 //0-3 Header is ignored in GCL
800
801 map["TIME"] = Source(4, "UW", -1, "samples", "Sample counter");
802
803 map["@IN[1]"] = Source(6, "UB", 0, "Boolean", "Digital input 1");
804 map["@IN[2]"] = Source(6, "UB", 1, "Boolean", "Digital input 2");
805 map["@IN[3]"] = Source(6, "UB", 2, "Boolean", "Digital input 3");
806 map["@IN[4]"] = Source(6, "UB", 3, "Boolean", "Digital input 4");
807 map["@IN[5]"] = Source(6, "UB", 4, "Boolean", "Digital input 5");
808 map["@IN[6]"] = Source(6, "UB", 5, "Boolean", "Digital input 6");
809 map["@IN[7]"] = Source(6, "UB", 6, "Boolean", "Digital input 7");
810 map["@IN[8]"] = Source(6, "UB", 7, "Boolean", "Digital input 8");
811
812 map["@OUT[1]"] = Source(8, "UB", 0, "Boolean", "Digital output 1");
813 map["@OUT[2]"] = Source(8, "UB", 1, "Boolean", "Digital output 2");
814 map["@OUT[3]"] = Source(8, "UB", 2, "Boolean", "Digital output 3");
815 map["@OUT[4]"] = Source(8, "UB", 3, "Boolean", "Digital output 4");
816
817 map["_TC"] = Source(10, "UB", -1, "", "Error code");
818
819 //Thread status
820 map["NO0"] = Source(11, "UB", 0, "Boolean", "Thread 0 running");
821 map["NO1"] = Source(11, "UB", 1, "Boolean", "Thread 1 running");
822 map["NO2"] = Source(11, "UB", 2, "Boolean", "Thread 2 running");
823 map["NO3"] = Source(11, "UB", 3, "Boolean", "Thread 3 running");
824 map["NO4"] = Source(11, "UB", 4, "Boolean", "Thread 4 running"); //Firmware prior to 1.2a has only 4 threads
825 map["NO5"] = Source(11, "UB", 5, "Boolean", "Thread 5 running");
826
827 //Analog IO
828 //version 1.1b provides 16 bit AQ-compatible data in data record
829 if (dmc31010)
830 aq_analog(12, 2);
831 else
832 map["@AN[2]"] = Source(12, "UW", -1, "V", "Analog input 2", 13107.2); //0-5 16 bit upsampling
833
834 map["@AO[1]"] = Source(14, "SW", -1, "V", "Analog output 1", 3276.8); //+/- 10v
835 map["@AO[2]"] = Source(16, "SW", -1, "V", "Analog output 2", 3276.8);
836
837 //Amp status
838 map["TA00"] = Source(18, "UB", 0, "Boolean", "Axis A over current");
839 map["TA01"] = Source(18, "UB", 1, "Boolean", "Axis A over voltage");
840 map["TA02"] = Source(18, "UB", 2, "Boolean", "Axis A over temperature");
841 map["TA03"] = Source(18, "UB", 3, "Boolean", "Axis A under voltage");
842 map["TA1A"] = Source(19, "UB", 0, "Boolean", "Axis A hall error");
843 map["TA2A"] = Source(20, "UB", 0, "Boolean", "Axis A at _TKA peak current");
844 map["TA3AD"] = Source(21, "UB", 0, "Boolean", "Axis A ELO active");
845
846 //contour mode
847 map["CD"] = Source(22, "UL", -1, "segments", "Contour segment count");
848 map["_CM"] = Source(26, "UW", -1, "elements", "Contour buffer space");
849
850 //S plane
851 map["_CSS"] = Source(28, "UW", -1, "segments", "Axis S segment count");
852 map["VDS"] = Source(30, "UB", 3, "Boolean", "Axis S final deceleration");
853 map["STS"] = Source(30, "UB", 4, "Boolean", "Axis S stopping");
854 map["VSS"] = Source(30, "UB", 5, "Boolean", "Axis S slewing");
855 map["_BGS"] = Source(31, "UB", 7, "Boolean", "Axis S moving");
856 map["_AVS"] = Source(32, "SL", -1, "counts", "Axis S length");
857 map["_LMS"] = Source(36, "UW", -1, "elements", "Axis S buffer speace");
858
859 //per-axis data
860 int base = 38; //starting offset
861 int i = 0; //only one axis on 30010, no need to iterate axes
862
863 map[ax("_MO", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " motor off"));
864 map[ax("HM", i, "3")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " found index"));
865 map[ax("_AL", i, "")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " latch armed"));
866 map[ax("DC", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " began deceleration"));
867 map[ax("ST", i, "")] = Source(base, "UW", 4, "Boolean", ax("Axis ", i, " began stop"));
868 map[ax("SP", i, "")] = Source(base, "UW", 5, "Boolean", ax("Axis ", i, " began slew"));
869 map[ax("CM", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " in contour mode"));
870 map[ax("JG", i, "-")] = Source(base, "UW", 7, "Boolean", ax("Axis ", i, " negative move"));
871 ++base; //39
872 map[ax("VM", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " in VM or LI mode"));
873 map[ax("HM", i, "2")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " finding index"));
874 map[ax("HM", i, "1")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " coming off home switch"));
875 map[ax("HM", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " home command issued"));
876 map[ax("FE", i, "")] = Source(base, "UW", 4, "Boolean", ax("Axis ", i, " find edge issued"));
877 map[ax("PA", i, "")] = Source(base, "UW", 5, "Boolean", ax("Axis ", i, " in PA mode"));
878 map[ax("PR", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " in PA or PR mode"));
879 map[ax("_BG", i, "")] = Source(base, "UW", 7, "Boolean", ax("Axis ", i, " move in progress"));
880 ++base; //40
881 map[ax("MT", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " in stepper mode"));
882 map[ax("_HM", i, "")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " home switch"));
883 map[ax("_LR", i, "")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " reverse limit switch"));
884 map[ax("_LF", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " forward limit switch"));
885 //4 and 5 reserved
886 map[ax("AL", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " latch digital input"));
887 map[ax("_AL", i, "=0")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " latch occurred"));
888 ++base; //41
889 map[ax("_SC", i, "")] = Source(base, "UB", -1, "", ax("Axis ", i, " stop code"));
890 ++base; //42
891 map[ax("_RP", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " reference position"));
892 base += 4; //46
893 map[ax("_TP", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " encoder position"));
894 base += 4; //50
895 map[ax("_TE", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " position error"));
896 base += 4; //54
897 map[ax("_TD", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " dual encoder position"));
898 base += 4; //58
899 map[ax("_TV", i, "")] = Source(base, "SL", -1, "counts/s", ax("Axis ", i, " filtered velocity"), 64);
900 base += 4; //62
901 map[ax("_TT", i, "")] = Source(base, "SL", -1, "V", ax("Axis ", i, " torque (DAC)"), 3255);
902 base += 4; //66
903
904 //version 1.1b provides 16 bit AQ-compatible data in data record
905 if (dmc31010)
906 aq_analog(base, i + 1);
907 else
908 map["@AN[" + to_string(i + 1) + "]"] = Source(base, "UW", -1, "V", "Analog input " + to_string(i + 1), 13107.2);
909
910 base += 2; //68
911
912 map[ax("_QH", i, "")] = Source(base, "UB", -1, "", ax("Axis ", i, " hall sensors"));
913 base++; //69 reserved
914 base++; //70
915 map[ax("_ZA", i, "")] = Source(base, "SL", -1, "", ax("Axis ", i, " user variable"));
916 base += 4; //74
917
918 }
919
920 void GalilPrivate::Init2103(int axes)
921 {
922
923 bool db28040 = (GCmd(g, "MG @AN[1]") == G_NO_ERROR); //probe @AN for existance of DB-28040
924
925 //0-3 Header is ignored in GCL
926
927 map["TIME"] = Source(4, "UW", -1, "samples", "Sample counter");
928
929 //Digital Inputs
930 map["_TI0"] = Source(6, "UB", -1, "", "Digital inputs 1 to 8");
931 input_bits(6, 1);
932
933 map["_TI1"] = Source(7, "UB", -1, "", "Digital inputs 9 to 16"); //TI always included
934 if (axes > 4) //9-16 depend on axes 5-8
935 input_bits(7, 9);
936
937 //Digital outputs
938 map["_OP0"] = Source(16, "UW", -1, "", "Digital outputs 1 to 16");
939 output_bits(16, 1);
940
941 if (axes > 4) //9-16 depend on axes 5-8
942 output_bits(17, 9);
943
944 //Extended I/O
945 int co = -1;
946 if (db28040 && (GCmdI(g, "MG_CO", &co) == G_NO_ERROR))
947 {
948 map["_TI2"] = Source(8, "UB", -1, "", "Digital inputs 17 to 24"); //TI always included in gcl
949 map["_TI3"] = Source(9, "UB", -1, "", "Digital inputs 25 to 32");
950 map["_TI4"] = Source(10, "UB", -1, "", "Digital inputs 33 to 40");
951 map["_TI5"] = Source(11, "UB", -1, "", "Digital inputs 41 to 48");
952 map["_TI6"] = Source(12, "UB", -1, "", "Digital inputs 49 to 56");
953
954 map["_OP1"] = Source(18, "UW", -1, "", "Digital outputs 17 to 32"); //OP always included in gcl
955 map["_OP2"] = Source(20, "UW", -1, "", "Digital outputs 33 to 48");
956 map["_OP3"] = Source(22, "UW", -1, "", "Digital outputs 49 to 64");
957
958 if (co & 0x00000001) //bank 2 is output
959 output_bits(18, 17);
960 else //bank 2 in input
961 input_bits(8, 17);
962
963 if (co & 0x00000002) //bank 3 is output
964 output_bits(19, 25);
965 else //bank 3 is input
966 input_bits(9, 25);
967
968 if (co & 0x00000004) //bank 4 is output
969 output_bits(20, 33);
970 else //bank 4 is input
971 input_bits(10, 33);
972
973 if (co & 0x00000008) //bank 5 is output
974 output_bits(21, 41);
975 else //bank 5 is input
976 input_bits(11, 41);
977
978 if (co & 0x00000010) //bank 6 is output
979 output_bits(22, 49);
980 else //bank 6 is input
981 input_bits(12, 49);
982 }
983
984 map["_TC"] = Source(26, "UB", -1, "", "Error code");
985
986 //general status
987 map["_EO"] = Source(27, "UB", 0, "Boolean", "Echo on");
988 map["TR"] = Source(27, "UB", 1, "Boolean", "Trace on");
989 map["IN"] = Source(27, "UB", 2, "Boolean", "IN waiting for user input");
990 map["XQ"] = Source(27, "UB", 7, "Boolean", "Program running");
991
992 //S plane
993 map["_CSS"] = Source(28, "UW", -1, "segments", "Axis S segment count");
994 map["VDS"] = Source(30, "UB", 3, "Boolean", "Axis S final deceleration");
995 map["STS"] = Source(30, "UB", 4, "Boolean", "Axis S stopping");
996 map["VSS"] = Source(30, "UB", 5, "Boolean", "Axis S slewing");
997 map["_BGS"] = Source(31, "UB", 7, "Boolean", "Axis S moving");
998 map["_AVS"] = Source(32, "SL", -1, "counts", "Axis S length");
999
1000 //T plane
1001 map["_CST"] = Source(36, "UW", -1, "segments", "Axis T segment count");
1002 map["VDT"] = Source(38, "UB", 3, "Boolean", "Axis T final deceleration");
1003 map["STT"] = Source(38, "UB", 4, "Boolean", "Axis T stopping");
1004 map["VST"] = Source(38, "UB", 5, "Boolean", "Axis T slewing");
1005 map["_BGT"] = Source(39, "UB", 7, "Boolean", "Axis T moving");
1006 map["_AVT"] = Source(40, "SL", -1, "counts", "Axis T length");
1007
1008 //per-axis data
1009 int base = 44; //start of A axis data
1010 for (int i = 0; i < axes; i++)
1011 {
1012 map[ax("_MO", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " motor off"));
1013 map[ax("_OE", i, "")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " off-on-error set"));
1014 map[ax("_AL", i, "")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " latch armed"));
1015 map[ax("DC", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " began deceleration"));
1016 map[ax("ST", i, "")] = Source(base, "UW", 4, "Boolean", ax("Axis ", i, " began stop"));
1017 map[ax("SP", i, "")] = Source(base, "UW", 5, "Boolean", ax("Axis ", i, " began slew"));
1018 map[ax("CM", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " in contour mode"));
1019 map[ax("JG", i, "-")] = Source(base, "UW", 7, "Boolean", ax("Axis ", i, " negative move"));
1020 ++base; //45
1021 map[ax("VM", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " in VM or LI mode"));
1022 map[ax("HM", i, "2")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " finding index"));
1023 map[ax("HM", i, "1")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " coming off home switch"));
1024 map[ax("HM", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " home command issued"));
1025 map[ax("FE", i, "")] = Source(base, "UW", 4, "Boolean", ax("Axis ", i, " find edge issued"));
1026 map[ax("PA", i, "")] = Source(base, "UW", 5, "Boolean", ax("Axis ", i, " in PA mode"));
1027 map[ax("PR", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " in PA or PR mode"));
1028 map[ax("_BG", i, "")] = Source(base, "UW", 7, "Boolean", ax("Axis ", i, " move in progress"));
1029 ++base; //46
1030 map[ax("SM", i, "")] = Source(base, "UW", 0, "Boolean", ax("Axis ", i, " stepper jumper installed"));
1031 map[ax("_HM", i, "")] = Source(base, "UW", 1, "Boolean", ax("Axis ", i, " home switch"));
1032 map[ax("_LR", i, "")] = Source(base, "UW", 2, "Boolean", ax("Axis ", i, " reverse limit switch"));
1033 map[ax("_LF", i, "")] = Source(base, "UW", 3, "Boolean", ax("Axis ", i, " forward limit switch"));
1034 //4 and 5 reserved
1035 map[ax("AL", i, "")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " latch digital input"));
1036 map[ax("_AL", i, "=0")] = Source(base, "UW", 6, "Boolean", ax("Axis ", i, " latch occurred"));
1037 ++base; //47
1038 map[ax("_SC", i, "")] = Source(base, "UB", -1, "", ax("Axis ", i, " stop code"));
1039 ++base; //48
1040 map[ax("_RP", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " reference position"));
1041 base += 4; //52
1042 map[ax("_TP", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " encoder position"));
1043 base += 4; //56
1044 map[ax("_TE", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " position error"));
1045 base += 4; //60
1046 map[ax("_TD", i, "")] = Source(base, "SL", -1, "counts", ax("Axis ", i, " dual encoder position"));
1047 base += 4; //64
1048 map[ax("_TV", i, "")] = Source(base, "SL", -1, "counts/s", ax("Axis ", i, " filtered velocity"), 64);
1049 base += 4; //68
1050 map[ax("_TT", i, "")] = Source(base, "SW", -1, "V", ax("Axis ", i, " torque (DAC)"), 3255);
1051 base += 2; //70
1052
1053 if (db28040) //card has onboard Analog inputs
1054 {
1055 aq_analog(base, i + 1); //map in the analog
1056 }
1057 base += 2; //72
1058 } //for
1059 }
1060
1061 void GalilPrivate::InitRio(bool rio3)
1062 {
1063
1064
1065 //0-3 Header is ignored in GCL
1066
1067 map["TIME"] = Source(4, "UW", -1, "samples", "Sample counter");
1068 map["_TC"] = Source(6, "UB", -1, "", "Error code");
1069
1070 //general status
1071 map["_EO"] = Source(7, "UB", 0, "Boolean", "Echo on");
1072 map["TR"] = Source(7, "UB", 1, "Boolean", "Trace on");
1073 map["IN"] = Source(7, "UB", 2, "Boolean", "IN waiting for user input");
1074 map["XQ"] = Source(7, "UB", 7, "Boolean", "Program running");
1075
1076 bool aqdq = (q->command("ID").find("(AQ)") != string::npos); //progammable analog I/O
1077
1078 if (aqdq)
1079 {
1080 dq_analog(8, 0);
1081 dq_analog(10, 1);
1082 dq_analog(12, 2);
1083 dq_analog(14, 3);
1084 dq_analog(16, 4);
1085 dq_analog(18, 5);
1086 dq_analog(20, 6);
1087 dq_analog(22, 7);
1088 }
1089 else //fixed 0-5V
1090 {
1091 map["@AO[0]"] = Source(8, "UW", -1, "V", "Analog output 0", 13107.2, 0);
1092 map["@AO[1]"] = Source(10, "UW", -1, "V", "Analog output 1", 13107.2, 0);
1093 map["@AO[2]"] = Source(12, "UW", -1, "V", "Analog output 2", 13107.2, 0);
1094 map["@AO[3]"] = Source(14, "UW", -1, "V", "Analog output 3", 13107.2, 0);
1095 map["@AO[4]"] = Source(16, "UW", -1, "V", "Analog output 4", 13107.2, 0);
1096 map["@AO[5]"] = Source(18, "UW", -1, "V", "Analog output 5", 13107.2, 0);
1097 map["@AO[6]"] = Source(20, "UW", -1, "V", "Analog output 6", 13107.2, 0);
1098 map["@AO[7]"] = Source(22, "UW", -1, "V", "Analog output 7", 13107.2, 0);
1099 }
1100
1101
1102 if (aqdq)
1103 {
1104 aq_analog(24, 0);
1105 aq_analog(26, 1);
1106 aq_analog(28, 2);
1107 aq_analog(30, 3);
1108 aq_analog(32, 4);
1109 aq_analog(34, 5);
1110 aq_analog(36, 6);
1111 aq_analog(38, 7);
1112 }
1113 else //fixed 0-5V
1114 {
1115 map["@AN[0]"] = Source(24, "UW", -1, "V", "Analog input 0", 13107.2, 0);
1116 map["@AN[1]"] = Source(26, "UW", -1, "V", "Analog input 1", 13107.2, 0);
1117 map["@AN[2]"] = Source(28, "UW", -1, "V", "Analog input 2", 13107.2, 0);
1118 map["@AN[3]"] = Source(30, "UW", -1, "V", "Analog input 3", 13107.2, 0);
1119 map["@AN[4]"] = Source(32, "UW", -1, "V", "Analog input 4", 13107.2, 0);
1120 map["@AN[5]"] = Source(34, "UW", -1, "V", "Analog input 5", 13107.2, 0);
1121 map["@AN[6]"] = Source(36, "UW", -1, "V", "Analog input 6", 13107.2, 0);
1122 map["@AN[7]"] = Source(38, "UW", -1, "V", "Analog input 7", 13107.2, 0);
1123 }
1124
1125 //Data record diverges here for RIO471/472 and RIO473
1126 int base = 40;
1127
1128 //outputs
1129 map["_OP0"] = Source(base, "UB", -1, "", "Digital ouputs 0-7");
1130 output_bits(base, 0);
1131 base++;
1132
1133 map["_OP1"] = Source(base, "UB", -1, "", "Digital outputs 8-15");
1134 output_bits(base, 8);
1135 base++;
1136
1137 if (rio3)
1138 {
1139 map["_OP2"] = Source(base, "UB", -1, "", "Digital outputs 16-23");
1140 output_bits(base, 16);
1141 base++;
1142 base++; //one more byte in IO space
1143 }
1144
1145 //inputs
1146 map["_TI0"] = Source(base, "UB", -1, "", "Digital inputs 0-7");
1147 input_bits(base, 0);
1148 base++;
1149
1150 map["_TI1"] = Source(base, "UB", -1, "", "Digital inputs 8-15");
1151 input_bits(base, 8);
1152 base++;
1153
1154 if (rio3)
1155 {
1156 map["_TI2"] = Source(base, "UB", -1, "", "Digital inputs 16-23");
1157 input_bits(base, 16);
1158 base++;
1159 base++; //one more byte in IO space
1160 }
1161
1162 //pulse counter
1163 map["_PC"] = Source(base, "UL", -1, "edges", "Pulse counter");
1164 base += 4;
1165
1166 //user vars
1167 map["_ZC"] = Source(base, "SL", -1, "", "1st user variable");
1168 base += 4;
1169 map["_ZD"] = Source(base, "SL", -1, "", "2nd user variable");
1170 base += 4;
1171 }
1172
1173 void GalilPrivate::InitRio3_24Ex()
1174 {
1175 //Extended I/O tacks 8 bytes on the end of the data record, three bytes of each of I/O, one reserved for each
1176 map["_OP3"] = Source(60, "UB", -1, "", "Digital outputs 24-31");
1177 output_bits(60, 24);
1178 map["_OP4"] = Source(61, "UB", -1, "", "Digital outputs 32-39");
1179 output_bits(61, 32);
1180 map["_OP5"] = Source(62, "UB", -1, "", "Digital outputs 40-47");
1181 output_bits(62, 40);
1182 //byte 63 is reserved
1183
1184 map["_TI3"] = Source(64, "UB", -1, "", "Digital inputs 24-31");
1185 input_bits(64, 24);
1186 map["_TI4"] = Source(65, "UB", -1, "", "Digital inputs 32-39");
1187 input_bits(65, 32);
1188 map["_TI5"] = Source(66, "UB", -1, "", "Digital inputs 40-47");
1189 input_bits(66, 40);
1190 //byte 67 is reserved
1191 }
1192
1193 void GalilPrivate::InitRioSer(bool rio3)
1194 {
1195 //SER tacks 4 longs on the end of the data record (4 encoders)
1196 int base = rio3 ? 60 : 56; //RIO 47300 base data record is longer than the other RIO products due to 24 i/o standard
1197 map["_QE0"] = Source(base, "SL", -1, "counts", "encoder position"); base += 4;
1198 map["_QE1"] = Source(base, "SL", -1, "counts", "encoder position"); base += 4;
1199 map["_QE2"] = Source(base, "SL", -1, "counts", "encoder position"); base += 4;
1200 map["_QE3"] = Source(base, "SL", -1, "counts", "encoder position"); base += 4;
1201 }
gcl_galil.h
GRecord
GCLIB_DLL_EXPORTED GReturn GCALL GRecord(GCon g, union GDataRecord *record, GOption method)
Provides a fresh copy of the controller's data record. Data is cast into a union, GDataRecord.
GRecordRate
GCLIB_DLL_EXPORTED GReturn GCALL GRecordRate(GCon g, double period_ms)
Sets the asynchronous data record to a user-specified period via DR.
Definition: gclibo.c:342
GCmdI
GCLIB_DLL_EXPORTED GReturn GCALL GCmdI(GCon g, GCStringIn command, int *value)
Wrapper around GCommand that provides the return value of a command parsed into an int.
Definition: gclibo.c:278
GCmd
GCLIB_DLL_EXPORTED GReturn GCALL GCmd(GCon g, GCStringIn command)
Wrapper around GCommand for use when the return value is not desired.
Definition: gclibo.c:237
G_DR
#define G_DR
Value for GRecord() method variable for acquiring a data record via DR mode.
Definition: gclib.h:50
G_NO_ERROR
#define G_NO_ERROR
Return value if function succeeded.
Definition: gclib_errors.h:13
G_QR
#define G_QR
Value for GRecord() method variable for acquiring a data record via QR mode.
Definition: gclib.h:51
e
void e(GReturn rc)
A trivial, C++ style return code check used in Galil's examples and demos.
Definition: examples.h:33
Source
Definition: gcl_galil.h:17
GDataRecord
Data record union, containing all structs and a generic byte array accessor.
Definition: gclib_record.h:1083
GDataRecord::byte_array
unsigned char byte_array[GALILDATARECORDMAXLENGTH]
Generic byte array for offsets.
Definition: gclib_record.h:1103