diff --git a/.gitignore b/.gitignore
index 5dea49c8f1dba63b0c0c1669c828824e1549aad2..57204b7edc1d8be1576f1914a200d8db42731ba0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,5 @@
 Python/test.ipynb
 __pycache__/
-Python/lib/AWG.py
 *.pyc
 *.png
 *.npz
@@ -138,4 +137,7 @@ FakesAssemblies/
 **/*.DesktopClient/ModelManifest.xml
 **/*.Server/GeneratedArtifacts
 **/*.Server/ModelManifest.xml
-_Pvt_Extensions
\ No newline at end of file
+_Pvt_Extensions
+/Cpp/.vscode
+/Cpp/test.cpp
+/Cpp/test.exe
diff --git a/Cpp/Cpp.vcxproj b/Cpp/Cpp.vcxproj
index 2a4f15c9992528bfbff9c94cf7024f35b9fbb18a..83cb67cda0787aa8971f2e0bce3dd009054f2eed 100644
--- a/Cpp/Cpp.vcxproj
+++ b/Cpp/Cpp.vcxproj
@@ -72,7 +72,7 @@
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <RunCodeAnalysis>true</RunCodeAnalysis>
-    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSet>NativeRecommendedRules.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
@@ -109,10 +109,13 @@
       <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ConformanceMode>true</ConformanceMode>
       <EnablePREfast>true</EnablePREfast>
+      <LanguageStandard>stdcpp20</LanguageStandard>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalLibraryDirectories>C:\Lab\awg-control\Cpp\lib\driver_header;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>spcm_win64_msvcpp.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -137,11 +140,14 @@
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="lib\AWG.h" />
-    <ClInclude Include="lib\dlltyp.h" />
-    <ClInclude Include="lib\errors.h" />
-    <ClInclude Include="lib\regs.h" />
-    <ClInclude Include="lib\spcerr.h" />
-    <ClInclude Include="lib\spcm_drv.h" />
+    <ClInclude Include="lib\driver_header\dlltyp.h" />
+    <ClInclude Include="lib\driver_header\errors.h" />
+    <ClInclude Include="lib\driver_header\regs.h" />
+    <ClInclude Include="lib\driver_header\spcerr.h" />
+    <ClInclude Include="lib\driver_header\spcm_drv.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="cpp.hint" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
diff --git a/Cpp/Cpp.vcxproj.filters b/Cpp/Cpp.vcxproj.filters
index 61a75a94cd699cdb352036ea102559958aa57940..41493f74438abd4e921d69707dcee7131abf41d9 100644
--- a/Cpp/Cpp.vcxproj.filters
+++ b/Cpp/Cpp.vcxproj.filters
@@ -26,20 +26,23 @@
     <ClInclude Include="lib\AWG.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="lib\dlltyp.h">
+    <ClInclude Include="lib\driver_header\dlltyp.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="lib\errors.h">
+    <ClInclude Include="lib\driver_header\errors.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="lib\regs.h">
+    <ClInclude Include="lib\driver_header\regs.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="lib\spcerr.h">
+    <ClInclude Include="lib\driver_header\spcerr.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="lib\spcm_drv.h">
+    <ClInclude Include="lib\driver_header\spcm_drv.h">
       <Filter>Header Files</Filter>
     </ClInclude>
   </ItemGroup>
+  <ItemGroup>
+    <None Include="cpp.hint" />
+  </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/Cpp/cpp.hint b/Cpp/cpp.hint
new file mode 100644
index 0000000000000000000000000000000000000000..155867e17bb32ef3fec900aca26f58c5be394448
--- /dev/null
+++ b/Cpp/cpp.hint
@@ -0,0 +1,6 @@
+// Hint files help the Visual Studio IDE interpret Visual C++ identifiers
+// such as names of functions and macros.
+// For more information see https://go.microsoft.com/fwlink/?linkid=865984
+#define drv_handle
+#define int32
+#define int64
diff --git a/Cpp/lib/AWG.cpp b/Cpp/lib/AWG.cpp
index 164b11b7d4a99a5961925f5107b5e60669ef600e..263270151d9c26090754a05052ceadac14275319 100644
--- a/Cpp/lib/AWG.cpp
+++ b/Cpp/lib/AWG.cpp
@@ -1,6 +1,1023 @@
 #include "AWG.h"
+#include <iostream>
+#include <cmath>
 
-AWG::AWG(int cardID) noexcept
-{
+AWG::AWG() noexcept {	
+	this->pCardHandle = nullptr;
+	this->cardIdx = -1;
+	this->serialNumber = -1;
+	this->instMemSize = -1;
+	this->bytesPerSample = -1;
+	this->maxSampleRate = -1;
+}
 
-};
+AWG::~AWG() {
+	// TODO: do this
+	return;
+}
+
+void AWG::checkError() {
+	/**
+	 * printout error if detected.
+	 * 
+	 */
+	if (this->pCardHandle == nullptr) { return; }
+	char errorMsg[ERRORTEXTLEN];
+	if (
+		spcm_dwGetErrorInfo_i32(this->pCardHandle, NULL, NULL, errorMsg)
+		!= ERR_OK
+	) {
+		std::cout << "AWG error" << std::string(errorMsg) 
+			<< "\ncard closed\n";
+		this->close();
+	}
+}
+
+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) {	
+	/**
+	 * opens a connection to AWG by index.
+	 * 
+	 * @param openIndex card index, 0 or 1
+	 */
+	if (!this->isOpen()) {
+		std::cout << "card already opened" << std::endl;
+		return;
+	}
+
+	auto openMsg = "/dev/spcm" + std::to_string(openIndex);
+	this->pCardHandle = spcm_hOpen(openMsg.c_str());
+	if (pCardHandle == nullptr) {
+		std::cout << "card open failed" << std::endl;
+		return;
+	}
+
+	this->cardIdx = openIndex;
+	spcm_dwGetParam_i32(
+		this->pCardHandle,
+		SPC_PCISERIALNO,
+		&this->serialNumber
+	);
+	spcm_dwGetParam_i64(
+		this->pCardHandle,
+		SPC_PCISAMPLERATE,
+		&this->maxSampleRate
+	);
+	spcm_dwGetParam_i64(
+		this->pCardHandle,
+		SPC_PCIMEMSIZE,
+		&this->instMemSize
+	);
+	spcm_dwGetParam_i32(
+		this->pCardHandle,
+		SPC_MIINST_BYTESPERSAMPLE,
+		&this->bytesPerSample
+	);
+
+	this->checkError();
+}
+
+bool AWG::isOpen() {
+	/**
+	 * check if a connection to AWG exists.
+	 * 
+	 * @return true or false
+	 */
+	if (this->pCardHandle == nullptr) { return false; }
+	return true;
+	this->checkError();
+}
+
+void AWG::close() {
+	/**
+	 * close the connection to AWG.
+	 * 
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_vClose(this->pCardHandle);
+	this->pCardHandle = nullptr;
+}
+
+void AWG::reset() {
+	/**
+	 * resets the AWG card, equivalent to a power reset.
+	 *
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_M2CMD,
+		M2CMD_CARD_RESET
+	);
+	this->checkError();
+}
+
+int AWG::getCardIdx() {
+	return this->cardIdx;
+}
+
+int AWG::getSerialNumber() {
+	return this->serialNumber;
+}
+
+int64 AWG::getInstMemSize() {
+	return this->instMemSize;
+}
+
+int AWG::getBytesPerSample() {
+	return this->bytesPerSample;
+}
+
+int64 AWG::getMaxSampleRate() {
+	return this->maxSampleRate;
+}
+
+void AWG::setSampleRate(int64 sampleRate) {
+	if (!this->isOpen()) { return; }
+	if (sampleRate < 0 or sampleRate > this->maxSampleRate) {
+		std::cout << sampleRate << "exceeds max sample rate" << std::endl;
+		return;
+	}
+	spcm_dwSetParam_i64(
+		this->pCardHandle,
+		SPC_SAMPLERATE,
+		sampleRate
+	);
+}
+
+int64 AWG::getSampleRate() {
+	if (!this->isOpen()) { return 0; }
+	int64 sr;
+	spcm_dwGetParam_i64(
+		this->pCardHandle,
+		SPC_SAMPLERATE,
+		&sr
+	);
+	this->checkError();
+	return sr;
+}
+
+void AWG::setActiveChannels(std::set<int> channels) {
+	/**
+	 * activate channels for next run, resets last set.
+	 * 
+	 * @param channels vector of channel index (0-3)
+	 */
+	if (!this->isOpen()) { return; }
+	int64 chMask = 0;
+	for (auto ch : channels) {
+		chMask = chMask | int64(pow(2,ch)); 
+	}
+	spcm_dwSetParam_i64(
+		this->pCardHandle,
+		SPC_CHENABLE,
+		chMask
+	);
+	this->checkError();
+	this->activeChannels = channels;
+}
+
+void AWG::setChannelAmp(int ch, int amp) {
+	/**
+	 * set channel amplitude.
+	 * 
+	 * @param ch channel index
+	 * @param amp amplitude (mV)
+	 */
+	if (!this->isOpen()) { return; }
+	const auto regStep = SPC_AMP1 - SPC_AMP0;
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_AMP0 + ch * regStep,
+		amp
+	);
+	this->checkError();
+}
+
+void AWG::setChannelStopLvl(int ch, CHANNEL_STOPLVL stopLvl) {
+	/**
+	 * set channel stop level.
+	 * 
+	 * @param ch channel index
+	 * @param stopLvl options: ZERO,LOW,HIGH,HOLDLAST
+	 */
+	if (!this->isOpen()) { return; }
+	const auto regStep = SPC_CH1_STOPLEVEL - SPC_CH0_STOPLEVEL;
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_CH0_STOPLEVEL + ch * regStep,
+		int32(stopLvl)
+	);
+	this->checkError();
+}
+
+void AWG::toggleChannelOutput(int ch, bool enable) {
+	/**
+	 * toggle channel output.
+	 * 
+	 * @param ch channel index
+	 * @param enable true or false
+	 */
+	if (!this->isOpen()) { return; }
+	if (ch < 0 or ch > 3) {
+		std::cout << ch << "is not an allowed channel index"
+			<< std::endl;
+		return;
+	}
+	const auto regStep = SPC_ENABLEOUT1 - SPC_ENABLEOUT0;
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_ENABLEOUT0 + ch * regStep,
+		enable
+	);
+	this->checkError();
+}
+
+void AWG::setChannel(int ch, int amp, CHANNEL_STOPLVL stopLvl, bool enable) {
+	/**
+	 * channel macro set amplitude, stop level, and enables output.
+	 * 
+	 * @param ch channel index
+	 * @param amp amplitude (mV)
+	 * @param stopLvl options: ZERO, LOW, HIGH, HOLDLAST
+	 */
+	this->setChannelAmp(ch, amp);
+	this->setChannelStopLvl(ch, stopLvl);
+	this->toggleChannelOutput(ch, enable);
+}
+
+int AWG::getChannelCount() {
+	if (!this->isOpen()) { return 0; }
+	int32 numCh;
+	spcm_dwGetParam_i32(
+		this->pCardHandle,
+		SPC_CHCOUNT,
+		&numCh
+	);
+	this->checkError();
+	return numCh;
+}
+
+std::set<int> AWG::getChannelActivated() {
+	return this->activeChannels;	
+}
+
+void AWG::setChannelDiffMode(int chPair, bool enable) {
+	/**
+	 * set channel 0(2) and channel 1(3) to differential output mode.
+	 *
+	 * @param chPair 0 for channel 0,1, 1 for channel 2,3
+	 * @param enable true or false
+	 */
+	if (!this->isOpen()) { return; }
+	if (chPair != 0 && chPair != 1) {
+		std::cout << "unable to parse input chPair: "
+			<< chPair << std::endl;
+		return;
+	}
+	if (enable) {
+		if (chPair == 0 && this->activeChannels.contains(1)) {
+			std::cout << "channel 1 must disabled for chPair=0"
+				"in differential output mode" << std::endl;
+			return;
+		}
+		if (chPair == 1 && this->activeChannels.contains(3)) {
+			std::cout << "channel 3 must disabled for chPair=1"
+				"in differential output mode" << std::endl;
+			return;
+		}
+	}
+	const auto regStep = SPC_DIFF2 - SPC_DIFF0;
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_DIFF0 + chPair * regStep,
+		enable
+	);
+	this->checkError();
+}
+
+void AWG::setChannelDoubleMode(int chPair, bool enable) {
+	/**
+	 * set channel 0(2) and channel 1(3) to differential output mode.
+	 *
+	 * @param chPair 0 for channel 0,1, 1 for channel 2,3
+	 * @param enable true or false
+	 */
+	if (!this->isOpen()) { return; }
+	if (chPair != 0 && chPair != 1) {
+		std::cout << "unable to parse input chPair: "
+			<< chPair << std::endl;
+		return;
+	}
+	if (enable) {
+		if (chPair == 0 && this->activeChannels.contains(1)) {
+			std::cout << "channel 1 must disabled for chPair=0"
+				"in double output mode" << std::endl;
+			return;
+		}
+		if (chPair == 1 && this->activeChannels.contains(3)) {
+			std::cout << "channel 3 must disabled for chPair=1"
+				"in double output mode" << std::endl;
+			return;
+		}
+	}
+	const auto regStep = SPC_DOUBLEOUT2 - SPC_DOUBLEOUT0;
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_DOUBLEOUT0 + chPair * regStep,
+		enable
+	);
+	this->checkError();
+}
+
+void AWG::writeSetup() {
+	/**
+	 * write current setup to card without starting hardware,
+	 * some settings may not be changed while card is running.
+	 * 
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_M2CMD,
+		M2CMD_CARD_WRITESETUP
+	);
+	this->checkError();
+}
+
+void AWG::cardRun() {
+	/**
+	 * starts the card with all selected settings.
+	 * 
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_M2CMD,
+		M2CMD_CARD_START
+	);
+	this->checkError();
+}
+
+void AWG::cardStop() {
+	/**
+	 * stops the card, no effect if not running.
+	 * 
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_M2CMD,
+		M2CMD_CARD_STOP
+	);
+	this->checkError();
+}
+
+void AWG::waitReady() {
+	/**
+	 * wait until card finished current output run.
+	 * TODO: check if this blocks.
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_M2CMD,
+		M2CMD_CARD_WAITREADY
+	);
+	this->checkError();
+}
+
+void AWG::setTimeOut(int time) {
+	/**
+	 * set a timeout time in ms, 0 to disable.
+	 *
+	 * @param time
+	 */
+	if (!this->isOpen()) { return; }
+	if (time < 0) {
+		std::cout << time << "is an invalid timeout time" << std::endl;
+	}
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_TIMEOUT,
+		time
+	);
+	this->checkError();
+}
+
+int AWG::getTimeOut() {
+	if (!this->isOpen()) { return 0; }
+	int32 time;
+	spcm_dwGetParam_i32(
+		this->pCardHandle,
+		SPC_TIMEOUT,
+		&time
+	);
+	return time;
+}
+
+void AWG::printCardStatus() {
+	if (!this->isOpen()) { return; }
+	int32 status;
+	spcm_dwGetParam_i32(
+		this->pCardHandle,
+		SPC_M2STATUS,
+		&status
+	);
+	std::cout << STATUS_NAMES.at(status) << std::endl;
+}
+
+void AWG::toggleTrigger(bool enable) {
+	/**
+	 * toggle the trigger detection.
+	 * 
+	 * @param enable
+	 */
+	if (!this->isOpen()) { return; }
+	auto command = enable 
+		? M2CMD_CARD_ENABLETRIGGER
+		: M2CMD_CARD_DISABLETRIGGER;
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_M2CMD,
+		command
+	);
+	this->checkError();
+}
+
+void AWG::forceTrigger() {
+	/**
+	 * sends a software trigger, equivalent to an actual trigger.
+	 * 
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_M2CMD,
+		M2CMD_CARD_FORCETRIGGER
+	);
+	this->checkError();
+}
+
+void AWG::waitTrigger() {
+	/**
+	 * wait until trigger event.
+	 * TODO: check if this blocks.
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_M2CMD,
+		M2CMD_CARD_WAITTRIGGER
+	);
+	this->checkError();
+}
+
+void AWG::setTrigMaskOr(std::initializer_list<TRIGGER_MASK> trigMasks) {
+	/**
+	 * program the OR trigger mask.
+	 *
+	 * @param trigMasks 1 or more TRIGGER_MASK
+	 */
+	if (!this->isOpen()) { return; }
+	auto mask = 0;
+	for (auto m : trigMasks) {
+		mask = mask | int32(m);
+	}
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_TRIG_ORMASK,
+		mask
+	);
+	this->checkError();
+}
+
+void AWG::setTrigMaskAnd(std::initializer_list<TRIGGER_MASK> trigMasks) {
+	/**
+	 * program the AND trigger mask.
+	 *
+	 * @param trigMasks 1 or more TRIGGER_MASK
+	 */
+	if (!this->isOpen()) { return; }
+	int mask = 0;
+	for (auto m : trigMasks) {
+		mask = mask | int32(m);
+	}
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_TRIG_ANDMASK,
+		mask
+	);
+	this->checkError();
+}
+
+void AWG::setTrigMode(int trigChannel, TRIGGER_MODE trigMode) {
+	/**
+	 * sets the trigger mode of trigger channel.
+	 * 
+	 * @param trigChannel 0 or 1 (labeled EXT0 and EXT1 on board)
+	 * @param trigMode see TRIGGER_MODE for options
+	 */
+	if (!this->isOpen()) { return; }
+	if (trigChannel != 0 and trigChannel != 1) {
+		std::cout << "invalid trigger channel: " 
+			<< trigChannel << std::endl;
+		return;
+	}
+	auto trigRegister = trigChannel
+		? SPC_TRIG_EXT1_MODE
+		: SPC_TRIG_EXT0_MODE;
+
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		trigRegister,
+		int32(trigMode)
+	);
+	this->checkError();
+}
+
+void AWG::setTrigTerm(int term) {
+	/**
+	 * sets the trigger input termination.
+	 *
+	 * \param term 0 for high impedance, 1 for 50 Ohm.
+	 */
+
+	if (!this->isOpen()) { return; }
+	if (term != 0) {
+		std::cout << "invalid trigger input termination setting: "
+			<< term << std::endl;
+		return;
+	}
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_TRIG_TERM,
+		term
+	);
+	this->checkError();
+}
+
+int AWG::getTrigTerm() {
+	if (!this->isOpen()) { return -1; }
+	int32 term;
+	spcm_dwGetParam_i32(
+		this->pCardHandle,
+		SPC_TRIG_TERM,
+		&term
+	);
+	this->checkError();
+	return term;
+}
+
+void AWG::setTrigCoupling(int channel, int coupling) {
+	/**
+	 * sets trigger coupling to DC or AC.
+	 * 
+	 * @param coupling 1 for AC, 0 for DC
+	 */
+	if (!this->isOpen()) { return; }
+	if (coupling != 0 and coupling != 1) {
+		std::cout << "invalid trigger coupling setting :" << coupling
+			<< std::endl;
+		return;
+	}
+	auto trigChannelReg = channel ? 
+		SPC_TRIG_EXT1_ACDC : SPC_TRIG_EXT0_ACDC;
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		trigChannelReg,
+		coupling
+	);
+	this->checkError();
+}
+
+int AWG::getTrigCoupling(int channel) {
+	if (!this->isOpen()) { return -1; }
+	auto trigChannelReg = channel ? 
+		SPC_TRIG_EXT1_ACDC : SPC_TRIG_EXT0_ACDC;
+	int32 coupling;
+	spcm_dwGetParam_i32(
+		this->pCardHandle,
+		trigChannelReg,
+		&coupling
+	);
+	this->checkError();
+	return coupling;
+}
+
+void AWG::setTrigLvl(int channel, int level) {
+	/**
+	 * set trigger level.
+	 * 
+	 * @param channel trigger channel
+	 * @param level -10000mV to 10000mV
+	 */
+	if (!this->isOpen()) { return; }
+	if (level < -10000 or level > 10000) {
+		std::cout << "invalid trigger level: " << level << std::endl;
+		return;
+	}
+	auto trigChannelReg = channel ?
+		SPC_TRIG_EXT1_LEVEL0 : SPC_TRIG_EXT0_LEVEL0;
+	spcm_dwSetParam_i64(
+		this->pCardHandle,
+		trigChannelReg,
+		level
+	);
+	this->checkError();
+}
+
+int AWG::getTrigLvl(int channel) {
+	if (!this->isOpen()) { return 0; }
+	auto trigChannelReg = channel ?
+		SPC_TRIG_EXT1_LEVEL0 : SPC_TRIG_EXT0_LEVEL0;
+	int32 level;
+	spcm_dwGetParam_i32(
+		this->pCardHandle,
+		trigChannelReg,
+		&level
+	);
+	this->checkError();
+	return level;
+}
+
+void AWG::setTrigRearmLvl(int channel, int level) {
+	/**
+	 * sets rearm trigger level.
+	 * 
+	 * @param channel trigger channel
+	 * @param level -10000mV to +10000mV
+	 */
+	if (!this->isOpen()) { return; }
+	auto trigChannelReg = channel ?
+		SPC_TRIG_EXT1_LEVEL1 : SPC_TRIG_EXT0_LEVEL1;
+	spcm_dwSetParam_i64(
+		this->pCardHandle,
+		trigChannelReg,
+		level
+	);
+	this->checkError();
+}
+
+int64 AWG::getTrigRearmLvl(int channel) {
+	if (!this->isOpen()) { return 0; }
+	auto trigChannelReg = channel ?
+		SPC_TRIG_EXT1_LEVEL1 : SPC_TRIG_EXT0_LEVEL1;
+	int64 level;
+	spcm_dwGetParam_i64(
+		this->pCardHandle,
+		trigChannelReg,
+		&level
+	);
+	return level;
+}
+
+//void AWG::setReplayMode(REPLAY_MODE mode) {
+//	/**
+//	 * set the data replay mode.
+//	 * 
+//	 * a macro for sequence replay mode is setup in
+//	 * initReplayModeSeq(), if you wish to use other modes, you must
+//	 * consult the manual for mode specific settings.
+//	 * 
+//	 * @param mode SINGLE, MULTI, GATE, SINGLERESTART, SEQUENCE,
+//	 * FIFO_{SINGLE, MULTI, GATE}.
+//	 * 
+//	 */
+//	if (!this->isOpen()) { return; }
+//	spcm_dwSetParam_i32(
+//		this->pCardHandle,
+//		SPC_CARDMODE,
+//		mode
+//	);
+//	this->checkError();
+//}
+//
+//void AWG::setMemSize(int64 sampleSize) {
+//	/**
+//	 * set memory size in samples in SINGLE, SINGLE_RESTART,
+//	 * MULTI, and GATE mode.
+//	 * Please consult the manual for # of channel dependent
+//	 * minimum/maximum sample size considerations.
+//	 * 
+//	 * @param sampleSize size of sample
+//	 *
+//	 */
+//	if (!this->isOpen()) { return; }
+//	if (sampleSize < 0 or sampleSize > 2e9) {
+//		std::cout << "invalid sampleSize: " << sampleSize << std::endl;
+//		return;
+//	}
+//	spcm_dwSetParam_i64(
+//		this->pCardHandle,
+//		SPC_MEMSIZE,
+//		sampleSize
+//	);
+//	this->checkError();
+//}
+//
+//int64 AWG::getMemsize() {
+//	int64 ms;
+//	spcm_dwGetParam_i64(
+//		this->pCardHandle,
+//		SPC_MEMSIZE,
+//		&ms
+//	);
+//	this->checkError();
+//	return ms;
+//}
+//
+//void AWG::setLoop(int nLoop) {
+//	/**
+//	 * set number of replay loops in SINGLE, SINGLE_RESTART,
+//	 * MULTI, and GATE mode.
+//	 * 
+//	 * @param nLoop
+//	 */
+//	if (!this->isOpen()) { return; }
+//	if (nLoop < 0) {
+//		std::cout << "invalid number of loop: " << nLoop << std::endl;
+//		return;
+//	}
+//	spcm_dwSetParam_i32(
+//		this->pCardHandle,
+//		SPC_LOOPS,
+//		nLoop
+//	);
+//}
+//
+//int64 AWG::getLoop() {
+//	if (!this->isOpen()) { return -1; }
+//	int64 nl;
+//	spcm_dwGetParam_i64(
+//		this->pCardHandle,
+//		SPC_LOOPS,
+//		&nl
+//	);
+//	return nl;
+//}
+
+void AWG::initReplayModeSeq(int nSeg) {
+	/**
+	 * initialize sequence replay mode.
+	 * 
+	 * @param nSeg number of segments memory is divided into
+	 */
+	if (!this->isOpen()) { return; }
+	if (nSeg % 2 != 0) {
+		std::cout << "invalid number of segments for SEQUENCE mode: "
+			<< nSeg << std::endl;
+		return;
+	}
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_CARDMODE,
+		int32(REPLAY_MODE::SEQUENCE)
+	);
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_SEQMODE_MAXSEGMENTS,
+		nSeg
+	);
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_SEQMODE_STARTSTEP,
+		0
+	);
+	this->checkError();
+}
+
+void AWG::setSeqModeStep(
+	uint64 step,
+	uint64 segment,
+	uint64 nextStep,
+	uint64 nLoop,
+	SEQ_LOOPCONDITION condition) {
+	/**
+	 * configure a step in sequence replay mode.
+	 * 
+	 * @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 condition end loop condition
+	 */
+	if (!this->isOpen()) { return; }
+	int64 mask = 
+		(uint64(condition) << 32)
+		| (nLoop << 32)
+		| (nextStep << 16)
+		| segment;
+	spcm_dwSetParam_i64(
+		this->pCardHandle,
+		SPC_SEQMODE_STEPMEM0 + step,
+		mask
+	);
+}
+
+void AWG::writeSeqModeSegment(
+	void* pDataBuffer,
+	int size,
+	int segment) {
+	/**
+	 * write buffered data into a memory segment in sequence replay mode.
+	 * 
+	 * @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
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_SEQMODE_WRITESEGMENT,
+		segment
+	);
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_SEQMODE_SEGMENTSIZE,
+		size
+	);
+	this->prepDataTransfer(pDataBuffer, size);
+	this->startDataTransfer();
+	this->checkError();
+}
+
+void AWG::prepDataTransfer(
+	void* dataBuffer,
+	uint64 bufferLen,
+	BUFFER_TYPE bufType,
+	TRANSFER_DIR dir,
+	uint32 notifySize,
+	uint64 brdMemOffs
+) {
+	/**
+	 * prepares the board for data transfer.
+	 * 
+	 * @param dataBuffer pointer to the data buffer
+	 * @param bufferLen length of data buffer, bytes
+	 * @param bufType buffer type, use only DATA for replay
+	 * @param dir direction of data transfer
+	 * @param notifySize number of bytes after which an event is sent
+	 * @param brdMemOffs offset for transfer in board memory
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwDefTransfer_i64(
+		this->pCardHandle,
+		int32(bufType),
+		int32(dir),
+		notifySize,
+		dataBuffer,
+		brdMemOffs,
+		bufferLen
+	);
+	this->checkError();
+}
+
+void AWG::startDataTransfer() {
+	/**
+	 * starts data transfer for a defined buffer.
+	 *
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_M2CMD,
+		M2CMD_DATA_STARTDMA
+	);
+	this->checkError();
+}
+
+void AWG::waitDataTransfer() {
+	/**
+	 * wait for data transfer to complete, blocks, 
+	 * timeout is considered.
+	 * 
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_M2CMD,
+		M2CMD_DATA_WAITDMA
+	);
+	this->checkError();
+}
+
+void AWG::stopDataTransfer() {
+	/**
+	 * stops a running data transfer.
+	 * 
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_M2CMD,
+		M2CMD_DATA_STOPDMA
+	);
+	this->checkError();
+}
+
+void AWG::setClockMode(CLOCK_MODE cm) {
+	/**
+	 * set the clock mode.
+	 * 
+	 * @param cm INTPLL or EXTREFCLK
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_CLOCKMODE,
+		int32(cm)
+	);
+	this->checkError();
+}
+
+int32 AWG::getClockMode() {
+	if (!this->isOpen()) { return -1; }
+	int32 cm;
+	spcm_dwGetParam_i32(
+		this->pCardHandle,
+		SPC_CLOCKMODE,
+		&cm
+	);
+	this->checkError();
+	return cm;
+}
+
+void AWG::setRefClkFreq(int64 frequency) {
+	/**
+	 * if using EXTREFCLK mode, set the external clock frequency.
+	 * 
+	 * @param frequency Hz
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i64(
+		this->pCardHandle,
+		SPC_REFERENCECLOCK,
+		frequency
+	);
+	this->checkError();
+}
+
+void AWG::setClockOut(bool enable) {
+	/**
+	 * enable/disable clock output.
+	 * 
+	 * @param enable true/false
+	 */
+	if (!this->isOpen()) { return; }
+	spcm_dwSetParam_i32(
+		this->pCardHandle,
+		SPC_CLOCKOUT,
+		enable
+	);
+	this->checkError();
+}
+
+int64 AWG::getClockOutFreq() {
+	/**
+	 * Read out frequency of internally synthesized clock.
+	 * 
+	 * @return frequency (Hz)
+	 */
+	if (!this->isOpen()) { return -1; }
+	int64 freq;
+	spcm_dwGetParam_i64(
+		this->pCardHandle,
+		SPC_CLOCKOUTFREQUENCY,
+		&freq
+	);
+	this->checkError();
+	return freq;
+}
diff --git a/Cpp/lib/AWG.h b/Cpp/lib/AWG.h
index 06082170659ec4b8c7e7bc1049a924904c087e93..af28ce0b815b4bc921fe4550ae4b257d1ac3dab3 100644
--- a/Cpp/lib/AWG.h
+++ b/Cpp/lib/AWG.h
@@ -1,19 +1,194 @@
 #pragma once
