RTXI  2.4
The Real-Time eXperiment Interface Documentation
analogy_device.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 University of Bristol, UK
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 
19 #include <analogy_device.h>
20 #include <debug.h>
21 #include <math.h>
22 #include <sstream>
23 
24 #define A4L_CHAN_AREF_GROUND 0x1;
25 #define A4L_CHAN_AREF_COMMON 0x2;
26 #define A4L_CHAN_AREF_DIFF 0x4;
27 #define A4L_CHAN_AREF_OTHER 0x8;
28 
29 using namespace DAQ;
30 
31 AnalogyDevice::AnalogyDevice(a4l_desc_t *d,std::string name,IO::channel_t *chan,size_t size) : DAQ::Device(name,chan,size), dsc(*d)
32 {
33 
34  int err = 0;
35  a4l_sbinfo_t *sbinfo;
36  a4l_chinfo_t *chinfo;
37 
38  // We need to find each subdevice index manually since idx_*_subd often fails
39  // Go over all subdevices and save the indexes of the first AI, AO and DIO
40  int idx_ai = -1;
41  int idx_ao = -1;
42  int idx_dio = -1;
43  for (int i=0; i < dsc.nb_subd; i++)
44  {
45  err = a4l_get_subdinfo(&dsc, i, &sbinfo);
46  if(err != 0)
47  {
48  ERROR_MSG("AnalogyDriver: a4l_get_subd_info failed, wrong subdevice index %i (err=%d)\n", i, err);
49  }
50  // Assign subdevice index; save just the first device if many
51  if (((sbinfo->flags & A4L_SUBD_TYPES) == A4L_SUBD_AI) && (idx_ai < 0))
52  idx_ai = i;
53  else if (((sbinfo->flags & A4L_SUBD_TYPES) == A4L_SUBD_AO) && (idx_ao < 0))
54  idx_ao = i;
55  else if (((sbinfo->flags & A4L_SUBD_TYPES) == A4L_SUBD_DIO) && (idx_dio < 0))
56  {
57  idx_dio = i;
58  }
59  }
60 
61  // Get info about AI subdevice
62  err = a4l_get_subdinfo(&dsc, idx_ai, &sbinfo);
63  if((err == 0) && ((sbinfo->flags & A4L_SUBD_TYPES) == A4L_SUBD_AI))
64  {
65  subdevice[AI].id = idx_ai;
66  subdevice[AI].active = 0;
67  subdevice[AI].count = sbinfo->nb_chan;
68  subdevice[AI].chan = new channel_t[subdevice[AI].count];
69  if(!subdevice[AI].chan)
70  subdevice[AI].count = 0;
71  else
72  for(size_t i=0; i<subdevice[AI].count; ++i)
73  {
74  err = a4l_get_chinfo(&dsc, idx_ai, i, &chinfo);
75  // Something went wrong
76  if(err < 0)
77  {
78  subdevice[AI].active = 0;
79  subdevice[AI].count = 0;
80  delete[] subdevice[AI].chan;
81  break;
82  }
83  subdevice[AI].chan[i].active = false;
84  subdevice[AI].chan[i].analog.maxdata = (1<<chinfo->nb_bits)-1;
85  setAnalogGain(AI,i,1.0);
86  setAnalogRange(AI,i,0);
89  setAnalogUnits(AI,i,0);
93  }
94  }
95  else
96  {
97  subdevice[AI].active = 0;
98  subdevice[AI].count = 0;
99  subdevice[AI].chan = NULL;
100  }
101 
102  // Get info about AO subdevice
103  err = a4l_get_subdinfo(&dsc, idx_ao, &sbinfo);
104  if((err == 0) && ((sbinfo->flags & A4L_SUBD_TYPES) == A4L_SUBD_AO))
105  {
106  subdevice[AO].id = idx_ao;
107  subdevice[AO].active = 0;
108  subdevice[AO].count = sbinfo->nb_chan;
109  subdevice[AO].chan = new channel_t[subdevice[AO].count];
110  if(!subdevice[AO].chan)
111  subdevice[AO].count = 0;
112  else
113  for(size_t i=0; i<subdevice[AO].count; ++i)
114  {
115  err = a4l_get_chinfo(&dsc, idx_ao, i, &chinfo);
116  // Something went wrong
117  if(err < 0)
118  {
119  subdevice[AO].active = 0;
120  subdevice[AO].count = 0;
121  delete[] subdevice[AO].chan;
122  break;
123  }
124  subdevice[AO].chan[i].active = false;
125  subdevice[AO].chan[i].analog.maxdata = (1<<chinfo->nb_bits)-1;
126  setAnalogGain(AO,i,1.0);
127  setAnalogZeroOffset(AO,i,0);
128  setAnalogRange(AO,i,0);
129  setAnalogReference(AO,i,0);
130  setAnalogUnits(AO,i,0);
132  }
133  }
134  else
135  {
136  subdevice[AO].active = 0;
137  subdevice[AO].count = 0;
138  subdevice[AO].chan = NULL;
139  }
140 
141  // Get info about DIO subdevice and set to INPUT as default
142  // Then add all Digital I/O to INPUT list for the
143  // IO class to handle
144  err = a4l_get_subdinfo(&dsc, idx_dio, &sbinfo);
145  if((err == 0) && ((sbinfo->flags & A4L_SUBD_TYPES) == A4L_SUBD_DIO))
146  {
147  subdevice[DIO].id = idx_dio;
148  subdevice[DIO].active = 0;
149  subdevice[DIO].count = sbinfo->nb_chan;
150  subdevice[DIO].chan = new channel_t[subdevice[DIO].count];
151  if(!subdevice[DIO].chan)
152  subdevice[DIO].count = 0;
153  else
154  for(size_t i=0; i<subdevice[DIO].count; ++i)
155  {
156  subdevice[DIO].chan[i].active = false;
157  subdevice[DIO].chan[i].digital.previous_value = 0;
159  }
160  }
161  else
162  {
163  subdevice[DIO].active = 0;
164  subdevice[DIO].count = 0;
165  subdevice[DIO].chan = NULL;
166  }
167  setActive(true);
168 }
169 
171 {
172  if(subdevice[AI].chan) delete[] subdevice[AI].chan;
173  if(subdevice[AO].chan) delete[] subdevice[AO].chan;
174  if(subdevice[DIO].chan) delete[] subdevice[DIO].chan;
175  if(dsc.sbdata) a4l_close(&dsc);
176 }
177 
178 bool AnalogyDevice::analog_exists(type_t type,index_t count) const
179 {
180  if((type == AI && count < subdevice[AI].count) ||
181  (type == AO && count < subdevice[AO].count))
182  return true;
183  return false;
184 }
185 
186 // Returns number of channels available for type
188 {
189  if(type != AI && type != AO && type != DIO)
190  return 0;
191 
192  return subdevice[type].count;
193 }
194 
196 {
197  if(channel >= getChannelCount(type))
198  return false;
199 
200  return subdevice[type].chan[channel].active;
201 }
202 
203 int AnalogyDevice::setChannelActive(type_t type,index_t channel,bool state)
204 {
205  if(channel >= getChannelCount(type))
206  return -EINVAL;
207 
208  if(type == AI)
209  output(channel) = 0.0;
210 
211  if(subdevice[type].chan[channel].active && !state)
212  --subdevice[type].active;
213  else if(!subdevice[type].chan[channel].active && state)
214  ++subdevice[type].active;
215 
216  subdevice[type].chan[channel].active = state;
217  return 0;
218 }
219 
221 {
222  if(!analog_exists(type,channel))
223  return 0;
224 
225  int err = 0;
226  a4l_chinfo_t *chinfo;
227  a4l_desc_t d = dsc; // Copy descriptior because method is const
228 
229  err = a4l_get_chinfo(&d, subdevice[type].id, channel, &chinfo);
230  if (err < 0)
231  return 0;
232 
233  return static_cast<index_t>(chinfo->nb_rng);
234 }
235 
237 {
238  if(!analog_exists(type,channel))
239  return 0;
240 
241  return 4;
242 }
243 
245 {
246  if(!analog_exists(type,channel))
247  return 0;
248 
249  return 2;
250 }
251 
253 {
254  if(!analog_exists(type,channel))
255  return 0;
256 
257  return subdevice[type].chan[channel].analog.downsample;
258 }
259 
260 std::string AnalogyDevice::getAnalogRangeString(type_t type,index_t channel,index_t index) const
261 {
262  if(!analog_exists(type,channel) || !(index < getAnalogRangeCount(type,channel)))
263  return "";
264 
265  std::ostringstream rangeString;
266  int err = 0;
267  a4l_rnginfo_t *range;
268  a4l_desc_t d = dsc; // Copy descriptior because method is const
269 
270  err = a4l_get_rnginfo(&d, subdevice[type].id, channel, index, &range);
271  if (err < 0)
272  return "";
273 
274  rangeString << (double)range->min/1000000 << " to " << (double)range->max/1000000;
275  return rangeString.str();
276 }
277 
278 std::string AnalogyDevice::getAnalogReferenceString(type_t type,index_t channel,index_t index) const
279 {
280  if(!analog_exists(type,channel) || !(index < getAnalogReferenceCount(type,channel)))
281  return "";
282 
283  switch(index)
284  {
285  case 0:
286  return "Ground";
287  case 1:
288  return "Common";
289  case 2:
290  return "Differential";
291  case 3:
292  return "Other";
293  default:
294  return "";
295  }
296 }
297 
298 std::string AnalogyDevice::getAnalogUnitsString(type_t type,index_t channel,index_t index) const
299 {
300  if(!analog_exists(type,channel) || !(index < getAnalogUnitsCount(type,channel)))
301  return "";
302 
303  switch(index)
304  {
305  case 0:
306  return "Volts";
307  case 1:
308  return "Amps";
309  default:
310  return "";
311  }
312 }
313 
315 {
316  if(!analog_exists(type,channel))
317  return 0-1;
318 
319  return subdevice[type].chan[channel].analog.range;
320 }
321 
323 {
324  if(!analog_exists(type,channel))
325  return 0-1;
326 
327  return subdevice[type].chan[channel].analog.reference;
328 }
329 
331 {
332  if(!analog_exists(type,channel))
333  return 0-1;
334 
335  return subdevice[type].chan[channel].analog.units;
336 }
337 
339 {
340  if(!analog_exists(type,channel))
341  return 0-1;
342 
343  return subdevice[type].chan[channel].analog.offsetunits;
344 }
345 
346 double AnalogyDevice::getAnalogGain(type_t type,index_t channel) const
347 {
348  if(!analog_exists(type,channel))
349  return 0;
350 
351  return subdevice[type].chan[channel].analog.gain;
352 }
353 
355 {
356  if(!analog_exists(type,channel))
357  return 0;
358 
359  return subdevice[type].chan[channel].analog.zerooffset;
360 }
361 
363 {
364  if(!analog_exists(type,channel) || !(index < getAnalogRangeCount(type,channel)))
365  return -EINVAL;
366 
367  channel_t *chan = &subdevice[type].chan[channel];
368  int err = 0;
369  a4l_rnginfo_t *range;
370 
371  err = a4l_get_rnginfo(&dsc, subdevice[type].id, channel, index, &range);
372  if (err < 0)
373  return -EINVAL;
374 
375  chan->analog.range = index;
376  chan->analog.conv = (range->max-range->min)/1e6/chan->analog.maxdata;
377  chan->analog.offset = -range->min/chan->analog.conv/1e6;
378 
379  /*
380  * Save ourselves an extra division each timestep in the fast path.
381  */
382  if(type == AO)
383  chan->analog.conv = 1/chan->analog.conv;
384 
385  return 0;
386 }
387 
389 {
390  if(!analog_exists(type,channel) || !(index < getAnalogReferenceCount(type,channel)))
391  return -EINVAL;
392 
393  subdevice[type].chan[channel].analog.reference = index;
394  return 0;
395 }
396 
398 {
399  if(!analog_exists(type,channel) || !(index < getAnalogUnitsCount(type,channel)))
400  return -EINVAL;
401 
402  subdevice[type].chan[channel].analog.units = index;
403  return 0;
404 }
405 
407 {
408  if(!analog_exists(type,channel) || !(index < getAnalogUnitsCount(type,channel)))
409  return -EINVAL;
410 
411  subdevice[type].chan[channel].analog.offsetunits = index;
412  return 0;
413 }
414 
415 int AnalogyDevice::setAnalogZeroOffset(type_t type,index_t channel,double offset)
416 {
417  if(!analog_exists(type,channel))
418  return -EINVAL;
419 
420  subdevice[type].chan[channel].analog.zerooffset = offset;
421  return 0;
422 }
423 
424 int AnalogyDevice::setAnalogGain(type_t type,index_t channel,double gain)
425 {
426  if(!analog_exists(type,channel))
427  return -EINVAL;
428 
429  subdevice[type].chan[channel].analog.gain = gain;
430  return 0;
431 }
432 
434  if(!analog_exists(type,channel))
435  return -EINVAL;
436 
437  subdevice[type].chan[channel].analog.calOffset = value;
438  return 0;
439 }
440 
442 {
443  if(!analog_exists(type,channel))
444  return -EINVAL;
445 
446  return subdevice[type].chan[channel].analog.calOffset;
447 }
448 
449 int AnalogyDevice::setAnalogDownsample(type_t type, index_t channel, size_t downsample_rate)
450 {
451  if(!analog_exists(type,channel))
452  return -EINVAL;
453 
454  subdevice[type].chan[channel].analog.downsample = downsample_rate;
455  return 0;
456 }
457 
459 {
460  if(!analog_exists(type,channel))
461  return -EINVAL;
462 
463  subdevice[type].chan[channel].analog.counter = 0;
464  return 0;
465 }
466 
467 // Return the direction of the selected digital channel
469 {
470  if(channel >= subdevice[DIO].count)
471  return DAQ::INPUT;
472 
473  return subdevice[DIO].chan[channel].digital.direction;
474 }
475 
476 // Enable digital channel with specific direction
478 {
479  if(channel >= subdevice[DIO].count)
480  return -EINVAL;
481 
482  subdevice[DIO].chan[channel].digital.direction = direction;
483 
484  if(direction == DAQ::INPUT)
485  return a4l_config_subd(&dsc, subdevice[DIO].id, A4L_INSN_CONFIG_DIO_INPUT, channel);
486  else if(direction == DAQ::OUTPUT)
487  return a4l_config_subd(&dsc, subdevice[DIO].id, A4L_INSN_CONFIG_DIO_OUTPUT, channel);
488 
489  return -EINVAL;
490 }
491 
492 // Acquire data
494 {
495  lsampl_t sample = 0;
496  double value = 0;
497  int ref = 0;
498  int size = 0;
499  analog_channel_t *channel;
500  a4l_chinfo_t *chinfo;
501  a4l_rnginfo_t *rnginfo;
502  int err = 0;
503 
504  for(size_t i=0; i < subdevice[AI].count; ++i)
505  if(subdevice[AI].chan[i].active)
506  {
507  channel = &subdevice[AI].chan[i].analog;
508  if(!channel->counter++)
509  {
510 
511  // Get analogy reference
512  switch (channel->reference)
513  {
514  case 0:
515  ref = AREF_GROUND;
516  break;
517  case 1:
518  ref = AREF_COMMON;
519  break;
520  case 2:
521  ref = AREF_DIFF;
522  break;
523  case 3:
524  ref = AREF_OTHER;
525  break;
526  }
527 
528  // Get channel info
529  err = a4l_get_chinfo(&dsc, subdevice[AI].id, i, &chinfo);
530  if(err < 0)
531  rt_fprintf(stderr, "analogy_device::read::a4l_get_chinfo error: %d\n", err);
532 
533  // Get channel range info
534  err = a4l_get_rnginfo(&dsc, subdevice[AI].id, i, channel->range, &rnginfo);
535  if(err < 0)
536  rt_fprintf(stderr, "analogy_device::read::a4l_get_rnginfo error: %d\n", err);
537  size = a4l_sizeof_chan(chinfo);
538 
539  // Read 1 data sample via synchronous acq
540  err = a4l_sync_read(&dsc, subdevice[AI].id, PACK(i,channel->range,ref), 0, &sample, size);
541  if(err < 0)
542  rt_fprintf(stderr, "analogy_device::read::a4l_sync_read error: %d\n", err);
543 
544  // Convert to decimal via a4l
545  err = a4l_rawtod(chinfo, rnginfo, &value, &sample, 1);
546  if(err < 0)
547  rt_fprintf(stderr, "analogy_device::read::a4l_rawtod error: %d\n", err);
548 
549  // Gain, convert, and push into IO pipe
550  output(i) = channel->gain * value + channel->zerooffset - channel->calOffset;
551  }
552  channel->counter %= channel->downsample;
553  }
554 
555  size_t offset = getChannelCount(AI);
556  unsigned int data = 0, mask = 0;
557 
558  // Create mask using only enabled digital channels
559  for(size_t i=0; i < subdevice[DIO].count; ++i)
560  if(subdevice[DIO].chan[i].active && subdevice[DIO].chan[i].digital.direction == DAQ::INPUT)
561  mask |= (1<<i);
562 
563  // Read all data and output it according to channel activity
564  err = a4l_sync_dio(&dsc, subdevice[DIO].id, &mask, &data);
565  if(err < 0)
566  rt_fprintf(stderr, "analogy_device::read::a4l_sync_dio error: %d\n", err);
567 
568  // Read only enabled digital channels one by one with mask for each bit
569  for(size_t i=0; i < subdevice[DIO].count; ++i)
570  if(subdevice[DIO].chan[i].active && subdevice[DIO].chan[i].digital.direction == DAQ::INPUT)
571  {
572  mask = (1<<i);
573  output(i+offset) = (data & mask) == 0 ? 0 : 5;
574  }
575 }
576 
578 {
579  {
580  double value;
581  lsampl_t sample;
582  analog_channel_t *channel;
583  int ref = 0;
584  int size = 0;
585  a4l_chinfo_t *chinfo;
586  int err = 0;
587 
588  for(size_t i=0; i < subdevice[AO].count; ++i)
589  if(subdevice[AO].chan[i].active)
590  {
591  channel = &subdevice[AO].chan[i].analog;
592  value = round(channel->gain * channel->conv * (input(i) - channel->zerooffset) + channel->offset - channel->calOffset);
593 
594  // Prevent wrap around in the data units.
595  if(value > channel->maxdata)
596  value = channel->maxdata;
597  else if(value < 0.0)
598  value = 0.0;
599  sample = static_cast<lsampl_t>(value);
600 
601  // Get anaolgy reference
602  switch (channel->reference)
603  {
604  case 0:
605  ref = A4L_CHAN_AREF_GROUND;
606  break;
607  case 1:
608  ref = A4L_CHAN_AREF_COMMON;
609  break;
610  case 2:
611  ref = A4L_CHAN_AREF_DIFF;
612  break;
613  case 3:
614  ref = A4L_CHAN_AREF_OTHER;
615  break;
616  }
617  // Get channel size
618  err = a4l_get_chinfo(&dsc, subdevice[AO].id, i, &chinfo);
619  if(err < 0)
620  rt_fprintf(stderr, "analogy_device::write::a4l_get_chinfo error: %d\n", err);
621  size = a4l_sizeof_chan(chinfo);
622 
623  // Write sample
624  err = a4l_sync_write(&dsc, subdevice[AO].id, PACK(i,channel->range,ref), 0, &sample, size);
625  if(err < 0)
626  rt_fprintf(stderr, "analogy_device::read::a4l_sync_write error: %d\n", err);
627  }
628  }
629  {
630  size_t offset = getChannelCount(AO);
631  int value = 0;
632  unsigned int data = 0, mask = 0;
633 
634  // Create mask and data buffer with bits to be set
635  for(size_t i=0; i < subdevice[DIO].count; ++i)
636  {
637  value = input(i+offset) != 0.0;
638  if(subdevice[DIO].chan[i].active && subdevice[DIO].chan[i].digital.direction == DAQ::OUTPUT && subdevice[DIO].chan[i].digital.previous_value != value)
639  {
640  subdevice[DIO].chan[i].digital.previous_value = value;
641  data |= value == 0 ? (0<<i) : (1<<i); // Toggle the i-th bit for modification (set 0 or 1)
642  mask |= (1<<i); // Set i-th bit to specify channels to modify
643  }
644  }
645  // Write the data according to the mask
646  if (mask)
647  a4l_sync_dio(&dsc, subdevice[DIO].id, &mask, &data);
648  }
649 }
650 
652 {
653  for(size_t i = 0; i < subdevice[AI].count && i < static_cast<size_t>(s.loadInteger("AI Count")); ++i)
654  {
655  std::ostringstream str;
656  str << i;
657  setChannelActive(AI,i,s.loadInteger(str.str()+" AI Active"));
658  setAnalogRange(AI,i,s.loadInteger(str.str()+" AI Range"));
659  setAnalogReference(AI,i,s.loadInteger(str.str()+" AI Reference"));
660  setAnalogUnits(AI,i,s.loadInteger(str.str()+" AI Units"));
661  setAnalogGain(AI,i,s.loadDouble(str.str()+" AI Gain"));
662  setAnalogZeroOffset(AI,i,s.loadDouble(str.str()+" AI Zero Offset"));
663  if(s.loadDouble(str.str()+" AI Calibration Value"))
664  setAnalogCalibrationValue(AI,i,s.loadDouble(str.str()+" AI Calibration Value"));
665  if(s.loadInteger(str.str()+" AI Downsample"))
666  setAnalogDownsample(AI,i,s.loadInteger(str.str()+" AI Downsample"));
667  }
668 
669  for(size_t i = 0; i < subdevice[AO].count && i < static_cast<size_t>(s.loadInteger("AO Count")); ++i)
670  {
671  std::ostringstream str;
672  str << i;
673  setChannelActive(AO,i,s.loadInteger(str.str()+" AO Active"));
674  setAnalogRange(AO,i,s.loadInteger(str.str()+" AO Range"));
675  setAnalogReference(AO,i,s.loadInteger(str.str()+" AO Reference"));
676  setAnalogUnits(AO,i,s.loadInteger(str.str()+" AO Units"));
677  setAnalogGain(AO,i,s.loadDouble(str.str()+" AO Gain"));
678  setAnalogZeroOffset(AO,i,s.loadDouble(str.str()+" AO Zero Offset"));
679  if(s.loadDouble(str.str()+" AO Calibration Value"))
680  setAnalogCalibrationValue(AO,i,s.loadDouble(str.str()+" AO Calibration Value"));
681  }
682 
683  for(size_t i = 0; i < subdevice[DIO].count && i < static_cast<size_t>(s.loadInteger("DIO Count")); ++i)
684  {
685  std::ostringstream str;
686  str << i;
687  setChannelActive(DIO,i,s.loadInteger(str.str()+" DIO Active"));
688  setDigitalDirection(i,static_cast<DAQ::direction_t>(s.loadInteger(str.str()+" DIO Direction")));
689  }
690 }
691 
693 {
694  s.saveInteger("AI Count",subdevice[AI].count);
695  for(size_t i = 0; i < subdevice[AI].count; ++i)
696  {
697  std::ostringstream str;
698  str << i;
699  s.saveInteger(str.str()+" AI Active",getChannelActive(AI,i));
700  s.saveDouble(str.str()+" AI Calibration Value",getAnalogCalibrationValue(AI,i));
701  s.saveInteger(str.str()+" AI Range",getAnalogRange(AI,i));
702  s.saveInteger(str.str()+" AI Reference",getAnalogReference(AI,i));
703  s.saveInteger(str.str()+" AI Units",getAnalogUnits(AI,i));
704  s.saveDouble(str.str()+" AI Gain",getAnalogGain(AI,i));
705  s.saveDouble(str.str()+" AI Zero Offset",getAnalogZeroOffset(AI,i));
706  s.saveInteger(str.str()+" AI Downsample",getAnalogDownsample(AI,i));
707  }
708 
709  s.saveInteger("AO Count",subdevice[AO].count);
710  for(size_t i = 0; i < subdevice[AO].count; ++i)
711  {
712  std::ostringstream str;
713  str << i;
714  s.saveInteger(str.str()+" AO Active",getChannelActive(AO,i));
715  s.saveDouble(str.str()+" AO Calibration Value",getAnalogCalibrationValue(AO,i));
716  s.saveInteger(str.str()+" AO Range",getAnalogRange(AO,i));
717  s.saveInteger(str.str()+" AO Reference",getAnalogReference(AO,i));
718  s.saveInteger(str.str()+" AO Units",getAnalogUnits(AO,i));
719  s.saveDouble(str.str()+" AO Gain",getAnalogGain(AO,i));
720  s.saveDouble(str.str()+" AO Zero Offset",getAnalogZeroOffset(AO,i));
721  }
722 
723  s.saveInteger("DIO Count",subdevice[DIO].count);
724  for(size_t i = 0; i < subdevice[DIO].count; ++i)
725  {
726  std::ostringstream str;
727  str << i;
728  s.saveInteger(str.str()+" DIO Active",getChannelActive(DIO,i));
729  s.saveInteger(str.str()+" DIO Direction",subdevice[DIO].chan[i].digital.direction);
730  }
731 }
AnalogyDevice::setAnalogCounter
int setAnalogCounter(DAQ::type_t, DAQ::index_t)
Definition: analogy_device.cpp:458
AnalogyDevice::getAnalogUnitsString
std::string getAnalogUnitsString(DAQ::type_t, DAQ::index_t, DAQ::index_t) const
Definition: analogy_device.cpp:298
A4L_CHAN_AREF_COMMON
#define A4L_CHAN_AREF_COMMON
Definition: analogy_device.cpp:25
AnalogyDevice::getAnalogUnitsCount
size_t getAnalogUnitsCount(DAQ::type_t, DAQ::index_t) const
Definition: analogy_device.cpp:244
DAQ::type_t
type_t
Definition: daq.h:38
ERROR_MSG
void ERROR_MSG(const std::string &errmsg,...)
Definition: debug.cpp:27
AnalogyDevice::setAnalogRange
int setAnalogRange(DAQ::type_t, DAQ::index_t, DAQ::index_t)
Definition: analogy_device.cpp:362
AnalogyDevice::setAnalogOffsetUnits
int setAnalogOffsetUnits(DAQ::type_t, DAQ::index_t, DAQ::index_t)
Definition: analogy_device.cpp:406
AnalogyDevice::setAnalogUnits
int setAnalogUnits(DAQ::type_t, DAQ::index_t, DAQ::index_t)
Definition: analogy_device.cpp:397
A4L_CHAN_AREF_GROUND
#define A4L_CHAN_AREF_GROUND
Definition: analogy_device.cpp:24
AnalogyDevice::getAnalogCalibrationValue
double getAnalogCalibrationValue(DAQ::type_t, DAQ::index_t) const
Definition: analogy_device.cpp:441
DAQ::index_t
unsigned long index_t
Definition: daq.h:49
A4L_CHAN_AREF_OTHER
#define A4L_CHAN_AREF_OTHER
Definition: analogy_device.cpp:27
Settings::Object::State::loadDouble
double loadDouble(const std::string &name) const
Definition: settings.cpp:61
AnalogyDevice::setAnalogDownsample
int setAnalogDownsample(DAQ::type_t, DAQ::index_t, size_t)
Definition: analogy_device.cpp:449
AnalogyDevice::getChannelCount
size_t getChannelCount(DAQ::type_t) const
Definition: analogy_device.cpp:187
AnalogyDevice::setAnalogGain
int setAnalogGain(DAQ::type_t, DAQ::index_t, double)
Definition: analogy_device.cpp:424
AnalogyDevice::setAnalogReference
int setAnalogReference(DAQ::type_t, DAQ::index_t, DAQ::index_t)
Definition: analogy_device.cpp:388
AnalogyDevice::setDigitalDirection
int setDigitalDirection(DAQ::index_t, DAQ::direction_t)
Definition: analogy_device.cpp:477
AnalogyDevice::getAnalogDownsample
size_t getAnalogDownsample(DAQ::type_t, DAQ::index_t) const
Definition: analogy_device.cpp:252
AnalogyDevice::write
void write(void)
Definition: analogy_device.cpp:577
AnalogyDevice::doLoad
virtual void doLoad(const Settings::Object::State &)
Definition: analogy_device.cpp:651
A4L_CHAN_AREF_DIFF
#define A4L_CHAN_AREF_DIFF
Definition: analogy_device.cpp:26
Settings::Object::State::saveDouble
void saveDouble(const std::string &name, double)
Definition: settings.cpp:105
AnalogyDevice::getAnalogReferenceString
std::string getAnalogReferenceString(DAQ::type_t, DAQ::index_t, DAQ::index_t) const
Definition: analogy_device.cpp:278
DAQ
DAQ Oriented Classes.
Definition: daq.h:32
AnalogyDevice::setChannelActive
int setChannelActive(DAQ::type_t, DAQ::index_t, bool)
Definition: analogy_device.cpp:203
AnalogyDevice::setAnalogCalibrationValue
int setAnalogCalibrationValue(DAQ::type_t, DAQ::index_t, double)
Definition: analogy_device.cpp:433
AnalogyDevice::AnalogyDevice
AnalogyDevice(a4l_desc_t *, std::string, IO::channel_t *, size_t)
Definition: analogy_device.cpp:31
AnalogyDevice::read
void read(void)
Definition: analogy_device.cpp:493
AnalogyDevice::~AnalogyDevice
~AnalogyDevice(void)
Definition: analogy_device.cpp:170
AnalogyDevice::getAnalogReferenceCount
size_t getAnalogReferenceCount(DAQ::type_t, DAQ::index_t) const
Definition: analogy_device.cpp:236
IO::Block::output
double output(size_t index) const
Definition: io.cpp:129
AnalogyDevice::setAnalogZeroOffset
int setAnalogZeroOffset(DAQ::type_t, DAQ::index_t, double)
Definition: analogy_device.cpp:415
AnalogyDevice::getChannelActive
bool getChannelActive(DAQ::type_t, DAQ::index_t) const
Definition: analogy_device.cpp:195
IO::channel_t
Definition: io.h:56
AnalogyDevice::getAnalogRangeCount
size_t getAnalogRangeCount(DAQ::type_t, DAQ::index_t) const
Definition: analogy_device.cpp:220
Settings::Object::State::loadInteger
int loadInteger(const std::string &name) const
Definition: settings.cpp:77
DAQ::direction_t
direction_t
Definition: daq.h:57
AnalogyDevice::getAnalogZeroOffset
double getAnalogZeroOffset(DAQ::type_t, DAQ::index_t) const
Definition: analogy_device.cpp:354
AnalogyDevice::getAnalogRange
DAQ::index_t getAnalogRange(DAQ::type_t, DAQ::index_t) const
Definition: analogy_device.cpp:314
IO::Block::input
double input(size_t index) const
Definition: io.cpp:118
AnalogyDevice::getAnalogGain
double getAnalogGain(DAQ::type_t, DAQ::index_t) const
Definition: analogy_device.cpp:346
analogy_device.h
DAQ::DIO
@ DIO
Definition: daq.h:42
Settings::Object::State
Definition: settings.h:62
Settings::Object::State::saveInteger
void saveInteger(const std::string &name, int)
Definition: settings.cpp:112
AnalogyDevice::getAnalogReference
DAQ::index_t getAnalogReference(DAQ::type_t, DAQ::index_t) const
Definition: analogy_device.cpp:322
AnalogyDevice::getDigitalDirection
DAQ::direction_t getDigitalDirection(DAQ::index_t) const
Definition: analogy_device.cpp:468
AnalogyDevice::getAnalogRangeString
std::string getAnalogRangeString(DAQ::type_t, DAQ::index_t, DAQ::index_t) const
Definition: analogy_device.cpp:260
AnalogyDevice::doSave
virtual void doSave(Settings::Object::State &) const
Definition: analogy_device.cpp:692
DAQ::INPUT
@ INPUT
Definition: daq.h:59
DAQ::AI
@ AI
Definition: daq.h:40
DAQ::OUTPUT
@ OUTPUT
Definition: daq.h:60
DAQ::Device
Definition: daq.h:139
DAQ::AO
@ AO
Definition: daq.h:41
AnalogyDevice::getAnalogUnits
DAQ::index_t getAnalogUnits(DAQ::type_t, DAQ::index_t) const
Definition: analogy_device.cpp:330
RT::Device::setActive
void setActive(bool)
Definition: rt.cpp:130
AnalogyDevice::getAnalogOffsetUnits
DAQ::index_t getAnalogOffsetUnits(DAQ::type_t, DAQ::index_t) const
Definition: analogy_device.cpp:338
debug.h