lecroy.cpp
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 #include "lecroy.h"
15 #include "charinterface.h"
16 #include "xwavengraph.h"
17 
18 REGISTER_TYPE(XDriverList, LecroyDSO, "Lecroy/Teledyne/Iwatsu DSO");
19 
20 //---------------------------------------------------------------------------
21 XLecroyDSO::XLecroyDSO(const char *name, bool runtime,
22  Transaction &tr_meas, const shared_ptr<XMeasure> &meas) :
23  XCharDeviceDriver<XDSO>(name, runtime, ref(tr_meas), meas) {
24  iterate_commit([=](Transaction &tr){
25  for(auto &&x: {trace1(), trace2(), trace3(), trace4()})
26  tr[ *x].add({"C1", "C2", "C3", "C4", "M1", "M2", "M3", "M4"});
27  for(auto &&x: {vFullScale1(), vFullScale2(), vFullScale3(), vFullScale4()})
28  tr[ *x].add({"0.02", "0.05", "0.1", "0.2", "0.5", "1", "2", "5", "10", "20", "50", "100"});
29  tr[ *trigSource()].add({"C1", "C2", "C3", "C4", "LINE", "EX", "EX10", "PA", "ETM10"});
30  });
31 // interface()->setGPIBWaitBeforeWrite(20); //20msec
32 // interface()->setGPIBWaitBeforeSPoll(10); //10msec
33  interface()->setGPIBUseSerialPollOnRead(false);
34  interface()->setGPIBUseSerialPollOnWrite(false);
35  interface()->setEOS("\n");
36 
37  trans( *recordLength()) = 10000;
38 }
39 
40 void
42  interface()->send("COMM_HEADER OFF");
43  interface()->send("COMM_FORMAT DEF9,WORD,BIN");
44  //LSB first for litte endian.
45  interface()->send("COMM_ORDER LO");
46 
47  interface()->query("TIME_DIV?");
48  trans( *timeWidth()) = interface()->toDouble() * 10.0;
49 
50  interface()->query("MEMORY_SIZE?");
51  XString str = interface()->toStrSimplified();
52  double x = interface()->toDouble();
53  if(str.find("MA") != std::string::npos)
54  x *= 1e6;
55  if(str.find("K") != std::string::npos)
56  x *= 1e3;
57  trans( *recordLength()) = lrint(x);
58 
59  Snapshot shot_this( *this);
60  onAverageChanged(shot_this, average().get());
61 
62  start();
63 }
64 bool
65 XLecroyDSO::isWaveMaster() {
66  interface()->query("*IDN?");
67  if(interface()->toStr().find("WAVEMASTER") != std::string::npos) return true;
68  char buf[256];
69  if(interface()->scanf("LECROY,LT%s", buf) == 1) return false;
70  if(interface()->scanf("LECROY,LC%s", buf) == 1) return false;
71  int num;
72  if(interface()->scanf("LECROY,9%d", &num) == 1) return false;
73 // if(interface()->toStr().find("MXI") != std::string::npos) return true;
74  return true;
75 }
76 
77 void
78 XLecroyDSO::activateTrace(const char *name) {
79  interface()->queryf("%s:TRACE?", name);
80  if( !strncmp( &interface()->buffer()[0], "OFF", 2)) {
81  interface()->queryf("%s:TRACE ON;*OPC?", name);
82  msecsleep(500);
83  Snapshot shot_this( *this);
84  onAverageChanged(shot_this, average().get());
85  }
86 }
87 
88 void
89 XLecroyDSO::onTrace1Changed(const Snapshot &shot, XValueNodeBase *) {
90  XScopedLock<XInterface> lock( *interface());
91  XString ch = ( **trace1())->to_str();
92  if( !ch.empty()) {
93  activateTrace(ch.c_str());
94  }
95 }
96 void
97 XLecroyDSO::onTrace2Changed(const Snapshot &shot, XValueNodeBase *) {
98  XScopedLock<XInterface> lock( *interface());
99  XString ch = ( **trace2())->to_str();
100  if( !ch.empty()) {
101  activateTrace(ch.c_str());
102  }
103 }
104 void
105 XLecroyDSO::onTrace3Changed(const Snapshot &shot, XValueNodeBase *) {
106  XScopedLock<XInterface> lock( *interface());
107  XString ch = ( **trace3())->to_str();
108  if( !ch.empty()) {
109  activateTrace(ch.c_str());
110  }
111 }
112 void
113 XLecroyDSO::onTrace4Changed(const Snapshot &shot, XValueNodeBase *) {
114  XScopedLock<XInterface> lock( *interface());
115  XString ch = ( **trace4())->to_str();
116  if( !ch.empty()) {
117  activateTrace(ch.c_str());
118  }
119 }
120 void
121 XLecroyDSO::onAverageChanged(const Snapshot &shot, XValueNodeBase *) {
122  XScopedLock<XInterface> lock( *interface());
123  Snapshot shot_this( *this);
124  interface()->send("TRIG_MODE STOP");
125  int avg = shot_this[ *average()];
126  avg = std::max(1, avg);
127  bool sseq = shot_this[ *singleSequence()];
128  if(avg == 1) {
129 // interface()->send("F1:TRACE OFF");
130 // interface()->send("F2:TRACE OFF");
131  if(sseq) {
132  interface()->send("ARM");
133  }
134  else {
135  interface()->send("TRIG_MODE NORM");
136  }
137  }
138  else {
139  bool wavemaster = isWaveMaster();
140  const char *atype = sseq ? "SUMMED" : "CONTINUOUS";
141  if( !wavemaster)
142  atype = sseq ? "AVGS" : "AVGC";
143  XString chs[] = {shot_this[ *trace1()].to_str(), shot_this[ *trace2()].to_str(),
144  shot_this[ *trace3()].to_str(), shot_this[ *trace4()].to_str()};
145  const char *tchs[] = {"TA", "TB", "TC", "TD"};
146 // if(wavemaster)
147 // tcshs = {"F1", "F2", "F3", "F4"}; //not nescessary at the moment
148  auto tch = tchs;
149  for(auto it = chs; it != chs + 4; ++it) {
150  if( !it->empty()) {
151  if(wavemaster) {
152 // interface()->sendf("%s:DEFINE EQN,'AVG(%s)',AVETYPE,%s,SWEEPS,%d",
153  interface()->sendf("%s:DEFINE EQN,'AVG(%s)',AVERAGETYPE,%s,SWEEPS,%d",
154  *tch, it->c_str(), atype, avg);
155  }
156  else {
157  interface()->sendf("%s:DEFINE EQN,'%s(%s)',SWEEPS,%d",
158  *tch, atype, it->c_str(), avg);
159  }
160  interface()->sendf("%s:TRACE ON", *tch);
161  tch++;
162  }
163  }
164  interface()->send("TRIG_MODE NORM");
165  }
166  startSequence();
167 }
168 
169 void
170 XLecroyDSO::onSingleChanged(const Snapshot &shot, XValueNodeBase *node) {
171  Snapshot shot_this( *this);
172  onAverageChanged(shot_this, average().get());
173 }
174 void
175 XLecroyDSO::onTrigSourceChanged(const Snapshot &shot, XValueNodeBase *) {
176  interface()->sendf("TRIG_SELECT EDGE,SR,%s", shot[ *trigSource()].to_str().c_str());
177 }
178 void
179 XLecroyDSO::onTrigPosChanged(const Snapshot &shot, XValueNodeBase *) {
180  interface()->sendf("TRIG_DELAY %fPCT", (double)shot[ *trigPos()]);
181 }
182 void
183 XLecroyDSO::onTrigLevelChanged(const Snapshot &shot, XValueNodeBase *) {
184  Snapshot shot_this( *this);
185  interface()->sendf("%s:TRIG_LEVEL %gV", shot_this[ *trigSource()].to_str().c_str(), (double)shot_this[ *trigLevel()]);
186 }
187 void
188 XLecroyDSO::onTrigFallingChanged(const Snapshot &shot, XValueNodeBase *) {
189  Snapshot shot_this( *this);
190  interface()->sendf("%s:TRIG_SLOPE %s", shot_this[ *trigSource()].to_str().c_str(),
191  (shot_this[ *trigFalling()] ? "NEG" : "POS"));
192 }
193 void
194 XLecroyDSO::onTimeWidthChanged(const Snapshot &shot, XValueNodeBase *) {
195  interface()->sendf("TIME_DIV %.1g", (double)shot[ *timeWidth()] / 10.0);
196 }
197 void
198 XLecroyDSO::onVFullScale1Changed(const Snapshot &shot, XValueNodeBase *) {
199  Snapshot shot_this( *this);
200  XString ch = shot_this[ *trace1()].to_str();
201  if(ch.empty()) return;
202  interface()->sendf("%s:VOLT_DIV %.1g", ch.c_str(), atof(shot_this[ *vFullScale1()].to_str().c_str()) / 10.0);
203 }
204 void
205 XLecroyDSO::onVFullScale2Changed(const Snapshot &shot, XValueNodeBase *) {
206  Snapshot shot_this( *this);
207  XString ch = shot_this[ *trace2()].to_str();
208  if(ch.empty()) return;
209  interface()->sendf("%s:VOLT_DIV %.1g", ch.c_str(), atof(shot_this[ *vFullScale2()].to_str().c_str()) / 10.0);
210 }
211 void
212 XLecroyDSO::onVFullScale3Changed(const Snapshot &shot, XValueNodeBase *) {
213  Snapshot shot_this( *this);
214  XString ch = shot_this[ *trace3()].to_str();
215  if(ch.empty()) return;
216  interface()->sendf("%s:VOLT_DIV %.1g", ch.c_str(), atof(shot_this[ *vFullScale3()].to_str().c_str()) / 10.0);
217 }
218 void
219 XLecroyDSO::onVFullScale4Changed(const Snapshot &shot, XValueNodeBase *) {
220  Snapshot shot_this( *this);
221  XString ch = shot_this[ *trace4()].to_str();
222  if(ch.empty()) return;
223  interface()->sendf("%s:VOLT_DIV %.1g", ch.c_str(), atof(shot_this[ *vFullScale4()].to_str().c_str()) / 10.0);
224 }
225 void
226 XLecroyDSO::onVOffset1Changed(const Snapshot &shot, XValueNodeBase *) {
227  Snapshot shot_this( *this);
228  XString ch = shot_this[ *trace1()].to_str();
229  if(ch.empty()) return;
230  interface()->sendf("%s:OFFSET %.8g V", ch.c_str(), (double)shot_this[ *vOffset1()]);
231 }
232 void
233 XLecroyDSO::onVOffset2Changed(const Snapshot &shot, XValueNodeBase *) {
234  Snapshot shot_this( *this);
235  XString ch = shot_this[ *trace2()].to_str();
236  if(ch.empty()) return;
237  interface()->sendf("%s:OFFSET %.8g V", ch.c_str(), (double)shot_this[ *vOffset2()]);
238 }
239 void
240 XLecroyDSO::onVOffset3Changed(const Snapshot &shot, XValueNodeBase *) {
241  Snapshot shot_this( *this);
242  XString ch = shot_this[ *trace3()].to_str();
243  if(ch.empty()) return;
244  interface()->sendf("%s:OFFSET %.8g V", ch.c_str(), (double)shot_this[ *vOffset3()]);
245 }
246 void
247 XLecroyDSO::onVOffset4Changed(const Snapshot &shot, XValueNodeBase *) {
248  Snapshot shot_this( *this);
249  XString ch = shot_this[ *trace4()].to_str();
250  if(ch.empty()) return;
251  interface()->sendf("%s:OFFSET %.8g V", ch.c_str(), (double)shot_this[ *vOffset4()]);
252 }
253 void
254 XLecroyDSO::onRecordLengthChanged(const Snapshot &shot, XValueNodeBase *) {
255  interface()->sendf("MEMORY_SIZE %.2g", (double)(unsigned int)shot[ *recordLength()]);
256 }
257 void
258 XLecroyDSO::onForceTriggerTouched(const Snapshot &shot, XTouchableNode *) {
259  XScopedLock<XInterface> lock( *interface());
260  Snapshot shot_this( *this);
261  // interface()->send("FORCE_TRIGER");
262  if((shot_this[ *average()] <= 1) && shot_this[ *singleSequence()]) {
263  interface()->send("ARM");
264  }
265  else {
266  interface()->send("TRIG_MODE NORM");
267  }
268 }
269 
270 void
272  XScopedLock<XInterface> lock( *interface());
273  Snapshot shot_this( *this);
274  interface()->send("STOP;CLEAR_SWEEPS");
275  if((shot_this[ *average()] <= 1) && shot_this[ *singleSequence()])
276  interface()->send("ARM");
277  else
278  interface()->send("TRIG_MODE NORM");
279  m_totalCount = 0;
280 }
281 
282 int
283 XLecroyDSO::acqCount(bool *seq_busy) {
284  Snapshot shot_this( *this);
285  bool sseq = shot_this[ *singleSequence()];
286  unsigned int n = 0;
287  int avg = shot_this[ *average()];
288  avg = std::max(1, avg);
289  if( !shot_this[ *trace1()].to_str().empty()) {
290  interface()->queryf("%s:TRACE?", shot_this[ *trace1()].to_str().c_str());
291  if( !strncmp( &interface()->buffer()[0], "ON", 2)) {
292  //trace1 is displayed.
293  XString ch = (avg > 1) ? XString("TA") : shot_this[ *trace1()].to_str();
294  n = lrint(inspectDouble("SWEEPS_PER_ACQ", ch));
295  }
296  }
297  if( !sseq || (avg < 2)) {
298  interface()->query("INR?");
299  if(interface()->toInt() & 1) {
300  if( !sseq)
301  m_totalCount++;
302  else
303  n = 1;
304  }
305  if( !sseq)
306  n = m_totalCount;
307  }
308  *seq_busy = (n < avg);
309  return n;
310 }
311 
312 double
313 XLecroyDSO::inspectDouble(const char *req, const XString &trace) {
314  interface()->queryf("%s:INSPECT? '%s'", trace.c_str(), req);
315  double x;
316  interface()->scanf("\"%*s : %lf", &x);
317  return x;
318 }
319 
320 double
321 XLecroyDSO::getTimeInterval() {
322  return inspectDouble("HORIZ_INTERVAL", ( **trace1())->to_str());
323 }
324 
325 void
326 XLecroyDSO::getWave(shared_ptr<RawData> &writer, std::deque<XString> &channels) {
327  Snapshot shot( *this);
328  XScopedLock<XInterface> lock( *interface());
329 // interface()->send("TRIG_MODE STOP");
330  try {
331  writer->push<uint32_t>(channels.size());
332  for(unsigned int i = 0; i < std::min((unsigned int)channels.size(), 4u); i++) {
333  XString ch = channels[i];
334  if(shot[ *average()] > 1) {
335  const char *fch[] = {"TA", "TB", "TC", "TD"};
336  ch = fch[i];
337  }
338  interface()->sendf("%s:WAVEFORM? ALL", ch.c_str());
339  msecsleep(50);
340  interface()->receive(4); //For "ALL,"
341  if(interface()->buffer().size() != 4)
342  throw XInterface::XCommError(i18n("Invalid waveform"), __FILE__, __LINE__);
343  interface()->setGPIBUseSerialPollOnRead(false);
344  interface()->receive(2); //For "#9" or "#A"
345  if(interface()->buffer().size() != 2)
346  throw XInterface::XCommError(i18n("Invalid waveform"), __FILE__, __LINE__);
347  writer->insert(writer->end(),
348  interface()->buffer().begin(), interface()->buffer().end());
349  unsigned int n;
350  interface()->scanf("#%1x", &n);
351  interface()->receive(n);
352  if(interface()->buffer().size() != n)
353  throw XInterface::XCommError(i18n("Invalid waveform"), __FILE__, __LINE__);
354  writer->insert(writer->end(),
355  interface()->buffer().begin(), interface()->buffer().end());
356  int blks = interface()->toUInt();
357  XTime tstart = XTime::now();
358  for(int retry = 0;; retry++) {
359  interface()->receive(blks);
360  blks -= interface()->buffer().size();
361  writer->insert(writer->end(),
362  interface()->buffer().begin(), interface()->buffer().end());
363  if(blks <= 0)
364  break;
365  if(XTime::now() - tstart > 3.0)
366  break; //timeout.
367  msecsleep(20);
368  }
369  if(blks != 0)
370  throw XInterface::XCommError(i18n("Invalid waveform"), __FILE__, __LINE__);
371  interface()->receive(); //For LF.
372 // interface()->setGPIBUseSerialPollOnRead(true);
373  }
374  }
375  catch (XInterface::XInterfaceError &e) {
376 // interface()->setGPIBUseSerialPollOnRead(true);
377  throw e;
378  }
379 // if(!*singleSequence())
380 // interface()->send("TRIG_MODE NORM");
381 }
382 void
384  Snapshot &shot(tr);
385 
386 #define WAVEDESC_WAVE_ARRAY_COUNT 116
387 #define DATA_BLOCK 346
388 
389  unsigned int ch_cnt = reader.pop<uint32_t>();
390  for(unsigned int ch = 0; ch < ch_cnt; ch++) {
391  std::vector<char>::const_iterator dit = reader.popIterator();
392  unsigned int n;
393  sscanf( &*dit, "#%1u", &n);
394  dit += n + 2;
395  if(strncmp( &*dit, "WAVEDESC", 8)) {
396  throw XRecordError(i18n("Invalid waveform"), __FILE__, __LINE__);
397  }
398  dit += DATA_BLOCK;
399  reader.popIterator() += WAVEDESC_WAVE_ARRAY_COUNT + n + 2;
400  int32_t count = reader.pop<int32_t>();
401  reader.pop<int32_t>();
402  int32_t first_valid = reader.pop<int32_t>();
403  int32_t last_valid = reader.pop<int32_t>();
404  int32_t first = reader.pop<int32_t>();
405  reader.pop<int32_t>();
406  reader.pop<int32_t>();
407  reader.pop<int32_t>();
408  int32_t acqcount = reader.pop<int32_t>();
409  reader.pop<int16_t>();
410  reader.pop<int16_t>();
411  float vgain = reader.pop<float>();
412  float voffset = reader.pop<float>();
413  reader.pop<float>();
414  reader.pop<float>();
415  reader.pop<int16_t>();
416  reader.pop<int16_t>();
417  float interval = reader.pop<float>();
418  double hoffset = reader.pop<double>();
419 
420  fprintf(stderr, "first_valid=%d,last_valid=%d,first=%d,acqcount=%d,count=%d\n",
421  (int)first_valid, (int)last_valid, (int)first, (int)acqcount, (int)count);
422  if(ch == 0) {
423  if((count < 0) ||
424  (reader.size() < (count * 2 + DATA_BLOCK + n + 2) * ch_cnt))
425  throw XBufferUnderflowRecordError(__FILE__, __LINE__);
426  tr[ *this].setParameters(ch_cnt, hoffset, interval, count);
427  }
428 
429  double *wave = tr[ *this].waveDisp(ch);
430  reader.popIterator() = dit;
431  int length = shot[ *this].lengthDisp();
432  for(int i = 0; i < std::min(count, (int32_t)length); i++) {
433  int16_t x = reader.pop<int16_t>();
434  float v = voffset + vgain * x;
435  *wave++ = v;
436  }
437  }
438 }

Generated for KAME4 by  doxygen 1.8.3