pulserdrivernidaqmx.h
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13 ***************************************************************************/
14 #ifndef PULSERDRIVERNIDAQMX_H_
15 #define PULSERDRIVERNIDAQMX_H_
16 
17 #include "pulserdriver.h"
18 
19 #include "nidaqmxdriver.h"
20 
21 #include <vector>
22 
23 #ifdef _MSC_VER
24 typedef ptrdiff_t ssize_t;
25 #endif
26 
27 class XNIDAQmxPulser : public XNIDAQmxDriver<XPulser> {
28 public:
29  XNIDAQmxPulser(const char *name, bool runtime,
30  Transaction &tr_meas, const shared_ptr<XMeasure> &meas);
31  virtual ~XNIDAQmxPulser();
32 
33  //! time resolution [ms]
34  virtual double resolution() const {return m_resolutionDO;}
35 
36 private:
37  enum { NUM_AO_CH = 2};
38  enum { CAL_POLY_ORDER = 4};
39  typedef int16 tRawAO;
40  typedef struct {tRawAO ch[NUM_AO_CH];} tRawAOSet;
41  typedef uInt16 tRawDO;
42  struct GenPattern {
43  GenPattern(uint32_t pat, uint64_t next) :
44  pattern(pat), tonext(next) {}
45  uint32_t pattern;
46  uint64_t tonext; //!< in samps for buffer.
47  };
48 public:
49  struct Payload : public XNIDAQmxDriver<XPulser>::Payload {
50  private:
51  friend class XNIDAQmxPulser;
52  //! The pattern passed from \a XPulser to be output.
53  //! \sa createNativePatterns()
54  shared_ptr<std::vector<GenPattern> > m_genPatternListNext;
55  shared_ptr<std::vector<tRawAOSet> > m_genPulseWaveNextAO[PAT_QAM_MASK / PAT_QAM_PHASE];
56  tRawAOSet m_genAOZeroLevelNext;
57  };
58 protected:
59  virtual void open() throw (XKameError &) = 0;
60  virtual void close() throw (XKameError &);
61 
62  double resolutionQAM() const {return m_resolutionAO;}
63  //! \return Existence of AO ports.
64  virtual bool hasQAMPorts() const = 0;
65 
66  virtual const shared_ptr<XNIDAQmxInterface> &intfDO() const {return interface();}
67  virtual const shared_ptr<XNIDAQmxInterface> &intfAO() const {return interface();}
68  virtual const shared_ptr<XNIDAQmxInterface> &intfCtr() const {return interface();}
69 
70  //! Sends patterns to pulser or turns off.
71  virtual void changeOutput(const Snapshot &shot, bool output, unsigned int blankpattern);
72  //! Converts RelPatList to native patterns.
73  virtual void createNativePatterns(Transaction &tr);
74 
75  //! \return Minimum period of pulses [ms]
76  virtual double minPulseWidth() const {return resolution();}
77 
78  void openDO(bool use_ao_clock = false) throw (XKameError &);
79  void openAODO() throw (XKameError &);
80 private:
81  void startPulseGen(const Snapshot &shot) throw (XKameError &);
82  void stopPulseGen();
83  void abortPulseGen();
84 
85  void stopPulseGenFreeRunning(unsigned int blankpattern);
86  void startPulseGenFromFreeRun(const Snapshot &shot);
87 
88  void clearTasks();
89  void setupTasksDO(bool use_ao_clock);
90  void setupTasksAODO();
91 
92  static int32 onTaskDone_(TaskHandle task, int32 status, void*);
93  void onTaskDone(TaskHandle task, int32 status);
94 
95  shared_ptr<std::vector<GenPattern> > m_genPatternList;
96 
97  typedef std::vector<GenPattern>::iterator GenPatternIterator;
98  GenPatternIterator m_genLastPatIt;
99 
100  unsigned int m_genAOIndex; //!< Preserved index for \a m_genPulseWaveAO[], \sa fillBuffer().
101  shared_ptr<XNIDAQmxInterface::SoftwareTrigger> m_softwareTrigger;
102  unsigned int m_pausingBit; //!< Pausing bit triggers counter that stops DO/AO for a certain period.
103  unsigned int m_aswBit;
104  unsigned int m_pausingCount;
105  XString m_pausingCh;
106  XString m_pausingSrcTerm;
107  XString m_pausingGateTerm;
108  unsigned int m_preFillSizeDO; //!< Determines stating condition,\sa m_isThreadWriterReady.
109  unsigned int m_preFillSizeAO;
110  unsigned int m_transferSizeHintDO; //!< Max size of data transfer to DAQmx lib.
111  unsigned int m_transferSizeHintAO;
112  //! During the pattern generation, indicates total # of clocks at the next pattern change that has elapsed from the origin.
113  uint64_t m_genTotalCount;
114  uint64_t m_genRestCount; //!< indicates the remaining # of clocks to the next pattern change.
115  //! During the pattern generation, total # of samplings that has been generated for DO buffered device.
116  //! \a m_genTotalSamps is different from \a m_genTotalCount when pausing clocks are active.
117  uint64_t m_genTotalSamps;
118  uint64_t m_totalWrittenSampsDO, m_totalWrittenSampsAO; //!< # of samps written to DAQmx lib.
119  bool m_running;
120 protected:
121  double m_resolutionDO, m_resolutionAO;
122  TaskHandle m_taskAO, m_taskDO,
123  m_taskDOCtr, m_taskGateCtr;
124 private:
125  enum {PORTSEL_PAUSING = 17};
126  //! Ring buffer storing AO/DO patterns being transfered to DAQmx lib.
127  template <typename T>
128  struct RingBuffer {
129  enum {CHUNK_DIVISOR = 16};
130  void reserve(ssize_t s) {m_data.resize(s); m_curReadPos = 0; m_endOfWritten = 0; m_end = s;}
131  const T*curReadPos() {
132  if((m_endOfWritten < m_curReadPos) && (m_curReadPos == m_end))
133  m_curReadPos = 0;
134  return &m_data[m_curReadPos];
135  }
136  ssize_t writtenSize() const {
137  ssize_t end_of_written = m_endOfWritten;
138  if(m_curReadPos <= end_of_written) {
139  return end_of_written - m_curReadPos;
140  }
141  return m_end - m_curReadPos;
142  }
143  //! Tags as read.
144  void finReading(ssize_t size_read) {
145  ssize_t p = m_curReadPos + size_read;
146  m_curReadPos = p;
147  }
148  //! Size of reserved writing space beginning with \a curWritePos().
149  ssize_t chunkSize() const {
150  return m_data.size() / CHUNK_DIVISOR;
151  }
152  T *curWritePos() {
153  ssize_t readpos = m_curReadPos;
154  ssize_t write_reserve_end = m_endOfWritten + chunkSize();
155  if(write_reserve_end > m_data.size()) {
156  if(readpos == 0)
157  return NULL;
158  m_end = (ssize_t)m_endOfWritten;
159  m_endOfWritten = 0;
160  write_reserve_end = m_endOfWritten + chunkSize();
161  }
162  if((readpos > m_endOfWritten) && (readpos <= write_reserve_end))
163  return NULL; //not enough space.
164  return &m_data[m_endOfWritten];
165  }
166  //! Tags as written.
167  void finWriting(T *pend) {
168  assert(pend - &m_data[m_endOfWritten] <= chunkSize());
169  ssize_t pos = pend - &m_data[0];
170  m_endOfWritten = pos;
171  }
172  private:
173  atomic<ssize_t> m_curReadPos, m_endOfWritten;
174  atomic<ssize_t> m_end;
175  std::vector<T> m_data;
176  };
177 
178  RingBuffer<tRawDO> m_patBufDO; //!< Buffer containing generated patterns for DO.
179  RingBuffer<tRawAOSet> m_patBufAO; //!< Buffer containing generated patterns for AO.
180 
181  shared_ptr<std::vector<tRawAOSet> > m_genPulseWaveAO[PAT_QAM_MASK / PAT_QAM_PHASE];
182  tRawAOSet m_genAOZeroLevel;
183 
184  double m_coeffAODev[NUM_AO_CH][CAL_POLY_ORDER];
185  double m_upperLimAO[NUM_AO_CH];
186  double m_lowerLimAO[NUM_AO_CH];
187  //! Converts voltage to an internal value for DAC and compensates it.
188  inline tRawAOSet aoVoltToRaw(const double poly_coeff[NUM_AO_CH][CAL_POLY_ORDER], const std::complex<double> &volt);
189 
190  shared_ptr<XThread<XNIDAQmxPulser> > m_threadWriter;
191  bool m_isThreadWriterReady; //!< indicates DAQmx lib. has been (partially) filled with generated patterns.
192  //! \return Succeeded or not.
193  template <bool UseAO>
194  inline bool fillBuffer();
195  void rewindBufPos(double ms_from_gen_pos);
196  //! \return Counts being sent.
197  ssize_t writeToDAQmxDO(const tRawDO *pDO, ssize_t samps);
198  ssize_t writeToDAQmxAO(const tRawAOSet *pAO, ssize_t samps);
199  void startBufWriter();
200  void stopBufWriter();
201  void *executeWriter(const atomic<bool> &);
202  void *executeFillBuffer(const atomic<bool> &);
203  void preparePatternGen(const Snapshot &shot,
204  bool use_dummypattern, unsigned int blankpattern);
205 
206  int makeWaveForm(int num, double pw, tpulsefunc func, double dB, double freq = 0.0, double phase = 0.0);
207  XRecursiveMutex m_stateLock;
208 
209  typedef std::deque<std::pair<uint64_t, uint64_t> > QueueTimeGenCnt;
210  QueueTimeGenCnt m_queueTimeGenCnt; //!< pairs of real time and # of DO samps, which are identical if pausing feature is off.
211 };
212 
213 #endif /*PULSERDRIVERNIDAQMX_H_*/

Generated for KAME4 by  doxygen 1.8.3