RTXI  3.0.0
The Real-Time eXperiment Interface Reference Manual
analogy_driver.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 <sstream>
20 
21 #include <analogy_device.h>
22 #include <analogy_driver.h>
23 #include <debug.h>
24 
25 extern "C" Plugin::Object* createRTXIPlugin(void)
26 {
27  return new AnalogyDriver();
28 }
29 
31 {
32  for (std::list<AnalogyDevice*>::iterator i = devices.begin();
33  i != devices.end();
34  ++i)
35  delete *i;
36 }
37 
38 DAQ::Device* AnalogyDriver::createDevice(const std::list<std::string>& args)
39 {
40  int err = 0;
41  a4l_desc_t dsc;
42  a4l_sbinfo_t* sbinfo;
43  std::string name = args.front();
44 
45  err = a4l_open(&dsc, name.c_str());
46  if (err < 0) {
47  ERROR_MSG("AnalogyDriver::createDevice : unable to open %s (err=%d).\n",
48  name.c_str(),
49  err);
50  return 0;
51  }
52 
53  // Allocate a buffer to get more info (subd, chan, rng)
54  dsc.sbdata = malloc(dsc.sbsize);
55  if (dsc.sbdata == NULL) {
56  err = -ENOMEM;
57  ERROR_MSG("AnalogyDriver: info buffer allocation failed\n");
58  return 0;
59  }
60 
61  // Get this data
62  err = a4l_fill_desc(&dsc);
63  if (err < 0) {
64  ERROR_MSG(
65  "AnalogyDriver: a4l_fill_desc failed (err=%d)\nPlease run "
66  "rtxi_load_analogy script in scripts directory.\n",
67  err);
68  return 0;
69  }
70 
71  // We need to find each subdevice index manually since idx_*_subd often fails
72  // Go over all subdevices and save the indexes of the first AI, AO and DIO
73  int idx_ai = -1;
74  int idx_ao = -1;
75  int idx_dio = -1;
76  for (int i = 0; i < dsc.nb_subd; i++) {
77  err = a4l_get_subdinfo(&dsc, i, &sbinfo);
78  if (err != 0) {
79  ERROR_MSG(
80  "AnalogyDriver: a4l_get_subd_info failed, wrong subdevice index %i "
81  "(err=%d)\n",
82  err,
83  i);
84  return 0;
85  }
86  // Assign index; save just the first device if many
87  if (((sbinfo->flags & A4L_SUBD_TYPES) == A4L_SUBD_AI) && (idx_ai < 0))
88  idx_ai = i;
89  else if (((sbinfo->flags & A4L_SUBD_TYPES) == A4L_SUBD_AO) && (idx_ao < 0))
90  idx_ao = i;
91  else if (((sbinfo->flags & A4L_SUBD_TYPES) == A4L_SUBD_DIO)
92  && (idx_dio < 0))
93  idx_dio = i;
94  }
95 
96  size_t count[5] = {
97  0,
98  0,
99  0,
100  0,
101  0,
102  };
103  err = a4l_get_subdinfo(&dsc, idx_ai, &sbinfo);
104  if (err == 0)
105  count[0] = sbinfo->nb_chan;
106  err = a4l_get_subdinfo(&dsc, idx_ao, &sbinfo);
107  if (err == 0)
108  count[1] = sbinfo->nb_chan;
109  err = a4l_get_subdinfo(&dsc, idx_dio, &sbinfo);
110  if (err == 0)
111  count[2] = sbinfo->nb_chan;
112 
113  if (!(count[0] + count[1] + count[2] + count[3] + count[4])) {
114  ERROR_MSG(
115  "AnalogyDriver::createDevice : no Analogy device configured on %s.\n",
116  name.c_str());
117  a4l_close(&dsc);
118  return 0;
119  }
120 
121  IO::channel_t channel[count[0] + count[1] + 2 * count[2]];
122  for (size_t i = 0; i < count[0]; ++i) {
123  std::ostringstream name;
124  name << "Analog Input " << i;
125  channel[i].name = name.str();
126  channel[i].description = "";
127  channel[i].flags = IO::OUTPUT;
128  }
129  for (size_t i = count[0]; i < count[0] + count[1]; ++i) {
130  std::ostringstream name;
131  name << "Analog Output " << i - count[0];
132  channel[i].name = name.str();
133  channel[i].description = "";
134  channel[i].flags = IO::INPUT;
135  }
136  for (size_t i = count[0] + count[1]; i < count[0] + count[1] + count[2]; ++i)
137  {
138  std::ostringstream name;
139  name << "Digital I/O " << i - count[0] - count[1];
140  channel[i].name = name.str();
141  channel[i].description = "";
142  channel[i].flags = IO::OUTPUT;
143  }
144  for (size_t i = count[0] + count[1] + count[2];
145  i < count[0] + count[1] + 2 * count[2];
146  ++i)
147  {
148  std::ostringstream name;
149  name << "Digital I/O " << i - count[0] - count[1] - count[2];
150  channel[i].name = name.str();
151  channel[i].description = "";
152  channel[i].flags = IO::INPUT;
153  }
154  for (size_t i = count[0] + count[1] + 2 * count[2];
155  i < count[0] + count[1] + 2 * count[2] + count[3];
156  ++i)
157  {
158  std::ostringstream name;
159  name << "Digital Input " << i - count[0] - count[1] - 2 * count[2];
160  channel[i].name = name.str();
161  channel[i].description = "";
162  channel[i].flags = IO::OUTPUT;
163  }
164  for (size_t i = count[0] + count[1] + 2 * count[2] + count[3];
165  i < count[0] + count[1] + 2 * count[2] + count[3] + count[4];
166  ++i)
167  {
168  std::ostringstream name;
169  name << "Digital Output "
170  << i - count[0] - count[1] - 2 * count[2] - count[3];
171  channel[i].name = name.str();
172  channel[i].description = "";
173  channel[i].flags = IO::INPUT;
174  }
175 
176  AnalogyDevice* dev = new AnalogyDevice(
177  &dsc, name, channel, count[0] + count[1] + 2 * count[2]);
178  devices.push_back(dev);
179  return dev;
180 
181  return 0;
182 }
183 
184 void AnalogyDriver::doLoad(const Settings::Object::State& s)
185 {
186  for (size_t i = 0, end = s.loadInteger("Num Devices"); i < end; ++i) {
187  std::list<std::string> args;
188  args.push_back(s.loadString(QString::number(i).toStdString()));
189  DAQ::Device* device = createDevice(args);
190  if (device)
191  device->load(s.loadState(QString::number(i).toStdString()));
192  }
193 }
194 
195 void AnalogyDriver::doSave(Settings::Object::State& s) const
196 {
197  s.saveInteger("Num Devices", devices.size());
198  size_t n = 0;
199  for (std::list<AnalogyDevice*>::const_iterator i = devices.begin(),
200  end = devices.end();
201  i != end;
202  ++i)
203  {
204  std::ostringstream str;
205  str << n++;
206  s.saveString(str.str(), (*i)->getName());
207  s.saveState(str.str(), (*i)->save());
208  }
209 }
Plugin::Object * createRTXIPlugin(void)
virtual void doLoad(const State &)
virtual ~AnalogyDriver(void)
virtual DAQ::Device * createDevice(const std::list< std::string > &)
virtual void doSave(State &) const
void ERROR_MSG(const std::string &errmsg, Args... args)
Definition: debug.hpp:36
@ INPUT
Definition: io.hpp:54
@ OUTPUT
Definition: io.hpp:53
std::string name
Definition: io.hpp:70