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