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