246 lines
6.9 KiB
C++
246 lines
6.9 KiB
C++
/* #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<DaqInChanDescriptor> 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<double>(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<double>(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<byte_t *>(&(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<byte_t *>(&(buf[0])));
|
|
|
|
topenqueued = true;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
OutBufHandler::~OutBufHandler() {
|
|
DEBUGTRACE_ENTER;
|
|
UlError err = ulAOutScanStop(daq.getHandle());
|
|
if (err != ERR_NO_ERROR) {
|
|
showErr(err);
|
|
}
|
|
}
|
|
#endif
|