CARMA C++
ComediDevice.h
1 #ifndef CARMA_LINELENGTH_COMEDIDEVICE_H
2 #define CARMA_LINELENGTH_COMEDIDEVICE_H
3 
4 #include <carma/util/PthreadMutex.h>
5 #include <carma/util/PthreadCond.h>
6 
7 #include <boost/circular_buffer.hpp>
8 #include <boost/shared_ptr.hpp>
9 #include <comedilib.h>
10 #include <vector>
11 
12 namespace carma {
13 namespace linelength {
14 
15 /*
16  * Simple container to hold all information about a sample from the DAQ card,
17  * as obtained by the comedi library.
18  *
19  * The samples are already converted to volts using the units specified when
20  * the capture was configured.
21  *
22  * TODO FIXME: Is this a better data structure?
23  * typedef std::vector<double> DoubleVector;
24  * std::vector<DoubleVector> scans;
25  *
26  * Then each vector in 'scans' has equal length, and is exactly comparable to
27  * a single scan from the hardware. Maybe this makes the higher level software
28  * easier to reason about. No weird index manipulation and multiplications
29  * are needed!
30  */
31 struct ComediSample
32 {
33  ComediSample(const unsigned int nchannels, const unsigned int nsamples);
34  std::vector<double> calculateAverage() const;
35 
36  const unsigned int nchannels;
37  const unsigned int nsamples;
38 
39  std::vector<double> samples;
40  std::vector<bool> dio;
41 };
42 
43 typedef boost::shared_ptr<struct ComediSample> ComediSamplePtr;
44 
45 /*
46  * Class to control the comedi library/driver connected to a NI PXE-6031E
47  * Data Acquisition card. Only the features necessary for use by CARMA are
48  * exposed.
49  *
50  * No Digital I/O write capability has been exposed, since no CARMA applications
51  * have found it necessary. If you do find this necessary in the future, I
52  * suggest that this file be turned into a simple set of routines (not a class)
53  * which wrap some comedi functionality. Then leave the rest to the user. The
54  * comedi library is very simple to use once you read the documentation.
55  *
56  * This driver attempts to let you have full control of the streaming data
57  * access from the card by exposing the raw comedi interface. Anything other
58  * interface just looked like intentional obfuscation.
59  *
60  * You have to know how the card is wired up to use this class.
61  */
62 class ComediDevice
63 {
64  public:
65  // Open the specified device file and configure the comedi device
66  ComediDevice(const std::string &name);
67  ~ComediDevice();
68 
69  // Find the optimal comedi range index which contains the specified min
70  // and max voltages.
71  int findRange(const double min, const double max);
72 
73  // Use external reference with specified period (default to 10MHz)
74  void setupExternalReference(unsigned int period_ns = 100);
75 
76  // Configure device for operation and begin data capture
77  void startCapture(comedi_cmd *cmd, unsigned int nsamples);
78 
79  // Wait for next sample (comprised of one or more scans) to complete or
80  // timeout. Samples are converted to physical units before they are
81  // returned from this function.
82  ComediSamplePtr waitForNextSample(const struct timespec &ts);
83 
84  // thread entry point
85  static void thread(ComediDevice &This) { This.run(); };
86 
87  private:
88 
89  // thread data acquisition function
90  void run();
91 
92  // error handling
93  void clearExistingData();
94  void restartCapture();
95 
96  // data acquisition
97  void readSamples();
98  void readDIO(ComediSamplePtr buf);
99  void convertSamples(ComediSamplePtr buf);
100 
101  const std::string filename_;
102  comedi_t *device_;
103  comedi_cmd *cmd_;
104  bool capture_started_;
105 
106  // saved ranges for automatic unit conversion
107  std::vector<comedi_range *> ranges_;
108  std::vector<lsampl_t> maxdatas_;
109 
110  // samples which are currently being accumulated
111  unsigned int nchannels_;
112  unsigned int nsamples_;
113  std::vector<sampl_t> samples_;
114 
115  // circular buffer to hold several pending samples
116  boost::circular_buffer<ComediSamplePtr> circbuf_;
119 };
120 
121 } // namespace linelength
122 } // namespace carma
123 
124 #endif /* CARMA_LINELENGTH_COMEDIDEVICE_H */
125 
126 /* vim: set ts=4 sts=4 sw=4 et tw=92: */
A simple wrapper class that makes use of ::pthread_cond_t easier in a C++ world.
Definition: PthreadCond.h:43
A simple wrapper class that makes use of ::pthread_mutex_t easier in a C++ world. ...
Definition: PthreadMutex.h:41