#pragma once #include "lasp_daqconfig.h" #include "lasp_types.h" #include #include #include #include #include #include /** \addtogroup device * @{ */ class Daq; using byte_t = char; /** * @brief Data coming from / going to DAQ. **Non-interleaved format**, which * means data in buffer is ordered by channel: _ptr[frame+channel*nframes] */ class DaqData { protected: /** * @brief Storage for the actual data. */ byte_t *_data; public: /** * @brief The number of frames in this block of data. */ us nframes; /** * @brief The number of channels */ us nchannels; /** * @brief The data type corresponding to a sample */ DataTypeDescriptor::DataType dtype; /** * @brief The data type description corresponding to a sample */ DataTypeDescriptor dtype_descr; /** * @brief The number of bytes per sample (sample width, sw) */ us sw; /** * @brief Initialize an empty frame of data * * @param nframes The number of frames * @param nchannels The number of channels * @param dtype The data type */ DaqData(const us nframes, const us nchannels, const DataTypeDescriptor::DataType dtype); /** * @brief Initialize using no allocation */ DaqData(const DaqData &); /* DaqData(DaqData &&); */ DaqData &operator=(const DaqData &) = delete; virtual ~DaqData(); /** * @brief Return pointer to the raw data corresponding to a certain sample * (frame, channel combo). * * @param frame The frame number * @param channel The channel number * * @return Pointer to sample, not casted to final type */ byte_t *raw_ptr(const us frame = 0, const us channel = 0) { assert(frame < nframes); assert(channel < nchannels); return &(_data[sw * (frame + channel * nframes)]); } const byte_t *raw_ptr(const us frame = 0, const us channel = 0) const { assert(frame < nframes); assert(channel < nchannels); return &(_data[sw * (frame + channel * nframes)]); } /** * @brief Return the total number of bytes * * @return Number of bytes of data. */ us size_bytes() const { return sw * nchannels * nframes; } /** * @brief Copy data from a set of raw pointers of *uninterleaved* data. * Overwrites any existing available data. * * @param ptrs Pointers to data from channels */ void copyInFromRaw(const std::vector &ptrs); /** * @brief Copy contents of DaqData for a certain channel to a raw pointer. * * @param channel The channel to copy. * @param ptr The pointer where data is copied to. */ void copyToRaw(const us channel, byte_t *ptr); /** * @brief Convert samples to floating point values and return a nframes x * nchannels array of floats. For data that is not already floating-point, * the data is scaled back from MAX_INT to +1.0. * * @return Array of floats */ arma::Mat toFloat() const; /** * @brief Convert samples to floating point value; and return a nframes * column vector of floats. For data that is not already floating-point, * the data is scaled back from MAX_INT to +1.0. * * @param channel The channel to convert * * @return Array of floats */ arma::Col toFloat(const us channel_no) const; /** * @brief Convert single sample to floating point value; and return a nframes * column vector of floats. For data that is not already floating-point, * the data is scaled back from MAX_INT to +1.0. * * @param channel The channel to convert * @param frame_no The frame number to convert * * @return Float value */ d toFloat(const us frame_no, const us channel_no) const; // Return value based on type template T &value(const us frame, const us channel) { #if LASP_DEBUG == 1 check_type(); #endif return *reinterpret_cast(raw_ptr(frame, channel)); } template const T &value(const us frame, const us channel) const { #if LASP_DEBUG == 1 check_type(); #endif return *reinterpret_cast(raw_ptr(frame, channel)); } /** * @brief For debugging purposes: prints some stats */ void print() const; protected: template void check_type() const { using DataType = DataTypeDescriptor::DataType; bool correct = false; static_assert(std::is_arithmetic::value); if constexpr (std::is_floating_point::value) { correct |= sizeof(T) == 4 && dtype == DataType::dtype_fl32; correct |= sizeof(T) == 8 && dtype == DataType::dtype_fl64; } else { correct |= sizeof(T) == 1 && dtype == DataType::dtype_int8; correct |= sizeof(T) == 2 && dtype == DataType::dtype_int16; correct |= sizeof(T) == 4 && dtype == DataType::dtype_int32; } if (!correct) { throw std::runtime_error("Wrong datatype for template argument"); } } template arma::Mat toFloat() const; template arma::Col toFloat(const us channel_no) const; template d toFloat(const us frame_no, const us channel_no) const; /** * @brief Return a value as floating point. Does a conversion from integer to * float, if the stored type is integer. Also scales by its maximum value. * * @tparam T The original type * @param frame Frame number * @param channel Channel number * * @return Value converted to floating point */ }; /** @} */