/* #define DEBUGTRACE_ENABLED */ #include "debugtrace.hpp" #include "lasp_config.h" #if LASP_HAS_ULDAQ == 1 #include "lasp_uldaq_bufhandler.h" #include "lasp_daq.h" InBufHandler::InBufHandler(DT9837A &daq, InDaqCallback cb) : BufHandler(daq, daq.neninchannels()), cb(cb) { DEBUGTRACE_ENTER; assert(daq.getHandle() != 0); monitorOutput = daq.monitorOutput; DaqInScanFlag inscanflags = DAQINSCAN_FF_DEFAULT; ScanOption scanoptions = SO_CONTINUOUS; UlError err = ERR_NO_ERROR; std::vector indescs; boolvec eninchannels_without_mon = daq.eninchannels(false); // Set ranges for each input. Below asks only channels that are not a // monitor channel (hence the false flag). dvec ranges = daq.inputRangeForEnabledChannels(false); us enabled_ch_counter = 0; for (us chin = 0; chin < 4; chin++) { if (eninchannels_without_mon[chin] == true) { DaqInChanDescriptor indesc; indesc.type = DAQI_ANALOG_SE; indesc.channel = chin; double rangeval = ranges.at(enabled_ch_counter); Range rangenum; if (fabs(rangeval - 1.0) < 1e-8) { rangenum = BIP1VOLTS; } else if (fabs(rangeval - 10.0) < 1e-8) { rangenum = BIP10VOLTS; } else { throw Daq::StreamException(Daq::StreamStatus::StreamError::logicError); std::cerr << "Fatal: input range value is invalid" << endl; return; } indesc.range = rangenum; indescs.push_back(indesc); enabled_ch_counter++; } } // Add possibly last channel as monitor if (monitorOutput) { DaqInChanDescriptor indesc; indesc.type = DAQI_DAC; indesc.channel = 0; /// The output only has a range of 10V, therefore the monitor of the /// output also has to be set to this value. indesc.range = BIP10VOLTS; indescs.push_back(indesc); } assert(indescs.size() == nchannels); DEBUGTRACE_MESSAGE("Starting input scan"); err = ulDaqInScan(daq.getHandle(), indescs.data(), nchannels, 2 * nFramesPerBlock, // Watch the 2 here! &samplerate, scanoptions, inscanflags, buf.data()); throwOnPossibleUlException(err); } void InBufHandler::start() { DEBUGTRACE_ENTER; ScanStatus status; TransferStatus transferStatus; UlError err = ulDaqInScanStatus(daq.getHandle(), &status, &transferStatus); throwOnPossibleUlException(err); totalFramesCount = transferStatus.currentTotalCount; topenqueued = true; botenqueued = true; } bool InBufHandler::operator()() { /* DEBUGTRACE_ENTER; */ bool ret = true; auto runCallback = ([&](us totalOffset) { /* DEBUGTRACE_ENTER; */ DaqData data(nFramesPerBlock, nchannels, dtype_descr.dtype); us monitorOffset = monitorOutput ? 1 : 0; /* /// Put the output monitor in front */ if (monitorOutput) { for (us frame = 0; frame < nFramesPerBlock; frame++) { data.value(frame, 0) = buf[totalOffset // Offset to lowest part of the buffer, or not + (frame * nchannels) // Data is interleaved, so skip each + (nchannels - 1)] // Monitor comes as last in the channel list, // but we want it first in the output data. ; } } // Now, all normal channels for (us channel = 0; channel < nchannels - monitorOffset; channel++) { /* DEBUGTRACE_PRINT(channel); */ for (us frame = 0; frame < nFramesPerBlock; frame++) { data.value(frame, channel + monitorOffset) = buf[totalOffset + (frame * nchannels) + channel]; } } return cb(data); }); ScanStatus status; TransferStatus transferStatus; UlError err = ulDaqInScanStatus(daq.getHandle(), &status, &transferStatus); throwOnPossibleUlException(err); us increment = transferStatus.currentTotalCount - totalFramesCount; totalFramesCount += increment; if (increment > nFramesPerBlock) { throw Daq::StreamException(Daq::StreamStatus::StreamError::inputXRun); } assert(status == SS_RUNNING); if (transferStatus.currentIndex < (long long)buffer_mid_idx) { topenqueued = false; if (!botenqueued) { runCallback(nchannels * nFramesPerBlock); botenqueued = true; } } else { botenqueued = false; if (!topenqueued) { runCallback(0); topenqueued = true; } } return ret; } InBufHandler::~InBufHandler() { // At exit of the function, stop scanning. DEBUGTRACE_ENTER; UlError err = ulDaqInScanStop(daq.getHandle()); if (err != ERR_NO_ERROR) { showErr(err); } } OutBufHandler::OutBufHandler(DT9837A &daq, OutDaqCallback cb) : BufHandler(daq, daq.nenoutchannels()), cb(cb) { DEBUGTRACE_MESSAGE("Starting output scan"); DEBUGTRACE_PRINT(nchannels); AOutScanFlag outscanflags = AOUTSCAN_FF_DEFAULT; ScanOption scanoptions = SO_CONTINUOUS; UlError err = ulAOutScan(daq.getHandle(), 0, 0, BIP10VOLTS, 2 * nFramesPerBlock, // Watch the 2 here! &samplerate, scanoptions, outscanflags, buf.data()); throwOnPossibleUlException(err); } void OutBufHandler::start() { ScanStatus status; TransferStatus transferStatus; UlError err = ulAOutScanStatus(daq.getHandle(), &status, &transferStatus); if (err != ERR_NO_ERROR) { showErr(err); throw rte("Unable to start output on DAQ"); } if (status != SS_RUNNING) { throw rte("Unable to start output on DAQ"); } totalFramesCount = transferStatus.currentTotalCount; topenqueued = true; botenqueued = true; } bool OutBufHandler::operator()() { DEBUGTRACE_ENTER; bool res = true; assert(daq.getHandle() != 0); UlError err = ERR_NO_ERROR; ScanStatus status; TransferStatus transferStatus; err = ulAOutScanStatus(daq.getHandle(), &status, &transferStatus); throwOnPossibleUlException(err); if (status != SS_RUNNING) { return false; } us increment = transferStatus.currentTotalCount - totalFramesCount; totalFramesCount += increment; if (increment > nFramesPerBlock) { cerr << "totalFramesCount: " << totalFramesCount << ". Detected output underrun" << endl; /* throw Daq::StreamException(Daq::StreamStatus::StreamError::outputXRun); */ } if (transferStatus.currentIndex < buffer_mid_idx) { topenqueued = false; if (!botenqueued) { DaqData d(nFramesPerBlock, 1,// Only one output channel dtype_descr.dtype); // Receive data, run callback cb(d); d.copyToRaw(0, reinterpret_cast(&(buf[buffer_mid_idx]))); botenqueued = true; } } else { botenqueued = false; if (!topenqueued) { DaqData d(nFramesPerBlock, 1,// Only one output channel dtype_descr.dtype); // Receive cb(d); d.copyToRaw(0, reinterpret_cast(&(buf[0]))); topenqueued = true; } } return res; } OutBufHandler::~OutBufHandler() { DEBUGTRACE_ENTER; UlError err = ulAOutScanStop(daq.getHandle()); if (err != ERR_NO_ERROR) { showErr(err); } } #endif