lasp/src/lasp/device/lasp_daq.h

208 lines
5.5 KiB
C++

#pragma once
#include "lasp_config.h"
#include "lasp_daqdata.h"
#include "lasp_deviceinfo.h"
#include "lasp_types.h"
#include <functional>
#include <memory>
/**
* \defgroup device Device interfacing
* \addtogroup device
* @{
* @brief Callback of DAQ for input data. Callback should return
* false for a stop request.
*/
using InDaqCallback = std::function<bool(const DaqData &)>;
/**
* @brief
*/
using OutDaqCallback = std::function<bool(DaqData &)>;
/**
* @brief Base cass for all DAQ (Data Acquisition) interfaces. A DAQ can be a
* custom device, or for example a sound card.
*/
class Daq : public DaqConfiguration, public DeviceInfo {
protected:
Daq(const DeviceInfo &devinfo, const DaqConfiguration &config);
Daq(const Daq &) = delete;
public:
/**
* @brief Information regarding a stream.
*/
class StreamStatus {
public:
enum class StreamError {
noError,
inputXRun,
outputXRun,
driverError,
systemError,
threadError,
logicError,
apiSpecificError
};
/**
* @brief Map between error types and messages
*/
inline static const std::map<StreamError, std::string> errorMessages{
{StreamError::noError, "No error"},
{StreamError::inputXRun, "Input buffer overrun"},
{StreamError::outputXRun, "Output buffer underrun"},
{StreamError::driverError, "Driver error"},
{StreamError::systemError, "System error"},
{StreamError::threadError, "Thread error"},
{StreamError::logicError, "Logic error (probably a bug)"},
};
bool isRunning = false;
/**
* @brief Check if stream has error
*
* @return true if there is an error.
*/
bool error() const { return errorType != StreamError::noError; };
StreamError errorType{StreamError::noError};
std::string errorMsg() const { return errorMessages.at(errorType); }
/**
* @brief Returns true if everything is OK with a certain stream and the
* stream is running.
*
* @return as described above.
*/
bool runningOK() const { return isRunning && !error(); }
};
/**
* @brief Create a Daq based on given device info and configuration
*
* @param devinfo Device information of device to be used.
* @param config Configuation to apply to the deviec
*
* @return Pointer to Daq device created.
*/
static std::unique_ptr<Daq> createDaq(const DeviceInfo &devinfo,
const DaqConfiguration &config);
/**
* @brief Start the Daq.
*
* @param inCallback Function that is called with input data as argument,
* and which expects output data as a return value. If no input data is
* required, this callback should be unset.
* @param outCallback Function that is called when output data is required.
* If the stream does not require output data, this callback should be unset.
*/
virtual void start(InDaqCallback inCallback, OutDaqCallback outCallback) = 0;
/**
* @brief Stop the Daq device. Throws an exception if the device is not
* running at the time this method is called.
*/
virtual void stop() = 0;
virtual ~Daq() = 0;
/**
* @brief Returns the number of enabled input channels
*
* @param include_monitorchannels if true, all channels that are internally
* monitored are added to the list.
*
* @return number of enabled input channels
*/
us neninchannels(bool include_monitorchannels = true) const;
/**
* @brief Returns the number of enabled output channels
*
* @return Number of enabled output channels
*/
us nenoutchannels() const;
/**
* @brief Create a vector of boolean values of the enabled input channels.
*
* @param include_monitor If set to true and a monitor channel is available,
* the first index in the array will correspond to the monitor channel, and
* whether it is enabled
*
* @return Boolean vector
*/
boolvec eninchannels(bool include_monitor = true) const;
/**
* @brief Create an array of booleans for each enabled output channel.
*
* @return Boolean vector
*/
boolvec enoutchannels() const;
/**
* @brief Returns current sample rate
*
* @return Sample rate in [Hz]
*/
double samplerate() const;
/**
* @brief Returns the input range for each channel. Means the minimum from
* the absolute value of the minumum and maximum value that is allowed to
* pass unclipped.
*
* @param ch The channel index from the input channels.
*
* @return Maximum offset from 0 before clipping.
*/
double inputRangeForChannel(us ch) const;
/**
* @brief Returns datatype (enum) corresponding to the datatype of the
* samples.
*
* @return That as stated aboce
*/
DataTypeDescriptor::DataType dataType() const;
/**
* @brief More elaborate description of the datatypes.
*
* @return A DataTypeDescriptor
*/
const DataTypeDescriptor& dtypeDescr() const;
/**
* @brief The number of frames that is send in a block of DaqData.
*
* @return The number of frames per block
*/
us framesPerBlock() const {
return availableFramesPerBlock.at(framesPerBlockIndex);
}
/**
* @brief Get stream status corresponding to current DAQ.
*
* @return StreamStatus object.
*/
virtual StreamStatus getStreamStatus() const = 0;
/**
* @brief Whether the device runs in duplex mode (both input and output), or
* false if only input / only output.
*
* @return true if duplex
*/
bool duplexMode() const {
return (neninchannels() > 0 && nenoutchannels() > 0);
}
};
/** @} */