pulserdriver.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 //---------------------------------------------------------------------------
15 #ifndef pulserdriverH
16 #define pulserdriverH
17 //---------------------------------------------------------------------------
18 #include "primarydriver.h"
19 #include "xitemnode.h"
20 #include "xnodeconnector.h"
21 #include <complex>
22 #include "fft.h"
23 
24 class QMainWindow;
25 class Ui_FrmPulser;
27 class Ui_FrmPulserMore;
29 
31 
32 //! Base class of NMR Pulsers
33 class DECLSPEC_SHARED XPulser : public XPrimaryDriver {
34 public:
35  XPulser(const char *name, bool runtime,
36  Transaction &tr_meas, const shared_ptr<XMeasure> &meas);
37 ;
38  virtual ~XPulser() {}
39  //! shows all forms belonging to driver
40  virtual void showForms();
41 
42  //! driver specific part below
43 
44  //! \sa pulseAnalyzerMode()
45  enum {N_MODE_NMR_PULSER = 0, N_MODE_PULSE_ANALYZER = 1};
46  //! \sa combMode(), Payload::combMode().
47  enum {N_COMB_MODE_OFF = 0, N_COMB_MODE_ON = 1, N_COMB_MODE_P1_ALT = 2, N_COMB_MODE_COMB_ALT = 3};
48  //! \sa rtMode(), Payload::rtMode().
49  enum {N_RT_MODE_FIXREP = 0, N_RT_MODE_FIXREST = 1};
50  //! \sa numPhaseCycle(), Payload::numPhaseCycle().
51  enum {MAX_NUM_PHASE_CYCLE = 16};
52  //! # of digital-pulse ports.
53  enum {NUM_DO_PORTS= 16};
54  //! for RelPatList patterns. \sa Payload::RelPatList.
55  enum {PAT_DO_MASK = (1 << NUM_DO_PORTS) - 1,
56  PAT_QAM_PHASE = (1 << NUM_DO_PORTS),
57  PAT_QAM_PHASE_MASK = PAT_QAM_PHASE * 3,
58  PAT_QAM_PULSE_IDX = PAT_QAM_PHASE * 4,
59  PAT_QAM_PULSE_IDX_P1 = PAT_QAM_PULSE_IDX * 1,
60  PAT_QAM_PULSE_IDX_P2 = PAT_QAM_PULSE_IDX * 2,
61  PAT_QAM_PULSE_IDX_PCOMB = PAT_QAM_PULSE_IDX * 3,
62  PAT_QAM_PULSE_IDX_INDUCE_EMISSION = PAT_QAM_PULSE_IDX * 4,
63  PAT_QAM_PULSE_IDX_MASK = PAT_QAM_PULSE_IDX * 15,
64  PAT_QAM_MASK = PAT_QAM_PHASE_MASK | PAT_QAM_PULSE_IDX_MASK,
65  };
66 
67  struct Payload : public XPrimaryDriver::Payload {
68  //! ver 1 records.
69  int16_t combMode() const {return m_combMode;}
70  double rtime() const {return m_rtime;}
71  double tau() const {return m_tau;}
72  double pw1() const {return m_pw1;}
73  double pw2() const {return m_pw2;}
74  double combP1() const {return m_combP1;}
75  double altSep() const {return m_altSep;}
76  double combP1Alt() const {return m_combP1Alt;}
77  double aswSetup() const {return m_aswSetup;}
78  double aswHold() const {return m_aswHold;}
79  //! ver 2 records.
80  double difFreq() const {return m_difFreq;}
81  double combPW() const {return m_combPW;}
82  double combPT() const {return m_combPT;}
83  uint16_t echoNum() const {return m_echoNum;}
84  uint16_t combNum() const {return m_combNum;}
85  int16_t rtMode() const {return m_rtMode;}
86  uint16_t numPhaseCycle() const {return m_numPhaseCycle;}
87  //! ver 3 records.
88  bool invertPhase() const {return m_invertPhase;}
89  //! ver 4 records.
90  int16_t p1Func() const {return m_p1Func;}
91  int16_t p2Func() const {return m_p2Func;}
92  int16_t combFunc() const {return m_combFunc;}
93  double p1Level() const {return m_p1Level;}
94  double p2Level() const {return m_p2Level;}
95  double combLevel() const {return m_combLevel;}
96  double masterLevel() const {return m_masterLevel;}
97  double combOffRes() const {return m_combOffRes;}
98  bool conserveStEPhase() const {return m_conserveStEPhase;}
99 
100  bool isPulseAnalyzerMode() const {return m_paPulseBW > 0;}
101  double paPulseRept() const {return m_rtime;}
102  double paPulseBW() const {return m_paPulseBW;}
103  double paPulseOrigin() const {return m_paPulseOrigin;}
104 
105  //! periodic term of one cycle [ms].
106  double periodicTerm() const;
107 
108  struct RelPat {
109  RelPat(uint32_t pat, uint64_t t, uint64_t toapp) :
110  pattern(pat), time(t), toappear(toapp) {}
111  uint32_t pattern;
112  uint64_t time; //!< using unit of resolution().
113  uint64_t toappear; //!< term between this pattern and the previous. unit of resolution().
114  };
115 
116  typedef std::deque<RelPat> RelPatList;
117  RelPatList &relPatList() {return m_relPatList;}
118  const RelPatList &relPatList() const {return m_relPatList;}
119 
120  const std::vector<std::complex<double> > &qamWaveForm(unsigned int idx) const {
121  return m_qamWaveForm[idx];
122  }
123  private:
124  friend class XPulser;
125 
126  //! ver 1 records
127  int16_t m_combMode;
128  int16_t m_pulserMode;
129  double m_rtime;
130  double m_tau;
131  double m_pw1;
132  double m_pw2;
133  double m_combP1;
134  double m_altSep;
135  double m_combP1Alt;
136  double m_aswSetup;
137  double m_aswHold;
138  //! ver 2 records
139  double m_difFreq;
140  double m_combPW;
141  double m_combPT;
142  uint16_t m_echoNum;
143  uint16_t m_combNum;
144  int16_t m_rtMode;
145  uint16_t m_numPhaseCycle;
146  //! ver 3 records
148  //! ver 4 records
149  int16_t m_p1Func, m_p2Func, m_combFunc;
150  double m_p1Level, m_p2Level, m_combLevel, m_masterLevel;
151  double m_combOffRes;
152  bool m_conserveStEPhase;
153 
154  //! PA mode
155  double m_paPulseBW;
156  double m_paPulseOrigin; //!< [us]
157 
158  //! Patterns.
159  RelPatList m_relPatList;
160  std::vector<std::complex<double> >
161  m_qamWaveForm[XPulser::PAT_QAM_PULSE_IDX_MASK / XPulser::PAT_QAM_PULSE_IDX];
162  };
163 
164  const shared_ptr<XBoolNode> &output() const {return m_output;}
165  const shared_ptr<XComboNode> &combMode() const {return m_combMode;} //!< see above definitions in header file
166  //! Control period to next pulse sequence
167  //! Fix Repetition Time or Fix Rest Time which means time between pulse sequences
168  const shared_ptr<XComboNode> &rtMode() const {return m_rtMode;}
169  const shared_ptr<XComboNode> &numPhaseCycle() const {return m_numPhaseCycle;} //!< How many cycles in phase cycling
170  const shared_ptr<XDoubleNode> &rtime() const {return m_rt;} //!< Repetition/Rest Time [ms]
171  const shared_ptr<XDoubleNode> &tau() const {return m_tau;} //!< [us]
172  const shared_ptr<XDoubleNode> &combPW() const {return m_combPW;} //!< PulseWidths [us]
173  const shared_ptr<XDoubleNode> &pw1() const {return m_pw1;} //!< PulseWidths [us]
174  const shared_ptr<XDoubleNode> &pw2() const {return m_pw2;} //!< PulseWidths [us]
175  const shared_ptr<XDoubleNode> &combPT() const {return m_combPT;} //!< Comb pulse periodic term [us]
176  const shared_ptr<XDoubleNode> &combP1() const {return m_combP1;} //!< P1 and P1 alternative
177  const shared_ptr<XDoubleNode> &combP1Alt() const {return m_combP1Alt;} //!< P1 and P1 alternative
178  const shared_ptr<XDoubleNode> &aswSetup() const {return m_aswSetup;} //!< Analog switch setting, setup(proceeding) time before the first spin echo
179  const shared_ptr<XDoubleNode> &aswHold() const {return m_aswHold;} //!< Analog switch setting, hold time after the last spin echo
180  const shared_ptr<XDoubleNode> &altSep() const {return m_altSep;} //!< Separation time in DSO record, cause a shift of trigger of DSO in alternatively mode
181  const shared_ptr<XDoubleNode> &g2Setup() const {return m_g2Setup;} //!< Setup time of pre-gating port and QPSK
182  const shared_ptr<XUIntNode> &combNum() const {return m_combNum;} //!< # of comb pulses
183  const shared_ptr<XUIntNode> &echoNum() const {return m_echoNum;} //!< # of Spin echoes (i.e. pi pulses)
184  const shared_ptr<XBoolNode> &drivenEquilibrium() const {return m_drivenEquilibrium;} //!< polarize spins after pulse sequence or not
185  const shared_ptr<XDoubleNode> &combOffRes() const {return m_combOffRes;} //!< off-resonance comb pulses
186  const shared_ptr<XComboNode> &combFunc() const {return m_combFunc;} //!< Pulse Modulation
187  const shared_ptr<XComboNode> &p1Func() const {return m_p1Func;} //!< Pulse Modulation
188  const shared_ptr<XComboNode> &p2Func() const {return m_p2Func;} //!< Pulse Modulation
189  const shared_ptr<XDoubleNode> &combLevel() const {return m_combLevel;} //!< [dB], Pulse Modulation
190  const shared_ptr<XDoubleNode> &p1Level() const {return m_p1Level;} //!< [dB], Pulse Modulation
191  const shared_ptr<XDoubleNode> &p2Level() const {return m_p2Level;} //!< [dB], Pulse Modulation
192  const shared_ptr<XDoubleNode> &masterLevel() const {return m_masterLevel;} //!< [dB]
193  const shared_ptr<XBoolNode> &induceEmission() const {return m_induceEmission;}
194  const shared_ptr<XDoubleNode> &induceEmissionPhase() const {return m_induceEmissionPhase;}
195  const shared_ptr<XDoubleNode> &qamOffset1() const {return m_qamOffset1;}
196  const shared_ptr<XDoubleNode> &qamOffset2() const {return m_qamOffset2;} //!< [%F.S.]
197  const shared_ptr<XDoubleNode> &qamLevel1() const {return m_qamLevel1;} //! < Quadrature Amplitude Modulation. Amplitude compensation factor.
198  const shared_ptr<XDoubleNode> &qamLevel2() const {return m_qamLevel2;}
199  const shared_ptr<XDoubleNode> &qamDelay1() const {return m_qamDelay1;} //! < Delaying compensation [us].
200  const shared_ptr<XDoubleNode> &qamDelay2() const {return m_qamDelay2;} //!< [us]
201  const shared_ptr<XDoubleNode> &difFreq() const {return m_difFreq;} //!< [MHz]
202  const shared_ptr<XDoubleNode> &qswDelay() const {return m_qswDelay;} //!< Q-switch setting, period after the end-edge of pulses [us].
203  const shared_ptr<XDoubleNode> &qswWidth() const {return m_qswWidth;} //!< Q-switch setting, width of suppression [us].
204  const shared_ptr<XDoubleNode> &qswSoftSWOff() const {return m_qswSoftSWOff;} //!< Q-switch setting, second pulse [us].
205  const shared_ptr<XBoolNode> &qswPiPulseOnly() const {return m_qswPiPulseOnly;} //!< Q-switch setting, use QSW only for pi pulses.
206  const shared_ptr<XBoolNode> &invertPhase() const {return m_invertPhase;}
207  const shared_ptr<XBoolNode> &conserveStEPhase() const {return m_conserveStEPhase;}
208  const shared_ptr<XComboNode> &portSel(unsigned int port) const {
209  assert(port < NUM_DO_PORTS);
210  return m_portSel[port];
211  }
212  const shared_ptr<XBoolNode> &pulseAnalyzerMode() const {return m_pulseAnalyzerMode;}
213  const shared_ptr<XDoubleNode> &paPulseRept() const {return m_paPulseRept;}
214  const shared_ptr<XDoubleNode> &paPulseBW() const {return m_paPulseBW;}
215  const shared_ptr<XUIntNode> &firstPhase() const {return m_firstPhase;} //!< 0-3, selects the first phase of QPSK.
216 
217  //! time resolution [ms]
218  virtual double resolution() const = 0;
219 protected:
220  //! indice for return values of portSel().
221  enum {PORTSEL_UNSEL = -1,
222  PORTSEL_GATE = 0, PORTSEL_PREGATE = 1, PORTSEL_GATE3 = 2,
223  PORTSEL_TRIG1 = 3, PORTSEL_TRIG2 = 4, PORTSEL_ASW = 5, PORTSEL_QSW = 6,
224  PORTSEL_PULSE1 = 7, PORTSEL_PULSE2 = 8,
225  PORTSEL_COMB = 9, PORTSEL_COMB_FM = 10,
226  PORTSEL_QPSK_A = 11, PORTSEL_QPSK_B = 12,
227  PORTSEL_QPSK_OLD_NONINV = 13, PORTSEL_QPSK_OLD_INV = 14,
228  PORTSEL_QPSK_OLD_PSGATE = 15,
229  PORTSEL_PULSE_ANALYZER_GATE = 16,
230  /*PORTSEL_PAUSING = 17*/};
231  //! \param func e.g. PORTSEL_GATE.
232  //! \return bit mask.
233  unsigned int selectedPorts(const Snapshot &shot, int func) const;
234 
235  //! Starts up your threads, connects GUI, and activates signals.
236  virtual void start();
237  //! Shuts down your threads, unconnects GUI, and deactivates signals
238  //! This function may be called even if driver has already stopped.
239  virtual void stop();
240 
241  //! This function will be called when raw data are written.
242  //! Implement this function to convert the raw data to the record (Payload).
243  //! \sa analyze()
244  virtual void analyzeRaw(RawDataReader &reader, Transaction &tr) throw (XRecordError&);
245  //! This function is called inside analyze() or analyzeRaw()
246  //! This might be called even if the record is broken (time() == false).
247  virtual void visualize(const Snapshot &shot);
248 
249  typedef FFT::twindowfunc tpulsefunc;
250  tpulsefunc pulseFunc(int func_no) const;
251  int pulseFuncNo(const XString &str) const;
252 
253  //! Sends patterns to pulser or turns off.
254  virtual void changeOutput(const Snapshot &shot, bool output, unsigned int blankpattern) = 0;
255  //! Converts RelPatList to native patterns
256  virtual void createNativePatterns(Transaction &tr) = 0;
257  virtual double resolutionQAM() const = 0;
258  //! minimum period of pulses [ms]
259  virtual double minPulseWidth() const = 0;
260  //! existence of AO ports.
261  virtual bool hasQAMPorts() const = 0;
262 private:
263  const shared_ptr<XBoolNode> m_output;
264  const shared_ptr<XComboNode> m_combMode; //!< see above definitions in header file
265  //! Control period to next pulse sequence
266  //! Fix Repetition Time or Fix Rest Time which means time between pulse sequences
267  const shared_ptr<XComboNode> m_rtMode;
268  const shared_ptr<XDoubleNode> m_rt; //!< Repetition/Rest Time [ms]
269  const shared_ptr<XDoubleNode> m_tau; //!< [us]
270  const shared_ptr<XDoubleNode> m_combPW, m_pw1, m_pw2; //!< PulseWidths [us]
271  const shared_ptr<XUIntNode> m_combNum; //!< # of comb pulses
272  const shared_ptr<XDoubleNode> m_combPT; //!< Comb pulse periodic term [us]
273  const shared_ptr<XDoubleNode> m_combP1, m_combP1Alt; //!< P1 and P1 alternative
274  const shared_ptr<XDoubleNode> m_aswSetup; //!< Analog switch setting, setup(proceeding) time before the first spin echo
275  const shared_ptr<XDoubleNode> m_aswHold; //!< Analog switch setting, hold time after the last spin echo
276  const shared_ptr<XDoubleNode> m_altSep; //!< Separation time in DSO record, cause a shift of trigger of DSO in alternatively mode
277  const shared_ptr<XDoubleNode> m_g2Setup; //!< Setup time of pre-gating port and QPSK
278  const shared_ptr<XUIntNode> m_echoNum; //!< # of Spin echoes (i.e. pi pulses)
279  const shared_ptr<XDoubleNode> m_combOffRes; //!< off-resonance comb pulses
280  const shared_ptr<XBoolNode> m_drivenEquilibrium; //!< polarize spins after pulse sequence or not
281  const shared_ptr<XComboNode> m_numPhaseCycle; //!< How many cycles in phase cycling
282  const shared_ptr<XComboNode> m_p1Func, m_p2Func, m_combFunc; //!< Pulse Modulation
283  const shared_ptr<XDoubleNode> m_p1Level, m_p2Level, m_combLevel; //!< [dB], Pulse Modulation
284  const shared_ptr<XDoubleNode> m_masterLevel; //!< [dB]
285  const shared_ptr<XDoubleNode> m_qamOffset1;
286  const shared_ptr<XDoubleNode> m_qamOffset2; //!< [%F.S.]
287  const shared_ptr<XDoubleNode> m_qamLevel1;
288  const shared_ptr<XDoubleNode> m_qamLevel2;
289  const shared_ptr<XDoubleNode> m_qamDelay1;
290  const shared_ptr<XDoubleNode> m_qamDelay2; //!< [us]
291  const shared_ptr<XDoubleNode> m_difFreq; //!< [MHz]
292  const shared_ptr<XBoolNode> m_induceEmission;
293  const shared_ptr<XDoubleNode> m_induceEmissionPhase;
294  const shared_ptr<XDoubleNode> m_qswDelay;
295  const shared_ptr<XDoubleNode> m_qswWidth;
296  const shared_ptr<XDoubleNode> m_qswSoftSWOff;
297  const shared_ptr<XBoolNode> m_invertPhase;
298  const shared_ptr<XBoolNode> m_conserveStEPhase;
299  const shared_ptr<XBoolNode> m_qswPiPulseOnly;
300  shared_ptr<XComboNode> m_portSel[NUM_DO_PORTS];
301  const shared_ptr<XBoolNode> m_pulseAnalyzerMode;
302  const shared_ptr<XDoubleNode> m_paPulseRept; //!< [ms]
303  const shared_ptr<XDoubleNode> m_paPulseBW; //!< [kHz]
304  const shared_ptr<XUIntNode> m_firstPhase; //!< 0-3, selects QPSK for the first cycle.
305 
306  const shared_ptr<XTouchableNode> m_moreConfigShow;
307  std::deque<xqcon_ptr> m_conUIs;
308  shared_ptr<XListener> m_lsnOnPulseChanged;
309  shared_ptr<XListener> m_lsnOnMoreConfigShow;
310  void onMoreConfigShow(const Snapshot &shot, XTouchableNode *);
311 
312  const qshared_ptr<FrmPulser> m_form;
313  const qshared_ptr<FrmPulserMore> m_formMore;
314 
315  xqcon_ptr m_conPulserDriver;
316 
317  void onPulseChanged(const Snapshot &shot, XValueNodeBase *node);
318 
319  //! creates \a RelPatList
321  void createRelPatListPulseAnalyzer(Transaction &tr) throw (XRecordError&);
322  //! \return maskbits for QPSK ports.
323  unsigned int bitpatternsOfQPSK(const Snapshot &shot, unsigned int qpsk[4], unsigned int qpskinv[4], bool invert);
324 
325  //! prepares waveforms for QAM.
326  void makeWaveForm(Transaction &tr, unsigned int pnum_minus_1,
327  double pw, unsigned int to_center,
328  tpulsefunc func, double dB, double freq = 0.0, double phase = 0.0);
329 
330  //! truncates time by resolution().
331  inline double rintTermMilliSec(double msec) const;
332  inline double rintTermMicroSec(double usec) const;
333  inline uint64_t ceilSampsMicroSec(double us) const;
334  inline uint64_t rintSampsMicroSec(double us) const;
335  inline uint64_t rintSampsMilliSec(double ms) const;
336 
337  void changeUIStatus(bool nmrmode, bool state);
338 };
339 
340 inline double
341 XPulser::rintTermMilliSec(double msec) const {
342  double res = resolution();
343  return rint(msec / res) * res;
344 }
345 inline double
346 XPulser::rintTermMicroSec(double usec) const {
347  double res = resolution() * 1e3;
348  return rint(usec / res) * res;
349 }
350 inline uint64_t
351 XPulser::ceilSampsMicroSec(double usec) const {
352  double res = resolution() * 1e3;
353  return llrint(usec / res + 0.499);
354 }
355 inline uint64_t
356 XPulser::rintSampsMicroSec(double usec) const {
357  double res = resolution() * 1e3;
358  return llrint(usec / res);
359 }
360 inline uint64_t
361 XPulser::rintSampsMilliSec(double msec) const {
362  double res = resolution();
363  return llrint(msec / res);
364 }
365 
366 #endif

Generated for KAME4 by  doxygen 1.8.3