19 #define DAQmx_Val_FallingSlope 0
20 #define DAQmx_Val_RisingSlope 0
21 #define DAQmx_Val_DigEdge 0
22 #define DAQmxGetReadAvailSampPerChan(x,y) 0
23 #endif //HAVE_NI_DAQMX
25 #include <qmessagebox.h>
26 #include "xwavengraph.h"
28 REGISTER_TYPE(
XDriverList, NIDAQmxDSO,
"National Instruments DAQ as DSO");
30 #define TASK_UNDEF ((TaskHandle)-1)
33 XNIDAQmxDSO::XNIDAQmxDSO(
const char *name,
bool runtime,
34 Transaction &tr_meas,
const shared_ptr<XMeasure> &meas) :
36 m_dsoRawRecordBankLatest(0),
40 tr[ *recordLength()] = 2000;
41 tr[ *timeWidth()] = 1e-2;
43 for(
auto &&x: {vFullScale1(), vFullScale2(), vFullScale3(), vFullScale4()}) {
44 tr[ *x].add({
"0.4",
"1",
"2",
"4",
"10",
"20",
"40",
"84"});
48 if(isMemLockAvailable()) {
49 const void *FIRST_OF_MLOCK_MEMBER = &m_recordBuf;
50 const void *LAST_OF_MLOCK_MEMBER = &m_task;
52 mlock(FIRST_OF_MLOCK_MEMBER, (
size_t)LAST_OF_MLOCK_MEMBER - (
size_t)FIRST_OF_MLOCK_MEMBER);
55 vOffset1()->disable();
56 vOffset2()->disable();
57 vOffset3()->disable();
58 vOffset4()->disable();
60 XNIDAQmxDSO::~XNIDAQmxDSO() {
64 XNIDAQmxDSO::onSoftTrigChanged(
const shared_ptr<XNIDAQmxInterface::SoftwareTrigger> &) {
66 tr[ *trigSource()].clear();
67 XString series = interface()->productSeries();
71 CHECK_DAQMX_RET(DAQmxGetDevAIPhysicalChans(interface()->devName(), buf,
sizeof(buf)));
72 std::deque<XString> chans;
74 for(std::deque<XString>::iterator it = chans.begin(); it != chans.end(); ++it) {
75 tr[ *trigSource()].add(it->c_str());
79 const char* sc_m[] = {
80 "PFI0",
"PFI1",
"PFI2",
"PFI3",
"PFI4",
"PFI5",
"PFI6",
"PFI7",
81 "PFI8",
"PFI9",
"PFI10",
"PFI11",
"PFI12",
"PFI13",
"PFI14",
"PFI15",
82 "Ctr0InternalOutput",
"Ctr1InternalOutput",
90 const char* sc_s[] = {
91 "PFI0",
"PFI1",
"PFI2",
"PFI3",
"PFI4",
"PFI5",
"PFI6",
"PFI7",
98 const char **sc = sc_m;
101 for(
const char **it = sc; *it; it++) {
102 XString str(formatString(
"/%s/%s", interface()->devName(), *it));
103 tr[ *trigSource()].add(str);
106 list(XNIDAQmxInterface::SoftwareTrigger::virtualTrigList());
107 for(XNIDAQmxInterface::SoftwareTrigger::SoftwareTriggerList_it
108 it = list->begin(); it != list->end(); ++it) {
109 for(
unsigned int i = 0; i < ( *it)->bits(); i++) {
110 tr[ *trigSource()].add(
111 formatString(
"%s/line%d", ( *it)->label(), i));
115 tr.unmark(m_lsnOnTrigSourceChanged);
124 CHECK_DAQMX_RET(DAQmxGetDevAIPhysicalChans(interface()->devName(), buf,
sizeof(buf)));
125 std::deque<XString> chans;
128 for(
auto it = chans.cbegin(); it != chans.cend(); ++it) {
129 for(
auto &&x: {trace1(), trace2(), trace3(), trace4()})
130 tr[ *x].add(it->c_str());
134 onSoftTrigChanged(shared_ptr<XNIDAQmxInterface::SoftwareTrigger>());
136 m_suspendRead =
true;
138 &XNIDAQmxDSO::executeReadAI));
139 m_threadReadAI->resume();
144 shared_from_this(), &XNIDAQmxDSO::onSoftTrigChanged,
145 XListener::FLAG_MAIN_THREAD_CALL);
152 m_lsnOnSoftTrigChanged.reset();
157 m_threadReadAI->terminate();
161 for(
auto &&x: {trace1(), trace2(), trace3(), trace4()})
171 XNIDAQmxDSO::clearAcquision() {
173 m_suspendRead =
true;
183 if(m_task != TASK_UNDEF) {
184 CHECK_DAQMX_RET(DAQmxClearTask(m_task));
189 XNIDAQmxDSO::disableTrigger() {
191 m_suspendRead =
true;
196 CHECK_DAQMX_RET(DAQmxStopTask(m_task));
198 if(m_task != TASK_UNDEF) {
200 CHECK_DAQMX_RET(DAQmxGetTaskNumChans(m_task, &num_ch));
202 CHECK_DAQMX_RET(DAQmxDisableStartTrig(m_task));
203 CHECK_DAQMX_RET(DAQmxDisableRefTrig(m_task));
210 if(m_softwareTrigger)
211 m_softwareTrigger->disconnect();
212 m_lsnOnSoftTrigStarted.reset();
213 m_softwareTrigger.reset();
216 XNIDAQmxDSO::setupTrigger() {
219 m_suspendRead =
true;
222 unsigned int pretrig = lrint(shot[ *trigPos()] / 100.0 * shot[ *recordLength()]);
223 m_preTriggerPos = pretrig;
227 XString src = shot[ *trigSource()].to_str();
231 CHECK_DAQMX_RET(DAQmxGetDevAIPhysicalChans(interface()->devName(), buf,
sizeof(buf)));
232 std::deque<XString> chans;
234 for(std::deque<XString>::iterator it = chans.begin(); it != chans.end(); ++it) {
242 int32 trig_spec = shot[ *trigFalling()] ? DAQmx_Val_FallingSlope : DAQmx_Val_RisingSlope;
244 if(m_softwareTrigger) {
245 dtrig = m_softwareTrigger->armTerm();
246 trig_spec = DAQmx_Val_RisingSlope;
248 CHECK_DAQMX_RET(DAQmxSetReadOverWrite(m_task, DAQmx_Val_OverwriteUnreadSamps));
249 m_softwareTrigger->setPersistentCoherentMode(shot[ *dRFMode()] >= 1);
253 if( !m_softwareTrigger && (pretrig < 2)) {
255 m_preTriggerPos = pretrig;
261 DAQmxCfgAnlgEdgeStartTrig(m_task,
262 atrig.c_str(), trig_spec, shot[ *trigLevel()]));
266 DAQmxCfgDigEdgeStartTrig(m_task,
267 dtrig.c_str(), trig_spec));
273 DAQmxCfgAnlgEdgeRefTrig(m_task,
274 atrig.c_str(), trig_spec, shot[ *trigLevel()], pretrig));
278 DAQmxCfgDigEdgeRefTrig(m_task,
279 dtrig.c_str(), trig_spec, pretrig));
284 CHECK_DAQMX_RET(DAQmxGetTaskChannels(m_task, ch,
sizeof(ch)));
285 if(interface()->productFlags() & XNIDAQmxInterface::FLAG_BUGGY_DMA_AI) {
286 CHECK_DAQMX_RET(DAQmxSetAIDataXferMech(m_task, ch,
287 DAQmx_Val_Interrupts));
289 if(interface()->productFlags() & XNIDAQmxInterface::FLAG_BUGGY_XFER_COND_AI) {
291 CHECK_DAQMX_RET(DAQmxGetBufInputOnbrdBufSize(m_task, &bufsize));
293 DAQmxSetAIDataXferReqCond(m_task, ch,
294 (m_softwareTrigger || (bufsize/2 < m_recordBuf.size())) ? DAQmx_Val_OnBrdMemNotEmpty :
295 DAQmx_Val_OnBrdMemMoreThanHalfFull));
299 XNIDAQmxDSO::setupSoftwareTrigger() {
301 XString src = shot[ *trigSource()].to_str();
304 list(XNIDAQmxInterface::SoftwareTrigger::virtualTrigList());
305 for(XNIDAQmxInterface::SoftwareTrigger::SoftwareTriggerList_it
306 it = list->begin(); it != list->end(); ++it) {
307 for(
unsigned int i = 0; i < ( *it)->bits(); i++) {
308 if(src == formatString(
"%s/line%d", ( *it)->label(), i)) {
309 m_softwareTrigger = *it;
310 m_softwareTrigger->connect(
311 !shot[ *trigFalling()] ? (1uL << i) : 0,
312 shot[ *trigFalling()] ? (1uL << i) : 0);
321 m_suspendRead =
true;
326 CHECK_DAQMX_RET(DAQmxStopTask(m_task));
330 CHECK_DAQMX_RET(DAQmxGetTaskNumChans(m_task, &num_ch));
331 if(num_ch == 0)
return;
334 setupSoftwareTrigger();
336 const unsigned int len = shot[ *recordLength()];
337 for(
unsigned int i = 0; i < 2; i++) {
339 rec.record.resize(len * num_ch * (rec.isComplex ? 2 : 1));
340 assert(rec.numCh == num_ch);
341 if(isMemLockAvailable()) {
342 mlock(&rec.record[0], rec.record.size() *
sizeof(int32_t));
345 m_recordBuf.resize(len * num_ch);
346 if(isMemLockAvailable()) {
347 mlock( &m_recordBuf[0], m_recordBuf.size() *
sizeof(tRawAI));
351 CHECK_DAQMX_RET(DAQmxGetBufInputOnbrdBufSize(m_task, &onbrd_size));
352 fprintf(stderr,
"Using on-brd bufsize=%d\n", (
int)onbrd_size);
353 unsigned int bufsize = len;
354 if(m_softwareTrigger) {
355 bufsize = std::max(bufsize * 8, (
unsigned int)lrint((len / shot[ *timeWidth()]) * 1.0));
356 bufsize = std::max(bufsize, (
unsigned int)(onbrd_size / num_ch));
360 DAQmxCfgSampClkTiming(m_task,
364 len / shot[ *timeWidth()],
366 !m_softwareTrigger ? DAQmx_Val_FiniteSamps : DAQmx_Val_ContSamps,
370 interface()->synchronizeClock(m_task);
374 CHECK_DAQMX_RET(DAQmxGetBufInputBufSize(m_task, &size));
375 fprintf(stderr,
"Using buffer size of %d\n", (
int)size);
376 if(size != bufsize) {
377 fprintf(stderr,
"Try to modify buffer size from %d to %d\n", (
int)size, (
int)bufsize);
378 CHECK_DAQMX_RET(DAQmxCfgInputBuffer(m_task, bufsize));
382 CHECK_DAQMX_RET(DAQmxSetExportedSampClkOutputTerm(m_task, formatString(
"/%s/PFI7", interface()->devName()).c_str()));
390 CHECK_DAQMX_RET(DAQmxGetSampClkRate(m_task, &rate));
391 m_interval = 1.0 / rate;
399 XNIDAQmxDSO::createChannels() {
402 m_suspendRead =
true;
407 CHECK_DAQMX_RET(DAQmxCreateTask(
"", &m_task));
408 assert(m_task != TASK_UNDEF);
410 if(shot[ *trace1()] >= 0) {
412 DAQmxCreateAIVoltageChan(m_task,
413 shot[ *trace1()].to_str().c_str(),
415 DAQmx_Val_Cfg_Default,
416 -atof(shot[ *vFullScale1()].to_str().c_str()) / 2.0,
417 atof(shot[ *vFullScale1()].to_str().c_str()) / 2.0,
423 for(
unsigned int i = 0; i < CAL_POLY_ORDER; i++)
424 m_coeffAI[0][i] = 0.0;
426 DAQmxGetAIDevScalingCoeff(m_task,
427 shot[ *trace1()].to_str().c_str(),
428 m_coeffAI[0], CAL_POLY_ORDER));
430 if(shot[ *trace2()] >= 0) {
432 DAQmxCreateAIVoltageChan(m_task,
433 shot[ *trace2()].to_str().c_str(),
435 DAQmx_Val_Cfg_Default,
436 -atof(shot[ *vFullScale2()].to_str().c_str()) / 2.0,
437 atof(shot[ *vFullScale2()].to_str().c_str()) / 2.0,
442 for(
unsigned int i = 0; i < CAL_POLY_ORDER; i++)
443 m_coeffAI[1][i] = 0.0;
444 CHECK_DAQMX_RET(DAQmxGetAIDevScalingCoeff(m_task,
445 shot[ *trace2()].to_str().c_str(),
446 m_coeffAI[1], CAL_POLY_ORDER));
448 if(shot[ *trace3()] >= 0) {
450 DAQmxCreateAIVoltageChan(m_task,
451 shot[ *trace3()].to_str().c_str(),
453 DAQmx_Val_Cfg_Default,
454 -atof(shot[ *vFullScale3()].to_str().c_str()) / 2.0,
455 atof(shot[ *vFullScale3()].to_str().c_str()) / 2.0,
460 for(
unsigned int i = 0; i < CAL_POLY_ORDER; i++)
461 m_coeffAI[2][i] = 0.0;
462 CHECK_DAQMX_RET(DAQmxGetAIDevScalingCoeff(m_task,
463 shot[ *trace3()].to_str().c_str(),
464 m_coeffAI[2], CAL_POLY_ORDER));
466 if(shot[ *trace4()] >= 0) {
468 DAQmxCreateAIVoltageChan(m_task,
469 shot[ *trace4()].to_str().c_str(),
471 DAQmx_Val_Cfg_Default,
472 -atof(shot[ *vFullScale4()].to_str().c_str()) / 2.0,
473 atof(shot[ *vFullScale4()].to_str().c_str()) / 2.0,
478 for(
unsigned int i = 0; i < CAL_POLY_ORDER; i++)
479 m_coeffAI[3][i] = 0.0;
480 CHECK_DAQMX_RET(DAQmxGetAIDevScalingCoeff(m_task,
481 shot[ *trace4()].to_str().c_str(),
482 m_coeffAI[3], CAL_POLY_ORDER));
486 CHECK_DAQMX_RET(DAQmxGetTaskNumChans(m_task, &num_ch));
489 for(
unsigned int i = 0; i < 2; i++) {
490 DSORawRecord &rec(m_dsoRawRecordBanks[i]);
494 rec.isComplex = (shot[ *dRFMode()] == DRFMODE_COHERENT_SG);
501 CHECK_DAQMX_RET(DAQmxRegisterDoneEvent(m_task, 0, &XNIDAQmxDSO::onTaskDone_,
this));
506 XNIDAQmxDSO::clearStoredSoftwareTrigger() {
507 uInt64 total_samps = 0;
509 CHECK_DAQMX_RET(DAQmxGetReadTotalSampPerChanAcquired(m_task, &total_samps));
510 m_softwareTrigger->clear(total_samps, 1.0 / m_interval);
513 XNIDAQmxDSO::onSoftTrigStarted(
const shared_ptr<XNIDAQmxInterface::SoftwareTrigger> &) {
515 m_suspendRead =
true;
520 CHECK_DAQMX_RET(DAQmxStopTask(m_task));
523 const DSORawRecord &rec(m_dsoRawRecordBanks[m_dsoRawRecordBankLatest]);
524 m_softwareTrigger->setBlankTerm(m_interval * rec.recordLength);
528 CHECK_DAQMX_RET(DAQmxGetTaskNumChans(m_task, &num_ch));
531 CHECK_DAQMX_RET(DAQmxGetStartTrigType(m_task, &type));
532 if(type != DAQmx_Val_DigEdge) {
535 CHECK_DAQMX_RET(DAQmxStartTask(m_task));
536 m_suspendRead =
false;
541 XNIDAQmxDSO::onTaskDone_(TaskHandle task, int32 status,
void *data) {
543 obj->onTaskDone(task, status);
547 XNIDAQmxDSO::onTaskDone(TaskHandle , int32 status) {
549 gErrPrint(
getLabel() + XNIDAQmxInterface::getNIDAQmxErrMessage(status));
550 m_suspendRead =
true;
556 m_suspendRead =
true;
559 if(m_softwareTrigger) {
562 CHECK_DAQMX_RET(DAQmxGetReadTotalSampPerChanAcquired(m_task, &total_samps));
563 m_softwareTrigger->forceStamp(total_samps, 1.0 / m_interval);
564 m_suspendRead =
false;
569 CHECK_DAQMX_RET(DAQmxStartTask(m_task));
570 m_suspendRead =
false;
575 XNIDAQmxDSO::tryReadAISuspend(
const atomic<bool> &terminated) {
578 while(m_suspendRead && !terminated) msecsleep(30);
585 XNIDAQmxDSO::executeReadAI(
const atomic<bool> &terminated) {
586 while( !terminated) {
592 m_suspendRead =
true;
600 while( !terminated) {
603 tryReadAISuspend(terminated);
609 CHECK_DAQMX_RET(DAQmxGetReadNumChans(m_task, &num_ch));
611 tryReadAISuspend(terminated);
616 const DSORawRecord &old_rec(m_dsoRawRecordBanks[m_dsoRawRecordBankLatest]);
617 if(num_ch != old_rec.numCh)
620 const unsigned int size = m_recordBuf.size() / num_ch;
621 const float64 freq = 1.0 / m_interval;
622 unsigned int cnt = 0;
624 uint64_t samplecnt_at_trigger = 0;
625 if(m_softwareTrigger) {
626 shared_ptr<XNIDAQmxInterface::SoftwareTrigger> &vt(m_softwareTrigger);
628 while( !terminated) {
629 if(tryReadAISuspend(terminated))
632 CHECK_DAQMX_RET(DAQmxGetReadTotalSampPerChanAcquired(m_task, &total_samps));
633 samplecnt_at_trigger = vt->tryPopFront(total_samps, freq);
634 if(samplecnt_at_trigger) {
636 CHECK_DAQMX_RET(DAQmxGetBufInputBufSize(m_task, &bufsize));
637 if(total_samps - samplecnt_at_trigger + m_preTriggerPos > bufsize * 4 / 5) {
638 gWarnPrint(i18n(
"Buffer Overflow."));
642 int16 tmpbuf[NUM_MAX_CH];
644 CHECK_DAQMX_RET(DAQmxSetReadRelativeTo(m_task, DAQmx_Val_MostRecentSamp));
645 CHECK_DAQMX_RET(DAQmxSetReadOffset(m_task, -1));
646 CHECK_DAQMX_RET(DAQmxReadBinaryI16(m_task, 1,
647 0, DAQmx_Val_GroupByScanNumber,
648 tmpbuf, NUM_MAX_CH, &samps, NULL
650 CHECK_DAQMX_RET(DAQmxSetReadRelativeTo(m_task, DAQmx_Val_CurrReadPos));
651 CHECK_DAQMX_RET(DAQmxSetReadOffset(m_task, 0));
653 CHECK_DAQMX_RET(DAQmxGetReadCurrReadPos(m_task, &curr_rdpos));
654 int32 offset = samplecnt_at_trigger - m_preTriggerPos - curr_rdpos;
655 CHECK_DAQMX_RET(DAQmxSetReadOffset(m_task, offset));
659 msecsleep(lrint(1e3 * size * m_interval / 6));
663 if(m_preTriggerPos) {
664 CHECK_DAQMX_RET(DAQmxSetReadRelativeTo(m_task, DAQmx_Val_FirstPretrigSamp));
667 CHECK_DAQMX_RET(DAQmxSetReadRelativeTo(m_task, DAQmx_Val_FirstSample));
670 CHECK_DAQMX_RET(DAQmxSetReadOffset(m_task, 0));
675 const unsigned int num_samps = std::min(size, 8192u);
678 samps = std::min(size - cnt, num_samps);
679 while( !terminated) {
680 if(tryReadAISuspend(terminated))
683 int ret = DAQmxGetReadAvailSampPerChan(m_task, &space);
684 if( !ret && (space >= (uInt32)samps))
686 msecsleep(lrint(1e3 * (samps - space) * m_interval));
690 CHECK_DAQMX_RET(DAQmxReadBinaryI16(m_task, samps,
691 0.0, DAQmx_Val_GroupByScanNumber,
692 &m_recordBuf[cnt * num_ch], samps * num_ch, &samps, NULL
695 if( !m_softwareTrigger) {
696 CHECK_DAQMX_RET(DAQmxSetReadOffset(m_task, cnt));
699 CHECK_DAQMX_RET(DAQmxSetReadOffset(m_task, 0));
704 const unsigned int av = shot[ *
average()];
709 bank = 1 - m_dsoRawRecordBankLatest;
710 if(m_dsoRawRecordBanks[bank].tryLock())
712 bank = m_dsoRawRecordBankLatest;
713 if(m_dsoRawRecordBanks[bank].tryLock())
716 assert((bank >= 0) && (bank < 2));
717 DSORawRecord &new_rec(m_dsoRawRecordBanks[bank]);
718 unsigned int accumcnt = old_rec.accumCount;
720 if( !sseq || (accumcnt < av)) {
721 if( !m_softwareTrigger) {
724 CHECK_DAQMX_RET(DAQmxStopTask(m_task));
726 CHECK_DAQMX_RET(DAQmxStartTask(m_task));
731 cnt = std::min(cnt, old_rec.recordLength);
732 new_rec.recordLength = cnt;
734 new_rec.numCh = num_ch;
735 const unsigned int bufsize = new_rec.recordLength * num_ch;
736 tRawAI *pbuf = &m_recordBuf[0];
737 const int32_t *pold = &old_rec.record[0];
738 int32_t *paccum = &new_rec.record[0];
740 unsigned int div = bufsize / 4;
741 unsigned int rest = bufsize % 4;
742 if(new_rec.isComplex) {
743 double ph =
phaseOfRF(shot, samplecnt_at_trigger, m_interval);
744 double cosph = cos(ph);
745 double sinph = sin(ph);
747 for(
unsigned int i = 0; i < div; i++) {
748 *paccum++ = *pold++ + *pbuf++ * cosph;
749 *paccum++ = *pold++ + *pbuf++ * cosph;
750 *paccum++ = *pold++ + *pbuf++ * cosph;
751 *paccum++ = *pold++ + *pbuf++ * cosph;
753 for(
unsigned int i = 0; i < rest; i++)
754 *paccum++ = *pold++ + *pbuf++ * cosph;
756 for(
unsigned int i = 0; i < div; i++) {
757 *paccum++ = *pold++ + *pbuf++ * sinph;
758 *paccum++ = *pold++ + *pbuf++ * sinph;
759 *paccum++ = *pold++ + *pbuf++ * sinph;
760 *paccum++ = *pold++ + *pbuf++ * sinph;
762 for(
unsigned int i = 0; i < rest; i++)
763 *paccum++ = *pold++ + *pbuf++ * cosph;
766 for(
unsigned int i = 0; i < div; i++) {
767 *paccum++ = *pold++ + *pbuf++;
768 *paccum++ = *pold++ + *pbuf++;
769 *paccum++ = *pold++ + *pbuf++;
770 *paccum++ = *pold++ + *pbuf++;
772 for(
unsigned int i = 0; i < rest; i++)
773 *paccum++ = *pold++ + *pbuf++;
775 new_rec.acqCount = old_rec.acqCount + 1;
779 if(new_rec.isComplex)
781 int32_t *paccum = &(new_rec.record[0]);
783 unsigned int div = bufsize / 4;
784 unsigned int rest = bufsize % 4;
785 for(
unsigned int i = 0; i < div; i++) {
786 *paccum++ -= *psub++;
787 *paccum++ -= *psub++;
788 *paccum++ -= *psub++;
789 *paccum++ -= *psub++;
791 for(
unsigned int i = 0; i < rest; i++)
792 *paccum++ -= *psub++;
796 new_rec.accumCount = accumcnt;
798 m_dsoRawRecordBankLatest = bank;
803 if(sseq && (accumcnt >= av)) {
804 if(m_softwareTrigger) {
806 m_suspendRead =
true;
815 m_suspendRead =
true;
819 m_dsoRawRecordBankLatest = 0;
820 for(
unsigned int i = 0; i < 2; i++) {
828 rec.recordLength = rec.record.size() / rec.numCh / (rec.isComplex ? 2 : 1);
829 memset(&rec.record[0], 0, rec.record.size() *
sizeof(int32_t));
833 if(m_softwareTrigger) {
834 if( !m_lsnOnSoftTrigStarted)
835 m_lsnOnSoftTrigStarted = m_softwareTrigger->onStart().connectWeakly(
836 shared_from_this(), &XNIDAQmxDSO::onSoftTrigStarted);
838 clearStoredSoftwareTrigger();
839 m_suspendRead =
false;
842 CHECK_DAQMX_RET(DAQmxTaskControl(m_task, DAQmx_Val_Task_Commit));
843 statusPrinter()->printMessage(i18n(
"Restart the software-trigger source."));
849 if(m_task != TASK_UNDEF)
850 CHECK_DAQMX_RET(DAQmxStopTask(m_task));
853 CHECK_DAQMX_RET(DAQmxGetTaskNumChans(m_task, &num_ch));
855 CHECK_DAQMX_RET(DAQmxStartTask(m_task));
856 m_suspendRead =
false;
865 const DSORawRecord &rec(m_dsoRawRecordBanks[m_dsoRawRecordBankLatest]);
867 *seq_busy = ((
unsigned int)rec.acqCount < shot[ *
average()]);
872 XNIDAQmxDSO::getTimeInterval() {
877 XNIDAQmxDSO::aiRawToVolt(
const float64 *pcoeff, float64 raw) {
880 for(
unsigned int i = 0; i < CAL_POLY_ORDER; i++) {
881 y += *(pcoeff++) * x;
893 bank = m_dsoRawRecordBankLatest;
894 if(m_dsoRawRecordBanks[bank].tryLock())
897 if(m_dsoRawRecordBanks[bank].tryLock())
901 assert((bank >= 0) && (bank < 2));
904 if(rec.accumCount == 0) {
908 uInt32 num_ch = rec.numCh;
909 uInt32 len = rec.recordLength;
912 CHECK_DAQMX_RET(DAQmxGetReadChannelsToRead(m_task, buf,
sizeof(buf)));
916 writer->push((uint32_t)num_ch);
917 writer->push((uint32_t)m_preTriggerPos);
918 writer->push((uint32_t)len);
919 writer->push((uint32_t)rec.accumCount);
920 writer->push((
double)m_interval);
921 for(
unsigned int ch = 0; ch < num_ch; ch++) {
922 for(
unsigned int i = 0; i < CAL_POLY_ORDER; i++) {
924 if(rec.isComplex) ch_real = ch / 2;
925 writer->push((
double)m_coeffAI[ch_real][i]);
928 const int32_t *p = &(rec.record[0]);
929 const unsigned int size = len * num_ch;
930 for(
unsigned int i = 0; i < size; i++)
931 writer->push<int32_t>( *p++);
933 writer->insert(writer->end(), str.begin(), str.end());
935 writer->insert(writer->end(), str.begin(), str.end());
941 const unsigned int num_ch = reader.pop<uint32_t>();
942 const unsigned int pretrig = reader.pop<uint32_t>();
943 const unsigned int len = reader.pop<uint32_t>();
944 const unsigned int accumCount = reader.pop<uint32_t>();
945 const double interval = reader.pop<
double>();
947 tr[ *
this].setParameters(num_ch, - (
double)pretrig * interval, interval, len);
949 double *wave[NUM_MAX_CH * 2];
950 float64 coeff[NUM_MAX_CH * 2][CAL_POLY_ORDER];
951 for(
unsigned int j = 0; j < num_ch; j++) {
952 for(
unsigned int i = 0; i < CAL_POLY_ORDER; i++) {
953 coeff[j][i] = reader.pop<
double>();
956 wave[j] = tr[ *
this].waveDisp(j);
959 const float64 prop = 1.0 / accumCount;
960 for(
unsigned int i = 0; i < len; i++) {
961 for(
unsigned int j = 0; j < num_ch; j++)
962 *(wave[j])++ = aiRawToVolt(coeff[j], reader.pop<int32_t>() * prop);