From 338bdca0655f5a10ea13d43db776242d9466c042 Mon Sep 17 00:00:00 2001
From: xiyehu2 <xiyehu2@illinois.edu>
Date: Mon, 23 Oct 2023 12:13:16 -0500
Subject: [PATCH] stable build

---
 Cpp/CMakeLists.txt              |   2 +-
 Cpp/lib/AWG.cpp                 |  42 +-----
 Cpp/lib/AWG.h                   |   8 +-
 Cpp/lib/CMakeLists.txt          |  18 +--
 Cpp/lib/external/CMakeLists.txt |   8 -
 Cpp/lib/waveform.cpp            | 252 ++++++++++++++++++++------------
 Cpp/lib/waveform.h              |  85 ++++++-----
 7 files changed, 224 insertions(+), 191 deletions(-)

diff --git a/Cpp/CMakeLists.txt b/Cpp/CMakeLists.txt
index 1636af2..98f785b 100644
--- a/Cpp/CMakeLists.txt
+++ b/Cpp/CMakeLists.txt
@@ -24,5 +24,5 @@ set(LIBS
 
 # main.exe
 project ("main")
-add_executable(main run.cpp)
+add_subdirectory(src)
 target_link_libraries(main ${LIBS})
diff --git a/Cpp/lib/AWG.cpp b/Cpp/lib/AWG.cpp
index 44c76b7..3c64736 100644
--- a/Cpp/lib/AWG.cpp
+++ b/Cpp/lib/AWG.cpp
@@ -32,40 +32,6 @@ void AWG::checkError() {
     }
 }
 
