LASP 1.0
Library for Acoustic Signal Processing
Loading...
Searching...
No Matches
lasp_uldaq_bufhandler.cpp
Go to the documentation of this file.
1/* #define DEBUGTRACE_ENABLED */
2#include "debugtrace.hpp"
3#include "lasp_config.h"
4
5#if LASP_HAS_ULDAQ == 1
7#include "lasp_daq.h"
8
10 : BufHandler(daq, daq.neninchannels()), cb(cb)
11
12{
13 DEBUGTRACE_ENTER;
14 assert(daq.getHandle() != 0);
15
16 monitorOutput = daq.monitorOutput;
17
18 DaqInScanFlag inscanflags = DAQINSCAN_FF_DEFAULT;
19 ScanOption scanoptions = SO_CONTINUOUS;
20 UlError err = ERR_NO_ERROR;
21
22 std::vector<DaqInChanDescriptor> indescs;
23 boolvec eninchannels_without_mon = daq.eninchannels(false);
24
25 // Set ranges for each input. Below asks only channels that are not a
26 // monitor channel (hence the false flag).
27 dvec ranges = daq.inputRangeForEnabledChannels(false);
28
29 us enabled_ch_counter = 0;
30 for (us chin = 0; chin < 4; chin++) {
31 if (eninchannels_without_mon[chin] == true) {
32 DaqInChanDescriptor indesc;
33 indesc.type = DAQI_ANALOG_SE;
34 indesc.channel = chin;
35
36 double rangeval = ranges.at(enabled_ch_counter);
37 Range rangenum;
38 if (fabs(rangeval - 1.0) < 1e-8) {
39 rangenum = BIP1VOLTS;
40 } else if (fabs(rangeval - 10.0) < 1e-8) {
41 rangenum = BIP10VOLTS;
42 } else {
44 std::cerr << "Fatal: input range value is invalid" << endl;
45 return;
46 }
47 indesc.range = rangenum;
48 indescs.push_back(indesc);
49 enabled_ch_counter++;
50 }
51 }
52
53 // Add possibly last channel as monitor
54 if (monitorOutput) {
55 DaqInChanDescriptor indesc;
56 indesc.type = DAQI_DAC;
57 indesc.channel = 0;
60 indesc.range = BIP10VOLTS;
61 indescs.push_back(indesc);
62 }
63 assert(indescs.size() == nchannels);
64
65 DEBUGTRACE_MESSAGE("Starting input scan");
66
67 err = ulDaqInScan(daq.getHandle(), indescs.data(), nchannels,
68 2 * nFramesPerBlock, // Watch the 2 here!
69 &samplerate, scanoptions, inscanflags, buf.data());
71}
73
74 DEBUGTRACE_ENTER;
75 ScanStatus status;
76 TransferStatus transferStatus;
77 UlError err = ulDaqInScanStatus(daq.getHandle(), &status, &transferStatus);
79
80 totalFramesCount = transferStatus.currentTotalCount;
81 topenqueued = true;
82 botenqueued = true;
83}
84
86
87 /* DEBUGTRACE_ENTER; */
88
89 bool ret = true;
90
91 auto runCallback = ([&](us totalOffset) {
92 /* DEBUGTRACE_ENTER; */
93
95
96 us monitorOffset = monitorOutput ? 1 : 0;
97 /* /// Put the output monitor in front */
98 if (monitorOutput) {
99 for (us frame = 0; frame < nFramesPerBlock; frame++) {
100 data.value<double>(frame, 0) =
101 buf[totalOffset // Offset to lowest part of the buffer, or not
102 + (frame * nchannels) // Data is interleaved, so skip each
103 + (nchannels - 1)] // Monitor comes as last in the channel list,
104 // but we want it first in the output data.
105 ;
106 }
107 }
108
109 // Now, all normal channels
110 for (us channel = 0; channel < nchannels - monitorOffset; channel++) {
111 /* DEBUGTRACE_PRINT(channel); */
112 for (us frame = 0; frame < nFramesPerBlock; frame++) {
113 data.value<double>(frame, channel + monitorOffset) =
114 buf[totalOffset + (frame * nchannels) + channel];
115 }
116 }
117 return cb(data);
118 });
119
120 ScanStatus status;
121 TransferStatus transferStatus;
122
123 UlError err = ulDaqInScanStatus(daq.getHandle(), &status, &transferStatus);
125
126 us increment = transferStatus.currentTotalCount - totalFramesCount;
127 totalFramesCount += increment;
128
129 if (increment > nFramesPerBlock) {
131 }
132 assert(status == SS_RUNNING);
133
134 if (transferStatus.currentIndex < (long long)buffer_mid_idx) {
135 topenqueued = false;
136 if (!botenqueued) {
137 runCallback(nchannels * nFramesPerBlock);
138 botenqueued = true;
139 }
140 } else {
141 botenqueued = false;
142 if (!topenqueued) {
143 runCallback(0);
144 topenqueued = true;
145 }
146 }
147 return ret;
148}
150 // At exit of the function, stop scanning.
151 DEBUGTRACE_ENTER;
152 UlError err = ulDaqInScanStop(daq.getHandle());
153 if (err != ERR_NO_ERROR) {
154 showErr(err);
155 }
156}
157
159 : BufHandler(daq, daq.nenoutchannels()), cb(cb) {
160
161 DEBUGTRACE_MESSAGE("Starting output scan");
162 DEBUGTRACE_PRINT(nchannels);
163 AOutScanFlag outscanflags = AOUTSCAN_FF_DEFAULT;
164 ScanOption scanoptions = SO_CONTINUOUS;
165 UlError err = ulAOutScan(daq.getHandle(), 0, 0, BIP10VOLTS,
166 2 * nFramesPerBlock, // Watch the 2 here!
167 &samplerate, scanoptions, outscanflags, buf.data());
168
170}
172
173 ScanStatus status;
174 TransferStatus transferStatus;
175
176 UlError err = ulAOutScanStatus(daq.getHandle(), &status, &transferStatus);
177 if (err != ERR_NO_ERROR) {
178 showErr(err);
179 throw rte("Unable to start output on DAQ");
180 }
181 if (status != SS_RUNNING) {
182 throw rte("Unable to start output on DAQ");
183 }
184 totalFramesCount = transferStatus.currentTotalCount;
185 topenqueued = true;
186 botenqueued = true;
187}
189
190 DEBUGTRACE_ENTER;
191 bool res = true;
192 assert(daq.getHandle() != 0);
193
194 UlError err = ERR_NO_ERROR;
195
196 ScanStatus status;
197 TransferStatus transferStatus;
198
199 err = ulAOutScanStatus(daq.getHandle(), &status, &transferStatus);
201 if (status != SS_RUNNING) {
202 return false;
203 }
204 us increment = transferStatus.currentTotalCount - totalFramesCount;
205 totalFramesCount += increment;
206
207 if (increment > nFramesPerBlock) {
208 cerr << "totalFramesCount: " << totalFramesCount << ". Detected output underrun" << endl;
209 /* throw Daq::StreamException(Daq::StreamStatus::StreamError::outputXRun); */
210 }
211
212 if (transferStatus.currentIndex < buffer_mid_idx) {
213 topenqueued = false;
214 if (!botenqueued) {
215 DaqData d(nFramesPerBlock, 1,// Only one output channel
217 // Receive data, run callback
218 cb(d);
219 d.copyToRaw(0, reinterpret_cast<byte_t *>(&(buf[buffer_mid_idx])));
220
221 botenqueued = true;
222 }
223 } else {
224 botenqueued = false;
225 if (!topenqueued) {
226 DaqData d(nFramesPerBlock, 1,// Only one output channel
228 // Receive
229 cb(d);
230 d.copyToRaw(0, reinterpret_cast<byte_t *>(&(buf[0])));
231
232 topenqueued = true;
233 }
234 }
235 return res;
236}
237
239 DEBUGTRACE_ENTER;
240 UlError err = ulAOutScanStop(daq.getHandle());
241 if (err != ERR_NO_ERROR) {
242 showErr(err);
243 }
244}
245#endif
const DataTypeDescriptor dtype_descr
The type of data, in this case always double precision floats.
std::vector< double > buf
Storage capacity for the DAQ I/O.
us nchannels
The number of channels, number of frames per callback (block).
us totalFramesCount
Counter for the total number of frames acquired / sent since the start of the stream.
long long buffer_mid_idx
bool botenqueued
Whether the bottom part of the buffer is enqueued enqueued.
DT9837A & daq
Reference to underlying Daq.
bool topenqueued
Whether the top part of the buffer is enqueued.
Data translation DT9837A Daq device.
Used for internal throwing of exceptions.
Definition lasp_daq.h:90
bool monitorOutput
If set to true and if the device has this capability, the output channels are added as input channels...
Data coming from / going to DAQ. Non-interleaved format, which means data in buffer is ordered by cha...
boolvec eninchannels(const bool include_monitor=true) const
Create a vector of boolean values of the enabled input channels.
Definition lasp_daq.cpp:109
dvec inputRangeForEnabledChannels(const bool include_monitor=true) const
Returns the input range for each channel. Maximum allowed absolute value of the signal that can pass ...
Definition lasp_daq.cpp:90
DataType dtype
The number from the enumeration.
InBufHandler(DT9837A &daq, InDaqCallback cb)
bool operator()()
InBufHandler::operator()()
bool operator()()
OutBufHandler::operator()
OutBufHandler(DT9837A &daq, OutDaqCallback cb)
std::runtime_error rte
Definition lasp_daq.cpp:16
void throwOnPossibleUlException(UlError err)
Throws an appropriate stream exception based on the UlError number. The mapping is based on the error...
std::vector< double > dvec
std::function< void(DaqData &)> OutDaqCallback
Definition lasp_daq.h:23
std::function< void(const DaqData &)> InDaqCallback
Definition lasp_daq.h:18
void showErr(UlError err)
Print error message to stderr.
char byte_t
std::vector< bool > boolvec
size_t us
We often use boolean values.
Definition lasp_types.h:29