-#include "dlltyp.h"
-#include "regs.h"
-#include "spcerr.h"
-#include "spcm_drv.h"
+#include "driver_header/dlltyp.h"
+#include "driver_header/regs.h"
+#include "driver_header/spcerr.h"
+#include "driver_header/spcm_drv.h"
+#include <string>
+#include <set>
+#include <map>
+
+class AWG {
+	/**
+	 * Class for handling AWG M4i.6622-x8 .
+	 * Manual can be found at
+	 * https://spectrum-instrumentation.com/products/details/M4i6622-x8.php
+	 */
+
+	 // collection of special constants to help with setting options
+	const enum class CHANNEL_STOPLVL : int32 {
+		ZERO	 = SPCM_STOPLVL_ZERO,
+		LOW		 = SPCM_STOPLVL_LOW,
+		HIGH	 = SPCM_STOPLVL_HIGH,
+		HOLDLAST = SPCM_STOPLVL_HOLDLAST,
+	};
+	const enum class REPLAY_MODE : int32 {
+		SINGLE		  = SPC_REP_STD_SINGLE,
+		MULTI		  = SPC_REP_STD_MULTI,
+		GATE		  = SPC_REP_STD_GATE,
+		SINGLERESTART = SPC_REP_STD_SINGLERESTART,
+		SEQUENCE	  = SPC_REP_STD_SEQUENCE,
+		FIFO_SINGLE	  = SPC_REP_FIFO_SINGLE,
+		FIFO_MULTI	  = SPC_REP_FIFO_MULTI,
+		FIFO_GATE	  = SPC_REP_FIFO_GATE,
+	};
+	const enum class BUFFER_TYPE : int32 {
+		DATA	  = SPCM_BUF_DATA,
+		ABA		  = SPCM_BUF_ABA,
+		TIMESTAMP = SPCM_BUF_TIMESTAMP,
+	};
+	const enum class TRANSFER_DIR : int32 {
+		PCTOCARD  = SPCM_DIR_PCTOCARD,
+		CARDTOPC  = SPCM_DIR_CARDTOPC,
+		CARDTOGPU = SPCM_DIR_CARDTOGPU,
+		GPUTOCARD = SPCM_DIR_GPUTOCARD,
+	};
+	const enum class CLOCK_MODE : int32 {
+		INTPLL	  = SPC_CM_INTPLL,
+		EXTREFCLK = SPC_CM_EXTREFCLOCK,
+	};
+	const enum class TRIGGER_MASK : int32 {
+		NONE	 = SPC_TMASK_NONE,
+		SOFTWARE = SPC_TMASK_SOFTWARE,
+		EXT0	 = SPC_TMASK_EXT0,
+		EXT1	 = SPC_TMASK_EXT1,
+	};
+	const enum class TRIGGER_MODE : int32 {
+		NONE	   = SPC_TM_NONE,
+		POS		   = SPC_TM_POS,
+		NEG		   = SPC_TM_NEG,
+		POS_REARM  = SPC_TM_POS | SPC_TM_REARM,
+		NEG_REARM  = SPC_TM_NEG | SPC_TM_REARM,
+		BOTH	   = SPC_TM_BOTH,
+		HIGH	   = SPC_TM_HIGH,
+		LOW		   = SPC_TM_LOW,
+		WINENTER   = SPC_TM_WINENTER,
+		WINLEAVE   = SPC_TM_WINLEAVE,
+		INWIN	   = SPC_TM_INWIN,
+		OUTSIDEWIN = SPC_TM_OUTSIDEWIN,
+	};
+	const enum class SEQ_LOOPCONDITION : int64 {
+		ALWAYS = SPCSEQ_ENDLOOPALWAYS,
+		ONTRIG = SPCSEQ_ENDLOOPONTRIG,
+		END	   = SPCSEQ_END,
+	};
+
+	// collection of card status for printouts
+	const std::map<int, std::string> STATUS_NAMES = {
+		{M2STAT_CARD_TRIGGER,	 "card received trigger"},
+		{M2STAT_CARD_READY,		 "card ready"},
+		{M2STAT_DATA_BLOCKREADY, "data block ready"},
+		{M2STAT_DATA_END,		 "data transfer ended"},
+		{M2STAT_DATA_OVERRUN,	 "data transfer overrun"},
+		{M2STAT_DATA_ERROR,		 "data transfer error"},
+	};
 
-class AWG 
-{
 private:
-	typedef struct // dirty struct containing much card info
-	{
-		drv_handle cardHandle;
+	// card information
+	drv_handle	pCardHandle;
+	int32	    cardIdx;
+	int32	    serialNumber;
+	int64	    instMemSize;
+	int32	    bytesPerSample;
+	int64	    maxSampleRate;
 
-	} CARDINFO;
+	// setting information
+	std::set<int> activeChannels;
+	void		  checkError();
+	void*		  getPageAlignedMem(uint64 memSize);
+	void		  freePageAlignedMem(void* pMem, uint64 memSize);
 
 public:
-	AWG(int cardID) noexcept;
+	// functions
+	AWG() noexcept;
+	~AWG();
+
+	// basic card setting
+	void  open(int openIndex);
+	bool  isOpen();
+	void  close();
+	void  reset();
+	int   getCardIdx();
+	int   getSerialNumber();
+	int64 getInstMemSize();
+	int   getBytesPerSample();
+	int64 getMaxSampleRate();
+	void  setSampleRate(int64 sampleRate);
+	int64 getSampleRate();
+
+	// channel output control
+	void setActiveChannels(std::set<int> channels);
+	void setChannelAmp(int ch, int amp);
+	void setChannelStopLvl(int ch, CHANNEL_STOPLVL stopLvl);
+	void toggleChannelOutput(int ch, bool enable);
+	void setChannel(int ch, int amp, CHANNEL_STOPLVL stopLvl, bool enable);
+	int	 getChannelCount();
+	std::set<int> getChannelActivated();
+	void setChannelDiffMode(int chPair, bool enable);
+	void setChannelDoubleMode(int chPair, bool enable);
+
+	// card status control
+	void writeSetup();
+	void cardRun();
+	void cardStop();
+	void waitReady();
+	void setTimeOut(int time); // ms
+	int  getTimeOut();
+	void printCardStatus();
+
+	// card trigger control
+	void   toggleTrigger(bool enable);
+	void   forceTrigger();
+	void   waitTrigger();
+	void   setTrigMaskOr(std::initializer_list<TRIGGER_MASK> trigMasks);
+	void   setTrigMaskAnd(std::initializer_list<TRIGGER_MASK> trigMasks);
+	void   setTrigMode(int trigChannel, TRIGGER_MODE trigMode);
+	void   setTrigTerm(int term);
+	int    getTrigTerm();
+	void   setTrigCoupling(int channel, int coupling);
+	int    getTrigCoupling(int channel);
+	void   setTrigLvl(int channel, int level);
+	int    getTrigLvl(int channel);
+	void   setTrigRearmLvl(int channel, int level);
+	int64  getTrigRearmLvl(int channel);
+
+	// replay mode control
+	//void  setReplayMode(REPLAY_MODE mode);
+	//void  setMemSize(int64 sampleSize);
+	//int64 getMemsize();
+	//void  setLoop(int nLoop);
+	//int64 getLoop();
+	void initReplayModeSeq(int nSeg);
+	void setSeqModeStep(
+		uint64 step,
+		uint64 segment,
+		uint64 nextStep,
+		uint64 nLoop,
+		SEQ_LOOPCONDITION condition
+	);
+	void writeSeqModeSegment(
+		void* pDataBuffer, 
+		int size,
+		int segment
+	);
+
+	// data transfer
+	void prepDataTransfer(
+		void* dataBuffer,
+		uint64 bufferLen,
+		BUFFER_TYPE bufType = BUFFER_TYPE::DATA,
+		TRANSFER_DIR dir = TRANSFER_DIR::PCTOCARD,
+		uint32 notifySize = 0,
+		uint64 brdMemOffs = 0
+	);
+	void startDataTransfer();
+	void waitDataTransfer();
+	void stopDataTransfer();
+
+	// clock control
+	void  setClockMode(CLOCK_MODE cm);
+	int32 getClockMode();
+	void  setRefClkFreq(int64 frequency);
+	void  setClockOut(bool enable);
+	int64 getClockOutFreq();
 };
 
diff --git a/Cpp/lib/driver_header/SpcStdNT.lib b/Cpp/lib/driver_header/SpcStdNT.lib
new file mode 100644
index 0000000000000000000000000000000000000000..50f6693e5246032570317a8b12db430d42499262
Binary files /dev/null and b/Cpp/lib/driver_header/SpcStdNT.lib differ
diff --git a/Cpp/lib/dlltyp.h b/Cpp/lib/driver_header/dlltyp.h
similarity index 100%
rename from Cpp/lib/dlltyp.h
rename to Cpp/lib/driver_header/dlltyp.h
diff --git a/Cpp/lib/errors.h b/Cpp/lib/driver_header/errors.h
similarity index 100%
rename from Cpp/lib/errors.h
rename to Cpp/lib/driver_header/errors.h
diff --git a/Cpp/lib/driver_header/readme.txt b/Cpp/lib/driver_header/readme.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0f2ebceb1bf87aa82ab71791e7b04b11e906c07d
--- /dev/null
+++ b/Cpp/lib/driver_header/readme.txt
@@ -0,0 +1,71 @@
+**************************************************************************
+c_header directory                                       (c) Spectrum GmbH
+**************************************************************************
+
+The directory contains all header and library files for all Spectrum
+drivers for ISA, PCI, PCI-X, PCIe, cPCI and PXI cards.
+
+**************************************************************************
+
+
+
+Common header files used by all drivers
+---------------------------------------
+
+dlltyp.h: definitions common for all Spectrum drivers and card types. This
+		header tries to examine the type of compiler and then defines common
+		data types that have the same length under all compilers and all
+		operating systems.
+
+regs.h: software register and constants definition for all Spectrum
+		drivers.
+
+spcerr.h: error codes of all Spectrum drivers. Until may 2004 this file was
+		errors.h. Name has been changed because errors.h has been already in
+		use by windows.
+
+
+
+Library and Header files of driver for ISA/PCI/MI/MC/MX cards
+-------------------------------------------------------------
+
+spcioctl.inc:	linux include file to access driver functions via kernel
+		calls. Is needed by all linux based programs that access one of the
+		ISA/PCI/MI/MC/MX Spectrum cards
+
+errors.h: former error file. Thsi file is just included because of
+		compatibility reasons with old projects. Please use spcerr.h
+
+spectrum.h: header file that contains all the prototypes of the driver
+		functions
+
+spectrum.lib:	library file for Microsoft Visual C++ for the spectrum
+		driver DLL. Calling type is c-call.
+
+SpcStdNT.lib: library file for other compilers for the spectrum
+		driver DLL. Calling type is stdcall.
+
+spclib_bcc.lib: library for Borland C++ Builder for the spectrum
+		driver DLL.
+
+
+
+Library and Header files of driver for SPCM driver based cards
+-------------------------------------------------------------
+
+spcm_drv.h: header file that contains all the prototypes of the
+		driver functions of the spcm driver
+
+spcm_win32_msvcpp.lib: library file for the Microsoft Visual C++
+		compiler. Calling type is stdcall.
+
+spcm_win32_bcppb.lib: library file for the Borland C++ Builder
+		compiler
+
+spcm_win32_cvi.lib: library file for National Instruments
+		LabWindows/CVI compiler
+
+spectrum_comp.lib: library file of the compatibility DLL that
+		simulates MI cards when findng M2i cards. Please include
+		this file instead of spectrum.lib for all projects that
+		should use M2i cards with the MI software interface
diff --git a/Cpp/lib/regs.h b/Cpp/lib/driver_header/regs.h
similarity index 100%
rename from Cpp/lib/regs.h
rename to Cpp/lib/driver_header/regs.h
diff --git a/Cpp/lib/spcerr.h b/Cpp/lib/driver_header/spcerr.h
similarity index 100%
rename from Cpp/lib/spcerr.h
rename to Cpp/lib/driver_header/spcerr.h
diff --git a/Cpp/lib/driver_header/spcioctl.inc b/Cpp/lib/driver_header/spcioctl.inc
new file mode 100644
index 0000000000000000000000000000000000000000..cf7db32c93114894a7ce83b151179d60dfe3248f
--- /dev/null
+++ b/Cpp/lib/driver_header/spcioctl.inc
@@ -0,0 +1,93 @@
+// ****************************************************************************
+// spcioctl.inc
+// ****************************************************************************
+// include source code for easy access of the ioctl and data transfer commands
+// of the spectrum driver.
+// ****************************************************************************
+
+
+
+// ----- ioctl_GetParam -----------------------------------
+int16 SpcGetParam (int hDrv, int32 lReg, int32 *plValue)
+	{
+	int32 lData[2];
+	int16 nRet;
+
+	lData[0] = lReg;
+	nRet = ioctl (hDrv, GETPARAM, lData);
+	*plValue = lData[1];
+
+	return nRet;
+	}
+
+// ----- ioctl_SetParam -----------------------------------
+int16 SpcSetParam (int hDrv, int32 lReg, int32 lValue) 
+	{
+	int32 lData[2];
+	
+	lData[0] = lReg;
+	lData[1] = lValue;
+
+	return ioctl(hDrv, SETPARAM, lData);
+	}
+
+
+
+// ----- ioctl_GetAdr -----------------------------------
+int16 SpcGetAdr (int hDrv, int32 lReg, void** ppvAdr)
+	{
+	int16 nRet;
+	_SETGETADR stSetGetAdr;
+
+	stSetGetAdr.lReg = lReg;
+	nRet = ioctl (hDrv, GETADR, &stSetGetAdr);
+	(*ppvAdr) = stSetGetAdr.pvAdr;
+
+	return nRet;
+	}
+
+// ----- ioctl_SetAdr -----------------------------------
+int16 SpcSetAdr (int hDrv, int32 lReg, void* pvAdr)
+	{
+	int16 nRet;
+	_SETGETADR stSetGetAdr;
+
+	stSetGetAdr.lReg = lReg;
+	stSetGetAdr.pvAdr = pvAdr;
+	nRet = ioctl (hDrv, SETADR, &stSetGetAdr);
+
+	return nRet;
+	}
+
+
+
+// ----- ioctl_GetData ------------------------------------
+int32 SpcGetData (int hDrv, int32 lCh, int32 lStart, int32 lLen, int16 nBytesPerSample, dataptr pvData)
+	{
+	int32 lRet;
+	int32 lData[1];
+	lData[0] = lCh;
+
+	ioctl (hDrv, SETCH, lData);
+
+ 	lseek (hDrv, lStart * nBytesPerSample, SEEK_SET);
+	lRet = read (hDrv, pvData, nBytesPerSample * lLen);
+
+	return lRet;
+	}
+
+// ----- ioctl_SetData ------------------------------------
+int32 SpcSetData (int hDrv, int32 lCh, int32 lStart, int32 lLen, int16 nBytesPerSample, dataptr pvData)
+	{
+	int32 lRet;
+	int32 lData[1];
+	
+	lData[0] = lCh;
+
+	ioctl (hDrv, SETCH, lData);
+
+	lseek (hDrv, lStart * nBytesPerSample, SEEK_SET);
+	lRet = write (hDrv, pvData, nBytesPerSample * lLen);
+
+	return lRet;
+	}
diff --git a/Cpp/lib/driver_header/spclib_bcc.lib b/Cpp/lib/driver_header/spclib_bcc.lib
new file mode 100644
index 0000000000000000000000000000000000000000..fe98a9d8b0a8f32f9a7d839251502e2fb362778a
Binary files /dev/null and b/Cpp/lib/driver_header/spclib_bcc.lib differ
diff --git a/Cpp/lib/spcm_drv.h b/Cpp/lib/driver_header/spcm_drv.h
similarity index 100%
rename from Cpp/lib/spcm_drv.h
rename to Cpp/lib/driver_header/spcm_drv.h
diff --git a/Cpp/lib/driver_header/spcm_win32_bcppb.lib b/Cpp/lib/driver_header/spcm_win32_bcppb.lib
new file mode 100644
index 0000000000000000000000000000000000000000..2f022cdce6c5c1bb719ffbe9b8aca3821eba47f1
Binary files /dev/null and b/Cpp/lib/driver_header/spcm_win32_bcppb.lib differ
diff --git a/Cpp/lib/driver_header/spcm_win32_cvi.lib b/Cpp/lib/driver_header/spcm_win32_cvi.lib
new file mode 100644
index 0000000000000000000000000000000000000000..db3b2cd1fdaba87b14e2229f07063d7f8f34600b
Binary files /dev/null and b/Cpp/lib/driver_header/spcm_win32_cvi.lib differ
diff --git a/Cpp/lib/driver_header/spcm_win32_msvcpp.lib b/Cpp/lib/driver_header/spcm_win32_msvcpp.lib
new file mode 100644
index 0000000000000000000000000000000000000000..33b1f5db3cf4072985782304eaf0e473598e706a
Binary files /dev/null and b/Cpp/lib/driver_header/spcm_win32_msvcpp.lib differ
diff --git a/Cpp/lib/driver_header/spcm_win64_msvcpp.lib b/Cpp/lib/driver_header/spcm_win64_msvcpp.lib
new file mode 100644
index 0000000000000000000000000000000000000000..07dee37fde851192cad0f13cb88f61af9a7d26bd
Binary files /dev/null and b/Cpp/lib/driver_header/spcm_win64_msvcpp.lib differ
diff --git a/Cpp/lib/driver_header/spectrum.h b/Cpp/lib/driver_header/spectrum.h
new file mode 100644
index 0000000000000000000000000000000000000000..77ca4fb47d8439b1b7707cd8010388c578b66b90
--- /dev/null
+++ b/Cpp/lib/driver_header/spectrum.h
@@ -0,0 +1,11 @@
+HEAD  SpcInitPCIBoards  (int16 *pnCount, int16 *pnPCIVersion);
+HEAD  SpcInitBoard      (int16 nNr, int16 nTyp);
+HEAD  SpcSetParam       (int16 nNr, int32 lReg, int32 lValue);
+HEAD  SpcGetParam       (int16 nNr, int32 lReg, int32 *plValue);
+HEAD  SpcGetData        (int16 nNr, int16 nCh, int32 lStart, int32 lLen, dataptr pvData);
+HEAD  SpcSetData        (int16 nNr, int16 nCh, int32 lStart, int32 lLen, dataptr pvData);
+HEAD  SpcGetVersionInfo (char *pszBuffer, int nBufferLen);
+
+// these functions are only needed under 64 bit Linux to set FIFO adresses
+HEAD  SpcSetAdr        (int16 nNr, int32 lReg, void*  pvAdr);
+HEAD  SpcGetAdr        (int16 nNr, int32 lReg, void** ppvAdr);
diff --git a/Cpp/lib/driver_header/spectrum.lib b/Cpp/lib/driver_header/spectrum.lib
new file mode 100644
index 0000000000000000000000000000000000000000..ac4873d485442d2a30c930fb1f86c29d5eae0528
Binary files /dev/null and b/Cpp/lib/driver_header/spectrum.lib differ
diff --git a/Cpp/lib/driver_header/spectrum_comp.lib b/Cpp/lib/driver_header/spectrum_comp.lib
new file mode 100644
index 0000000000000000000000000000000000000000..881e1c83ab1b5879c5d1de215b399b95a46c322b
Binary files /dev/null and b/Cpp/lib/driver_header/spectrum_comp.lib differ
diff --git a/Cpp/run.cpp b/Cpp/run.cpp
index a048923511b6c8b4ea1adeaad485c69ccf93d3ce..1c912f7d4be16b094986425b5d59b1ecaeaf536b 100644
--- a/Cpp/run.cpp
+++ b/Cpp/run.cpp
@@ -2,10 +2,13 @@
 //
 
 #include <iostream>
+#include <set>
+#include "lib/AWG.h"
 
 int main()
 {
-    std::cout << "Hello World!\n";
+	auto b = 10;
+	std::cout << b << std::endl;
 }
 
 // Run program: Ctrl + F5 or Debug > Start Without Debugging menu