Skip to content
Snippets Groups Projects
waveform.h 6.65 KiB
#pragma once
#include "external/Eigen/Dense"
#include <string>
#include <set>
typedef Eigen::Vector<int16_t, Eigen::Dynamic> EigenVectorXi16;

/**
 * @brief class for array waveform generation
 */
class ArrayWaveform {
    private:
    void* pDataBuffer; // points to a page aligned mem location where data is stored
    int64_t dataLen; // length of waveform
    struct WaveformParam {
        unsigned long samplingRate;
        unsigned long freqResolution;
        Eigen::VectorXd freqTones;
        Eigen::VectorXd phases;
        Eigen::VectorXd amplitudes;
    };
    WaveformParam wfmParam;

    /**
     * @brief allocates a page-aligned memory buffer for waveform data
     * 
     * @param bytes number of bytes to allocate
     */
    void bindBuffer(int64_t bytes);
    /**
     * @brief frees pDataBuffer
     */
    void unbindBuffer();

    /**
     * @brief generate a static frequency segment
     * 
     * @param timeSeries reference to an array filled with timestamps
     * @param f frequency
     * @param initPhase initial phase
     * @param amp amplitude
     * @return ending phase of the segment
     */
    double setStaticSegment(
        Eigen::Ref<Eigen::VectorXd> timeSeries,
        double f,
        double initPhase,
        double amp
    );
    /**
     * @brief generate a dynamic frequency segment
     * 
     * @param timeSeries reference to an array filled with timestamps
     * @param fInit initial frequency
     * @param fFinal final frequency
     * @param initPhase initial phase
     * @param amp amplitude
     * @return end phase of the segment
     */
    double setMovingSegment(
        Eigen::Ref<Eigen::VectorXd> timeSeries,
        double fInit,
        double fFinal,
        double initPhase,
        double amp
    );
    
    public:
    /**
     * @brief default constructor, all private members are set to 0/nullptr
     */
    ArrayWaveform();

    /**
     * @brief default destructor, calls unbindBuffer
     */
    ~ArrayWaveform();

    /**
     * @brief get the pointer to data buffer
     * 
     * @return void* pointer to data buffer, nullptr if uninitialized
     */
    void* getDataBuffer();

    /**
     * @brief get number of samples in current waveform
     * 
     * @return int64_t number of samples
     */
    int64_t getDataLen();

    /**
     * @brief set sampling rate
     * 
     * @param sr sampling rate (Hz)
     */
    void setSamplingRate(ulong sr);

    /**
     * @brief get sampling rate
     * 
     * @return sampling rate (Hz)
     */
    ulong getSamplingRate();

    /**
     * @brief set freqeuncy resolution
     * 
     * @param fr frequency resolution (Hz)
     */

    void setFreqResolution(ulong fr);

    /**
     * @brief get frequency resolution
     * 
     * @return frequency resolution (Hz)
     */
    ulong getFreqResolution();

    /**
     * @brief set array frequency tone
     * 
     * @param centerFreq center frequency of array (Hz)
     * @param freqSpacing freqeuncy spacing in the array (Hz)
     * @param numTones total number of tones to generate
     */
    void setFreqTone(
        int centerFreq, 
        int freqSpacing,
        int numTones
    );

    /**
     * @brief set array frequency tone
     * 
     * @param tones vector of frequency tones (Hz)
     */
    void setFreqTone(const std::vector<int>& tones);
    /**
     * @brief get array frequency tone
     * 
     * @return std::vector<double> vector of frequency tones (Hz)
     */
    std::vector<double> getFreqTone();

    /**
     * @brief set intial phase of all tones
     * 
     * @param phases range: [0 - 2pi)
     */
    void setPhase(const std::vector<double>& phases);

    /**
     * @brief get intial phase of all tones
     * @return vector of phases
     */
    std::vector<double> getPhase();

    /**
     * @brief set amplitudes of all tones
     * 
     * @param amplitudes range: [0, 2^15-1]
     */
    void setAmplitude(const std::vector<double>& amplitudes);

    /**
     * @brief get amplitudes of all tones
     * 
     * @return vector of amplitudes
     */
    std::vector<double> getAmplitude();

    /**
     * @brief Set phases to 0 and amplitudes to 2000
     */
    void setDefaultParam();

    /**
     * @brief save current waveform parameters to csv file
     * csv has format:
     * -----  col 0          | col 1         | ...
     * row 0  samplignRate   |               | 
     * row 1  freqResolution |               | 
     * row 2  freqTones[0]   | freqTones[1]  | ...
     * row 3  phases[0]      | phases[1]     | ...
     * row 4  amplitudes[0]  | amplitudes[1] | ...     */
    void saveParam(std::string fileName);

    /**
     * @brief load waveform parameters from file
     * 
     * @param fileName name of file to load from, must be of .csv
     */
    void loadParam(std::string fileName);

    /**
     * @brief debugging helper to print current waveform parameters
     */
    void printParam();

    /**
     * @brief get minimum data length that fulfills rounding 
     * requirements
     * @param samplingRate sampling rate (Hz)
     * @param freqResolution frequency resolution (Hz)
     * @return number of samples
     */
    ulong getMinSampleLen(ulong samplingRate, ulong freqResolution);

    /**
     * @brief get data length close to speficifed time and also
     * fulfills rounding requirements
     * 
     * @param tau time (s)
     * @param samplingRate sampling rate (Hz) 
     * @param freqResolution frequency resolution (Hz)
     * @return number of samples
     */
    ulong getSampleLen(
        double tau,
        ulong samplingRate,
        ulong freqResolution
    );

    /**
     * @brief generate a static frequency waveform from current set
     * of parameters
     * 
     * @return std::pair(pDataBuffer: void*, dataLength: int64_t)
     */
    std::pair<void*, int64_t> getStaticWaveform();

    /**
     * @brief generate a tricky-trick waveform from current set of
     * parameters
     * 
     * @param siteIndex index of array sites to perform tricky-trick
     * @param df frequency to move by (Hz)
     * @param tauMove moving time (s)
     * @param tauStay wait time (s)
     * @return std::pair(pDataBuffer: void*, dataLength: int64_t) 
     */
    std::pair<void*, int64_t> getTrickWaveform(
        std::set<int> siteIndex,
        double df,
        double tauMove=0,
        double tauStay=0
    );

    /**
     * @brief save currently generated waveform to csv file
     * csv has format:
     * -----  col 0 | col 1 | col 2 | ...
     * row 0  data0 | data1 | data2 | ...
     * @param fileName name of file to save to, must be of .csv
     */
    void saveWaveform(std::string fileName);
};

/**
 * @brief class for arbitrary waveform generation
 * @todo do this
 */
class ArbitraryWaveform {};