-//void* AWG::getPageAlignedMem(uint64 memSize) {
-//	/**
-//	 * returns a pointer to a page aligned mem location.
-//	 * 
-//	 * @param memSize size of memory to allocate, bytes
-//	 * @return pointer to start of a page aligned mem location
-//	 */
-//
-//	// for unknown reasons VirtualAlloc/VirtualFree leaks memory if memSize < 4096 (page size)
-//	// therefore use _aligned_malloc () to get small amounts of page aligned memory
-//	if (memSize >= 4096)
-//		return VirtualAlloc(NULL, (size_t)memSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
-//	else {
-//		void* pMem = _aligned_malloc((size_t)memSize, 4096);
-//		if (pMem == NULL)
-//			return NULL;
-//		memset(pMem, 0, (size_t)memSize);
-//		return pMem;
-//	}
-//}
-//
-//void AWG::freePageAlignedMem(void* pMem, uint64 memSize) {
-//	/**
-//	 * frees a page aligned memory space.
-//	 * 
-//	 * @param pMem pointer to a page aligned memory location
-//	 * @param memSize memory size in bytes to deallocate
-//	 */
-//	if (memSize >= 4096)
-//		VirtualFree(pMem, 0, MEM_RELEASE);
-//	else
-//		_aligned_free(pMem);
-//}
-//
 void AWG::open(int openIndex) {	
     if (this->isOpen()) {
         std::cout << "card already opened" << std::endl;
@@ -714,7 +680,8 @@ void AWG::setSeqModeStep(
     uint64 segment,
     uint64 nextStep,
     uint64 nLoop,
-    SEQ_LOOPCONDITION condition) {
+    SEQ_LOOPCONDITION condition
+) {
     if (!this->isOpen()) { return; }
     int64 mask = 
         (uint64(condition) << 32)
@@ -729,9 +696,10 @@ void AWG::setSeqModeStep(
 }
 
 void AWG::writeSeqModeSegment(
+    int segment,
     void* pDataBuffer,
-    int size,
-    int segment) {
+    int size
+) {
     if (!this->isOpen()) { return; }
     spcm_dwSetParam_i32(
         this->pCardHandle,
diff --git a/Cpp/lib/AWG.h b/Cpp/lib/AWG.h
index 4a21a20..73edc46 100644
--- a/Cpp/lib/AWG.h
+++ b/Cpp/lib/AWG.h
@@ -228,6 +228,7 @@ public:
      * @param ch channel index
      * @param amp amplitude (mV)
      * @param stopLvl enum CHANNEL_STOPLVL: ZERO, LOW, HIGH, HOLDLAST
+     * @param enable enable/disable channel output
      */
     void setChannel(int ch, int amp, CHANNEL_STOPLVL stopLvl, bool enable);
 
@@ -445,6 +446,7 @@ public:
      * @param step step to configure
      * @param segment memory segment step is associated with
      * @param nextStep index of next step after end loop condition is met
+     * @param nLoop number of loop the memory segment is replayed
      * @param condition end loop condition, enum SEQ_LOOPCONDITION
      */
     void setSeqModeStep(
@@ -458,14 +460,14 @@ public:
     /**
      * @brief write buffered data into a memory segment in sequence replay mode.
      * 
+     * @param segment memory segment to write to
      * @param pDataBuffer pointer to data memory, must be page aligned
      * @param size size of data buffer in number of samples
-     * @param segment memory segment to write to
      */
     void writeSeqModeSegment(
+        int segment,
         void* pDataBuffer, 
-        int size,
-        int segment
+        int size
     );
 
     // ---------------------data transfer---------------------
diff --git a/Cpp/lib/CMakeLists.txt b/Cpp/lib/CMakeLists.txt
index f1c7210..26f0bbc 100644
--- a/Cpp/lib/CMakeLists.txt
+++ b/Cpp/lib/CMakeLists.txt
@@ -1,6 +1,6 @@
 add_subdirectory(external)
 
-find_package(Eigen3 3.4 REQUIRED)
+# find_package(Eigen3 3.4 REQUIRED)
 target_sources(wfmLib
 	PRIVATE
 		waveform.cpp
@@ -8,9 +8,9 @@ target_sources(wfmLib
 		waveform.h
 		CSVhelper.hpp
 )
-target_link_libraries(wfmLib
-	Eigen3::Eigen
-)
+# target_link_libraries(wfmLib
+	# Eigen3::Eigen
+# )
 # target_link_libraries(wfmLib helperLib)
 
 target_sources(AWGLib
@@ -19,10 +19,10 @@ target_sources(AWGLib
 	PUBLIC
 		AWG.h
 )
-add_library(driverLib STATIC IMPORTED)
-set_target_properties(driverLib PROPERTIES
-    IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/driver_header/spcm_win64_msvcpp.lib"
-    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/driver_header"
-)
+# add_library(driverLib STATIC IMPORTED)
+# set_target_properties(driverLib PROPERTIES
+#     IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/driver_header/spcm_win64_msvcpp.lib"
+#     INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/driver_header"
+# )
 
 
diff --git a/Cpp/lib/external/CMakeLists.txt b/Cpp/lib/external/CMakeLists.txt
index da2c4db..e69de29 100644
--- a/Cpp/lib/external/CMakeLists.txt
+++ b/Cpp/lib/external/CMakeLists.txt
@@ -1,8 +0,0 @@
-# target_sources(tomlLib
-#     PRIVATE
-#         toml.cpp
-#     PUBLIC
-#         toml.hpp
-# )
-
-# target_include_directories(tomlLib PUBLIC ${CMAKE_CURRENT_LIST_DIR})
\ No newline at end of file
diff --git a/Cpp/lib/waveform.cpp b/Cpp/lib/waveform.cpp
index ac50e0f..11d06c2 100644
--- a/Cpp/lib/waveform.cpp
+++ b/Cpp/lib/waveform.cpp
@@ -5,82 +5,99 @@
 #include <vector>
 #include <string>
 #include <numeric>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
 
-ArrayWaveform::ArrayParam::ArrayParam() {
-    this->samplingRate = 0;
-    this->freqResolution = 0;
-}
+ArrayWaveform::ArrayWaveform() {}
 
-ArrayWaveform::ArrayParam::ArrayParam(const ArrayParam& other) {
-    this->samplingRate = other.samplingRate;
-    this->freqResolution = other.freqResolution;
-    this->freqTones = other.freqTones;
-    this->phases = other.phases;
-    this->amplitudes = other.amplitudes;
-}
+ArrayWaveform::~ArrayWaveform() { unbindBuffer(); }
+
+void* ArrayWaveform::getDataBuffer() { return this->pDataBuffer; }
 
-void ArrayWaveform::ArrayParam::setSamplingRate(unsigned long sr) {
-    this->samplingRate = sr;
+int64_t ArrayWaveform::getDataLen() { return this->dataLen; }
+
+void ArrayWaveform::setSamplingRate(ulong sr) {
+    this->wfmParam.samplingRate = sr;
 }
 
-void ArrayWaveform::ArrayParam::setFreqResolution(unsigned long fr) {
-    this->freqResolution = fr;
+ulong ArrayWaveform::getSamplingRate() { return this->wfmParam.samplingRate; }
+
+void ArrayWaveform::setFreqResolution(ulong fr) {
+    this->wfmParam.freqResolution = fr;
 }
 
-void ArrayWaveform::ArrayParam::setFreqTone(
+ulong ArrayWaveform::getFreqResolution() { return this->wfmParam.freqResolution; }
+
+void ArrayWaveform::setFreqTone(
     int centerFreq, 
     int freqSpacing,
     int numTones
 ) {
     int freqStart = centerFreq - 
         freqSpacing * int(std::floor(numTones / 2));
-    this->freqTones.setLinSpaced(
+    this->wfmParam.freqTones.setLinSpaced(
         numTones,
         freqStart,
         freqStart + freqSpacing * (numTones-1)
     );
 }
 
-void ArrayWaveform::ArrayParam::setFreqTone(const Eigen::VectorXd& tones) {
-    this->freqTones.resize(0);
-    this->freqTones.resize(tones.size());
-    this->freqTones = tones;
+void ArrayWaveform::setFreqTone(const std::vector<int>& tones) {
+    this->wfmParam.freqTones.resize(tones.size());
+    for (auto i = 0; i < tones.size(); i++) {
+        this->wfmParam.freqTones[i] = tones[i];
+    }
 }
 
-Eigen::VectorXd ArrayWaveform::ArrayParam::getFreqTone() {
-  return this->freqTones;
+std::vector<double> ArrayWaveform::getFreqTone() {
+    std::vector<double> v(
+        this->wfmParam.freqTones.data(),
+        this->wfmParam.freqTones.data() + this->wfmParam.freqTones.size()
+    );
+    return v;
 }
 
-void ArrayWaveform::ArrayParam::setPhase(const Eigen::VectorXd& phases) {
-    this->phases.resize(0);
-    this->phases.resize((phases.size()));
-    this->phases = phases;
+void ArrayWaveform::setPhase(const std::vector<double>& phases) {
+    this->wfmParam.phases.resize(phases.size());
+    for (auto i = 0; i < phases.size(); i++) {
+        this->wfmParam.phases[i] = phases[i];
+    }
 }
 
-Eigen::VectorXd ArrayWaveform::ArrayParam::getPhase() {
-  return this->phases;
+std::vector<double> ArrayWaveform::getPhase() {
+    std::vector<double> v(
+        this->wfmParam.phases.data(),
+        this->wfmParam.phases.data() + this->wfmParam.phases.size()
+    );
+  return v;
 }
 
-void ArrayWaveform::ArrayParam::setAmplitude(const Eigen::VectorXd& amplitudes) {
-    this->amplitudes.resize(0);
-    this->amplitudes.resize(amplitudes.size());
-    this->amplitudes = amplitudes;
+void ArrayWaveform::setAmplitude(const std::vector<double>& amplitudes) {
+    this->wfmParam.amplitudes.resize(amplitudes.size());
+    for (auto i = 0; i < amplitudes.size(); i++) {
+        this->wfmParam.amplitudes[i] = amplitudes[i];
+    }
 }
 
-Eigen::VectorXd ArrayWaveform::ArrayParam::getAmplitude() {
-  return this->amplitudes;
+std::vector<double> ArrayWaveform::getAmplitude() {
+    std::vector<double> v(
+        this->wfmParam.amplitudes.data(),
+        this->wfmParam.amplitudes.data() + this->wfmParam.amplitudes.size()
+    );
+  return v;
 }
 
-void ArrayWaveform::ArrayParam::setDefaultParam() {
-    if (this->freqTones.size() == 0) {return;}
-    auto numTones = this->freqTones.size();
-    this->setAmplitude(Eigen::VectorXd::Ones(numTones) * std::pow(2, 12));
-    this->setPhase(Eigen::VectorXd::Zero(numTones));
-    this->samplingRate = 614.4e6;
-    this->freqResolution = 1e3;
+void ArrayWaveform::setDefaultParam() {
+    if (this->wfmParam.freqTones.size() == 0) {return;}
+    auto numTones = this->wfmParam.freqTones.size();
+    this->setAmplitude(std::vector(numTones, 4096.0));
+    this->setPhase(std::vector(numTones, 0.0));
+    this->wfmParam.samplingRate = 614.4e6;
+    this->wfmParam.freqResolution = 1e3;
 }
 
-void ArrayWaveform::ArrayParam::saveParam(std::string fileName) {
+void ArrayWaveform::saveParam(std::string fileName) {
     const static Eigen::IOFormat csvFormat(
         Eigen::FullPrecision,
         Eigen::DontAlignCols,
@@ -90,72 +107,99 @@ void ArrayWaveform::ArrayParam::saveParam(std::string fileName) {
     );
     std::ofstream saveFile(fileName);
     if (saveFile.is_open()) {
-        saveFile << "samplingRate," << this->samplingRate << "\n";
-        saveFile << "freqResolution," << this->freqResolution << "\n";
+        saveFile << "samplingRate," << this->wfmParam.samplingRate << "\n";
+        saveFile << "freqResolution," << this->wfmParam.freqResolution << "\n";
         saveFile << "freqTones,"
-            << this->freqTones.format(csvFormat)
+            << this->wfmParam.freqTones.format(csvFormat)
             << "\n";
         saveFile << "phases,"
-            << this->phases.format(csvFormat)
+            << this->wfmParam.phases.format(csvFormat)
             << "\n";
         saveFile << "amplitudes,"
-            << this->amplitudes.format(csvFormat)
+            << this->wfmParam.amplitudes.format(csvFormat)
             << "\n";
         saveFile.close();
     }
 }
 
-void ArrayWaveform::ArrayParam::loadParam(std::string fileName) {
+void ArrayWaveform::loadParam(std::string fileName) {
     std::ifstream file(fileName);
+    if (!file.is_open()) {
+        std::cout << fileName
+            << " does not exists in loadParam()"
+            << std::endl;
+        return;
+    }
     int lineCounter = 0;
     for (auto& line : CSVRange(file)) {
         std::vector<int> lineDataI;
         std::vector<double> lineDataD;
         switch (lineCounter) {
         case 0:
-            this->samplingRate = std::stoi(std::string(line[1]));
+            this->wfmParam.samplingRate = std::stoi(std::string(line[0]));
             break;
         case 1:
-            this->freqResolution = std::stoi(std::string(line[1]));
+            this->wfmParam.freqResolution = std::stoi(std::string(line[0]));
             break;
         case 2:
-            for (auto i = 1; i < line.size(); i++) {
+            for (auto i = 0; i < line.size() - 1; i++) {
                 lineDataI.push_back(std::stoi(std::string(line[i])));
             }
-            this->freqTones.resize(lineDataI.size());
-            this->freqTones(lineDataI.data());
+            setFreqTone(lineDataI);
             break;
         case 3:
-            for (auto i = 1; i < line.size(); i++) {
+            for (auto i = 0; i < line.size() - 1; i++) {
                 lineDataD.push_back(std::stod(std::string(line[i])));
             }
-            this->phases.resize(lineDataD.size());
-            this->phases(lineDataD.data());
+            setPhase(lineDataD);
             break;
         case 4:
-            for (auto i = 1; i < line.size(); i++) {
+            for (auto i = 0; i < line.size() - 1; i++) {
                 lineDataD.push_back(std::stod(std::string(line[i])));
             }
-            this->amplitudes.resize(lineDataD.size());
-            this->amplitudes(lineDataD.data());
+            setAmplitude(lineDataD);
             break;
         }
         lineCounter++;
     }
 }
 
-void ArrayWaveform::ArrayParam::printParam() {
-    std::cout << "sampling rate: " << this->samplingRate << "\n";
-    std::cout << "frequency resolution: " << this->freqResolution << "\n\n";
-    std::cout << "frequency tones (MHz): " << "\n" << this->freqTones.array() / int(1e6) << "\n\n";
-    std::cout << "phases:" << "\n" << this->phases << "\n\n";
-    std::cout << "amplitudes:" << "\n" << this->amplitudes << "\n";
+void ArrayWaveform::printParam() {
+    std::cout << "sampling rate: " << this->wfmParam.samplingRate << "\n";
+    std::cout << "frequency resolution: " << this->wfmParam.freqResolution << "\n\n";
+    std::cout << "frequency tones (MHz): " << "\n" << this->wfmParam.freqTones.array() / int(1e6) << "\n\n";
+    std::cout << "phases:" << "\n" << this->wfmParam.phases << "\n\n";
+    std::cout << "amplitudes:" << "\n" << this->wfmParam.amplitudes << "\n\n";
 }
 
-ulong ArrayWaveform::getMinSampleLen(
-    ulong samplingRate,
-    ulong freqResolution
-) {
+void ArrayWaveform::bindBuffer(int64_t bytes) {
+    this->unbindBuffer();
+    int fd = open("/dev/zero", O_RDONLY);
+    this->pDataBuffer = mmap(
+        NULL,
+        bytes,
+        PROT_READ | PROT_WRITE,
+        MAP_PRIVATE,
+        fd,
+        0
+    );
+    if (this->pDataBuffer != MAP_FAILED) {
+        memset(this->pDataBuffer, 0, bytes);
+        this->dataLen = bytes / 2;
+        int16_t* pData = (int16_t*) this->pDataBuffer;
+    }
+    close(fd);    
+}
+
+void ArrayWaveform::unbindBuffer() {
+    if (this->dataLen != 0 and this->pDataBuffer != nullptr) {
+        munmap(this->pDataBuffer, this->dataLen);
+        this->pDataBuffer = nullptr;
+        this->dataLen = 0;
+    }
+}
+
+ulong ArrayWaveform::getMinSampleLen(ulong samplingRate, ulong freqResolution) {
     return 2 * samplingRate / std::gcd(samplingRate, freqResolution);
 }
 
@@ -215,23 +259,31 @@ double ArrayWaveform::setMovingSegment(
     return nextPhase;
 }
 
-EigenVectorXi16 ArrayWaveform::getStaticWaveform(const ArrayParam& param) {
-    auto minSampleLen = 2 * param.samplingRate
-        / std::gcd(param.samplingRate, param.freqResolution);
+std::pair<int16_t*, int64_t> ArrayWaveform::getStaticWaveform() {
+    auto minSampleLen = 2 * this->wfmParam.samplingRate
+        / std::gcd(
+            this->wfmParam.samplingRate,
+            this->wfmParam.freqResolution
+        );
     Eigen::VectorXd t = Eigen::VectorXd::LinSpaced(
         minSampleLen,
         0,
         minSampleLen - 1
-    ) / param.samplingRate;
-    Eigen::MatrixXd wfmMatrix = Eigen::sin(
-        ((param.freqTones * t.transpose() * M_PI * 2).array().colwise()
-        + param.phases.array())
-    ).array().colwise() * param.amplitudes.array();
-    return wfmMatrix.colwise().sum().cast<int16_t>();
+    ) / this->wfmParam.samplingRate;
+    Eigen::MatrixXd wfmMatrixrix = Eigen::sin(
+        (
+            (this->wfmParam.freqTones * t.transpose() * M_PI * 2)
+        .array().colwise()
+        + this->wfmParam.phases.array())
+    ).array().colwise() * this->wfmParam.amplitudes.array();
+    bindBuffer(minSampleLen * 2); // bytes
+    auto pData = (int16_t*) this->pDataBuffer;
+    Eigen::Map<EigenVectorXi16> dataMap(pData, minSampleLen);
+    dataMap = wfmMatrixrix.colwise().sum().cast<int16_t>();
+    return std::pair(pData, int64_t(minSampleLen));
 }
 
-EigenVectorXi16 ArrayWaveform::getTrickWaveform(
-    const ArrayParam& param,
+std::pair<int16_t*, int64_t> ArrayWaveform::getTrickWaveform(
     std::set<int> siteIndex,
     double df,
     double tauMove,
@@ -239,7 +291,7 @@ EigenVectorXi16 ArrayWaveform::getTrickWaveform(
 ) {
     if ((tauMove == 0 and tauStay == 0)
         or siteIndex.empty()) {
-        return getStaticWaveform(param);
+        return getStaticWaveform();
     }
     if (tauMove != 0 and tauStay != 0) {
         tauStay = std::ceil((tauMove + tauStay) * df) / df - tauMove;
@@ -249,21 +301,25 @@ EigenVectorXi16 ArrayWaveform::getTrickWaveform(
         tauStay = std::ceil(tauStay * df) / df;
     }
     auto tauTotal = tauMove * 2 + tauStay;
-    ulong sampleLen = getSampleLen(tauTotal, param.samplingRate, param.freqResolution);
-    ulong moveLen = tauMove * param.samplingRate;
-    ulong stayLen = tauStay * param.samplingRate;
+    ulong sampleLen = getSampleLen(
+        tauTotal,
+        this->wfmParam.samplingRate,
+        this->wfmParam.freqResolution
+    );
+    ulong moveLen = tauMove * this->wfmParam.samplingRate;
+    ulong stayLen = tauStay * this->wfmParam.samplingRate;
     auto idxSeg0 = moveLen;
     auto idxSeg1 = moveLen + stayLen;
     auto idxSeg2 = moveLen + stayLen + moveLen;
-    auto t = Eigen::ArrayXd::LinSpaced(sampleLen, 0, sampleLen - 1) / param.samplingRate;
-    Eigen::MatrixXd wfmMat(sampleLen, param.freqTones.size()); // site wfm stored column by column
-    for (auto i = 0; i < param.freqTones.size(); i++) {
-        wfmMat.col(i) = t;
-        Eigen::Ref<Eigen::ArrayXd> siteWfm = wfmMat.col(i);
-        auto fInit = param.freqTones[i];
+    auto t = Eigen::ArrayXd::LinSpaced(sampleLen, 0, sampleLen - 1) / this->wfmParam.samplingRate;
+    Eigen::MatrixXd wfmMatrix(sampleLen, this->wfmParam.freqTones.size()); // site wfm stored column by column
+    for (auto i = 0; i < this->wfmParam.freqTones.size(); i++) {
+        wfmMatrix.col(i) = t;
+        Eigen::Ref<Eigen::ArrayXd> siteWfm = wfmMatrix.col(i);
+        auto fInit = this->wfmParam.freqTones[i];
         auto fFinal = fInit + df;
-        auto phi = param.phases[i];
-        auto amp = param.amplitudes[i];
+        auto phi = this->wfmParam.phases[i];
+        auto amp = this->wfmParam.amplitudes[i];
         if (siteIndex.contains(i)) {
             if (tauMove != 0) {
                 phi = setMovingSegment(
@@ -291,10 +347,14 @@ EigenVectorXi16 ArrayWaveform::getTrickWaveform(
             setStaticSegment(siteWfm, fInit, phi, amp);
         }
     }
-    return wfmMat.rowwise().sum().cast<int16_t> ();
+    bindBuffer(sampleLen * 2);
+    auto pData = (int16_t*) this->pDataBuffer;
+    Eigen::Map<EigenVectorXi16> dataMap(pData, sampleLen);
+    dataMap = wfmMatrix.rowwise().sum().cast<int16_t> ();
+    return std::pair(pData, int64_t(sampleLen));
 }
 
-void ArrayWaveform::saveCSV(std::string fileName, EigenVectorXi16 wfm) {
+void ArrayWaveform::saveWaveform(std::string fileName) {
     const static Eigen::IOFormat csvFormat(
         Eigen::FullPrecision,
         Eigen::DontAlignCols,
@@ -302,6 +362,8 @@ void ArrayWaveform::saveCSV(std::string fileName, EigenVectorXi16 wfm) {
         ",",
         ""
     );
+    auto pData = (int16_t*) this->pDataBuffer;
+    auto wfm = Eigen::Map<EigenVectorXi16>(pData, this->dataLen);
     std::ofstream saveFile(fileName);
     if (saveFile.is_open()) {
         saveFile << wfm.format(csvFormat);
diff --git a/Cpp/lib/waveform.h b/Cpp/lib/waveform.h
index b923d3b..a46f682 100644
--- a/Cpp/lib/waveform.h
+++ b/Cpp/lib/waveform.h
@@ -1,48 +1,24 @@
 #pragma once
-#include <Eigen/Dense>
+#include "external/Eigen/Dense"
 #include <string>
 #include <set>
 typedef Eigen::Vector<int16_t, Eigen::Dynamic> EigenVectorXi16;
 
-namespace ArrayWaveform {
-
-    class ArrayParam {
-        public:
+class ArrayWaveform {
+    private:
+    void* pDataBuffer;
+    int64_t dataLen;
+    struct WaveformParam {
         unsigned long samplingRate;
         unsigned long freqResolution;
         Eigen::VectorXd freqTones;
         Eigen::VectorXd phases;
         Eigen::VectorXd amplitudes;
-
-        ArrayParam();
-        ArrayParam(const ArrayParam& other);
-
-        void setSamplingRate(unsigned long sr);
-        void setFreqResolution(unsigned long fr);
-
-        void setFreqTone(
-            int centerFreq, 
-            int freqSpacing,
-            int numTones
-        );
-        void setFreqTone(const Eigen::VectorXd& tones);
-        Eigen::VectorXd getFreqTone();
-        void setPhase(const Eigen::VectorXd& phases);
-        Eigen::VectorXd getPhase();
-        void setAmplitude(const Eigen::VectorXd& amplitudes);
-        Eigen::VectorXd getAmplitude();
-        void setDefaultParam();
-        void saveParam(std::string fileName);
-        void loadParam(std::string fileName);
-        void printParam();
     };
+    WaveformParam wfmParam;
 
-    ulong getMinSampleLen(ulong samplingRate, ulong freqResolution);
-    ulong getSampleLen(
-        double tau,
-        ulong samplingRate,
-        ulong freqResolution
-    );
+    void bindBuffer(int64_t bytes);
+    void unbindBuffer();
 
     double setStaticSegment(
         Eigen::Ref<Eigen::VectorXd> timeSeries,
@@ -57,18 +33,51 @@ namespace ArrayWaveform {
         double initPhase,
         double amp
     );
+    
+    public:
+    ArrayWaveform();
+    ~ArrayWaveform();
 
-    EigenVectorXi16 getStaticWaveform(const ArrayParam& param);
-    EigenVectorXi16 getTrickWaveform(
-        const ArrayParam& param,
+    void* getDataBuffer();
+    int64_t getDataLen();
+
+    void setSamplingRate(ulong sr);
+    ulong getSamplingRate();
+    void setFreqResolution(ulong fr);
+    ulong getFreqResolution();
+
+    void setFreqTone(
+        int centerFreq, 
+        int freqSpacing,
+        int numTones
+    );
+    void setFreqTone(const std::vector<int>& tones);
+    std::vector<double> getFreqTone();
+    void setPhase(const std::vector<double>& phases);
+    std::vector<double> getPhase();
+    void setAmplitude(const std::vector<double>& amplitudes);
+    std::vector<double> getAmplitude();
+    void setDefaultParam(); // optional helper
+    void saveParam(std::string fileName); // optional helper
+    void loadParam(std::string fileName); // optional helper
+    void printParam(); // optional helper
+
+    ulong getMinSampleLen(ulong samplingRate, ulong freqResolution);
+    ulong getSampleLen(
+        double tau,
+        ulong samplingRate,
+        ulong freqResolution
+    );
+    std::pair<int16_t*, int64_t> getStaticWaveform();
+    std::pair<int16_t*, int64_t> getTrickWaveform(
         std::set<int> siteIndex,
         double df,
         double tauMove=0,
         double tauStay=0
     );
 
-    void saveCSV(std::string fileName, EigenVectorXi16 wfm);
+    void saveWaveform(std::string fileName); // optional helper;
 };
 
-namespace ArbitraryWaveform {};
+class ArbitraryWaveform {};
 
-- 
GitLab