lasp/src/lasp/device/lasp_daqconfig.h

299 lines
7.7 KiB
C++

#pragma once
#include "lasp_config.h"
#include "lasp_types.h"
#include <map>
#include <vector>
using std::string;
using std::to_string;
using boolvec = std::vector<bool>;
using dvec = std::vector<double>;
using usvec = std::vector<us>;
/**
* @brief Descriptor for data types containing more detailed information.
*/
class DataTypeDescriptor {
public:
/**
* @brief Basic data types coming from a DAQ that we can deal with. The naming
* will be self-explainging.
*/
enum class DataType {
dtype_fl32 = 0,
dtype_fl64 = 1,
dtype_int8 = 2,
dtype_int16 = 3,
dtype_int32 = 4
};
/**
* @brief Name of the datatype
*/
string name;
/**
* @brief Sample width of a single sample, in bytes
*/
unsigned sw;
/**
* @brief Whether the datatype is a floating point Y/N
*/
bool is_floating;
/**
* @brief The number from the enumeration
*/
DataType dtype;
/**
* @brief Down-cast a DataTypeDescriptor to a datatype
*
* @return The descriptor as an enum
*/
operator DataType() { return dtype; }
/**
* @brief Compare two data type descriptors. Returns true if the DataType
* enumerator is the same.
*
* @param o
*
* @return
*/
bool operator==(const DataTypeDescriptor &o) noexcept {
return dtype == o.dtype;
}
};
const DataTypeDescriptor dtype_desc_fl32 = {
"32-bits floating point", 4, true,
DataTypeDescriptor::DataType::dtype_fl32};
const DataTypeDescriptor dtype_desc_fl64 = {
"64-bits floating point", 8, true,
DataTypeDescriptor::DataType::dtype_fl64};
const DataTypeDescriptor dtype_desc_int8 = {
"8-bits integer", 1, false, DataTypeDescriptor::DataType::dtype_int8};
const DataTypeDescriptor dtype_desc_int16 = {
"16-bits integer", 2, false, DataTypeDescriptor::DataType::dtype_int16};
const DataTypeDescriptor dtype_desc_int32 = {
"32-bits integer", 4, false, DataTypeDescriptor::DataType::dtype_int32};
const std::map<DataTypeDescriptor::DataType, const DataTypeDescriptor>
dtype_map = {
{DataTypeDescriptor::DataType::dtype_fl32, dtype_desc_fl32},
{DataTypeDescriptor::DataType::dtype_fl64, dtype_desc_fl64},
{DataTypeDescriptor::DataType::dtype_int8, dtype_desc_int8},
{DataTypeDescriptor::DataType::dtype_int16, dtype_desc_int16},
{DataTypeDescriptor::DataType::dtype_int32, dtype_desc_int32},
};
class DaqApi {
public:
string apiname = "Invalid API";
int apicode = -1;
unsigned api_specific_subcode = 0;
DaqApi(string apiname, unsigned apicode, unsigned api_specific_subcode = 0)
: apiname(apiname), apicode(apicode),
api_specific_subcode(api_specific_subcode) {}
DaqApi() {}
bool operator==(const DaqApi &other) const {
return (apiname == other.apiname && apicode == other.apicode &&
api_specific_subcode == other.api_specific_subcode);
}
operator string() const { return apiname + ", code: " + to_string(apicode); }
static std::vector<DaqApi> getAvailableApis();
};
#if LASP_HAS_ULDAQ == 1
const DaqApi uldaqapi("UlDaq", 0);
#endif
#if LASP_HAS_RTAUDIO == 1
#include <RtAudio.h>
const DaqApi rtaudioAlsaApi("RtAudio Linux ALSA", 1, RtAudio::Api::LINUX_ALSA);
const DaqApi rtaudioPulseaudioApi("RtAudio Linux Pulseaudio", 2,
RtAudio::Api::LINUX_PULSE);
const DaqApi rtaudioWasapiApi("RtAudio Windows Wasapi", 3,
RtAudio::Api::WINDOWS_WASAPI);
const DaqApi rtaudioDsApi("RtAudio Windows DirectSound", 4,
RtAudio::Api::WINDOWS_DS);
const DaqApi rtaudioAsioApi("RtAudio Windows ASIO", 5,
RtAudio::Api::WINDOWS_ASIO);
#endif
class DeviceInfo;
/**
* @brief Stores channel configuration data for each channel.
*/
class DaqChannel {
public:
/**
* @brief Possible physical quantities that are recorded.
*/
enum class Qty {
Number,
AcousticPressure,
Voltage,
UserDefined
};
/**
* @brief Whether the channel is enabled.
*/
bool enabled = false;
string name = "";
/**
* @brief The conversion between recorded physical unit and stored /
* outputed number, i.e. Number/Volt or Number/Pa. Converting stored numbers
* to physical qty, *divide* by the sensitivity.
*/
double sensitivity = -1;
/**
* @brief For input-only: enable IEPE constant current power supply for
* this channel. Only for hardware that is capable of doing so.
*/
bool IEPEEnabled = false;
/**
* @brief Whether to enable HW AC-coupling for this channel.
*/
bool ACCouplingMode = false;
/**
* @brief Index in possible ranges for input / output
*/
int rangeIndex = 0;
/**
* @brief The physical quantity that is inputed / outputed
*/
Qty qty = Qty::Number;
/**
* @brief Whether to enable a digital high pass on the signal before
* passing the result in case of input, or outputing the result in case of
* output.
*/
double digitalHighPassCutOn = -1;
};
/**
* @brief Configuration of a DAQ device
*/
class DaqConfiguration {
public:
/**
* @brief Export the class to TOML markup language.
*
* @return String with TOML exported data.
*/
std::string toTOML() const;
/**
* @brief Load in a DAQConfiguration from TOML.
*
* @param toml String containing TOML data
*
* @return DaqConfiguration object
*/
static DaqConfiguration fromTOML(const std::string &toml);
DaqApi api;
/**
* @brief The internal device name this DAQ configuration applies to.
*/
string device_name;
/**
* @brief Channel configuration for input channels
*/
std::vector<DaqChannel> inchannel_config;
/**
* @brief Channel configuration for output channels
*/
std::vector<DaqChannel> outchannel_config;
/**
* @brief Index in list of sample rates that are available for the device.
*/
int sampleRateIndex = 0; //
/**
* @brief Required datatype for output, should be present in the list
*/
int dataTypeIndex = 0;
/**
* @brief The index in the array of frames per block that can be used for the
* device.
*/
int framesPerBlockIndex = 0;
/**
* @brief If set to true and if the device has this capability, the output
* channels are added as input channels as well.
*/
bool monitorOutput = false;
/**
* @brief Create a default configuration, with all channels disabled on both
* input and output, and default channel names
*
* @param deviceinfo DeviceInfo structure
*/
DaqConfiguration(const DeviceInfo &DeviceInfo);
DaqConfiguration() {}
/**
* @brief Check to see whether the DAQ configuration matches with the device.
* This means, some basic checks are done on channels, sampling rate, etc,
* and that the name corresponds with the device name.
*
* @param devinfo The DeviceInfo to check
*
* @return true if it matches. Otherwise false.
*/
bool match(const DeviceInfo &devinfo) const;
/**
* @brief Get the highest channel number from the list of enabled input
* channels.
*
* @return Index to the highest input channel. -1 if no input channels are
* enabled.
*/
int getHighestInChannel() const;
/**
* @brief Get the highest channel number from the list of enabled output
* channels.
*
* @return Index to the highest input channel. -1 if no output channels are
* enabled.
*/
int getHighestOutChannel() const;
/**
* @brief Get the lowest channel number from the list of enabled input
* channels.
*
* @return Index to the lowest input channel. -1 if no input channels are
* enabled.
*/
int getLowestInChannel() const;
/**
* @brief Get the lowest channel number from the list of enabled output
* channels.
*
* @return Index to the lowest input channel. -1 if no output channels are
* enabled.
*/
int getLowestOutChannel() const;
};