diff --git a/tests/py/AnalogIO_AnalogDiscovery2_Power.py b/tests/py/AnalogIO_AnalogDiscovery2_Power.py
new file mode 100644
index 0000000000000000000000000000000000000000..420e88483dcbb94b2f4d48bcebc36c987699d50e
--- /dev/null
+++ b/tests/py/AnalogIO_AnalogDiscovery2_Power.py
@@ -0,0 +1,76 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+IsEnabled = c_int()
+usbVoltage = c_double()
+usbCurrent = c_double()
+auxVoltage = c_double()
+auxCurrent = c_double()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+# set up analog IO channel nodes
+# enable positive supply
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(0), c_double(True)) 
+# set voltage to 5 V
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(1), c_double(5.0)) 
+# enable negative supply
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(1), c_int(0), c_double(True)) 
+# set voltage to -5 V
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(1), c_int(1), c_double(-5.0)) 
+# master enable
+dwf.FDwfAnalogIOEnableSet(hdwf, c_int(True))
+
+for i in range(1, 11):
+    # wait 1 second between readings
+    time.sleep(1)
+    # fetch analogIO status from device
+    if dwf.FDwfAnalogIOStatus(hdwf) == 0:
+        break
+
+    #supply monitor
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(2), c_int(0), byref(usbVoltage))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(2), c_int(1), byref(usbCurrent))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(3), c_int(0), byref(auxVoltage))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(3), c_int(1), byref(auxCurrent))
+    print("USB: " + str(round(usbVoltage.value,3)) + "V\t" + str(round(usbCurrent.value,3)) + "A")
+    print("AUX: " + str(round(auxVoltage.value,3)) + "V\t" + str(round(auxCurrent.value,3)) + "A")
+
+    # in case of over-current condition the supplies are disabled
+    dwf.FDwfAnalogIOEnableStatus(hdwf, byref(IsEnabled))
+    if not IsEnabled:
+        #re-enable supplies
+        print("Power supplies stopped. Restarting...")
+        dwf.FDwfAnalogIOEnableSet(hdwf, c_int(False)) 
+        dwf.FDwfAnalogIOEnableSet(hdwf, c_int(True))
+
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/AnalogIO_AnalogDiscovery2_SystemMonitor.py b/tests/py/AnalogIO_AnalogDiscovery2_SystemMonitor.py
new file mode 100644
index 0000000000000000000000000000000000000000..ae7a4b597b1bbf2a47763ccab63434912ac6daaa
--- /dev/null
+++ b/tests/py/AnalogIO_AnalogDiscovery2_SystemMonitor.py
@@ -0,0 +1,61 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+usbVoltage = c_double()
+usbCurrent = c_double()
+auxVoltage = c_double()
+auxCurrent = c_double()
+deviceTemperature = c_double()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+print("Device temperature and USB/AUX supply voltage and current")
+
+# 10 times, once per second
+for i in range(1, 11):
+    # wait between readings
+    time.sleep(1)
+    # fetch analog IO status from device
+    if dwf.FDwfAnalogIOStatus(hdwf) == 0 :
+        break;
+    # get system monitor readings
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(2), c_int(0), byref(usbVoltage))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(2), c_int(1), byref(usbCurrent))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(2), c_int(2), byref(deviceTemperature))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(3), c_int(0), byref(auxVoltage))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(3), c_int(1), byref(auxCurrent))
+    print("Temperature: " + str(deviceTemperature.value) + "*C")
+    print("USB:\t" + str(round(usbVoltage.value,3)) + "V\t" + str(round(usbCurrent.value,3)) + "A")
+    print("AUX:\t" + str(round(auxVoltage.value,3)) + "V\t" + str(round(auxCurrent.value,3)) + "A")
+    
+#close the device
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/AnalogIO_AnalogDiscovery_Power.py b/tests/py/AnalogIO_AnalogDiscovery_Power.py
new file mode 100644
index 0000000000000000000000000000000000000000..9c52a8cf82a4422e3f142b6224febcbd8285abac
--- /dev/null
+++ b/tests/py/AnalogIO_AnalogDiscovery_Power.py
@@ -0,0 +1,75 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+IsEnabled = c_int()
+supplyVoltage = c_double()
+supplyCurrent = c_double()
+supplyPower = c_double()
+supplyLoadPercentage = c_double()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+    
+print("Preparing to read sample...")
+
+#set up analog IO channel nodes
+# enable positive supply
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, 0, 0, 1) 
+# enable negative supply
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, 1, 0, 1) 
+# master enable
+dwf.FDwfAnalogIOEnableSet(hdwf, True) 
+
+for i in range(1, 61):
+  #wait 1 second between readings
+  time.sleep(1)
+  #fetch analogIO status from device
+  dwf.FDwfAnalogIOStatus(hdwf)
+
+  #supply monitor
+  dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(3), c_int(0), byref(supplyVoltage))
+  dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(3), c_int(1), byref(supplyCurrent))
+  supplyPower.value = supplyVoltage.value * supplyCurrent.value
+  print("Total supply power: " + str(supplyPower.value) + "W")
+
+  supplyLoadPercentage.value = 100 * (supplyCurrent.value / 0.2)
+  print("Load: " + str(supplyLoadPercentage.value) + "%")
+
+  # in case of over-current condition the supplies are disabled
+  dwf.FDwfAnalogIOEnableStatus(hdwf, byref(IsEnabled))
+  if not IsEnabled:
+    #re-enable supplies
+    dwf.FDwfAnalogIOEnableSet(hdwf, c_int(0)) 
+    dwf.FDwfAnalogIOEnableSet(hdwf, c_int(1))
+
+#close the device
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/AnalogIO_AnalogDiscovery_SystemMonitor.py b/tests/py/AnalogIO_AnalogDiscovery_SystemMonitor.py
new file mode 100644
index 0000000000000000000000000000000000000000..8bfa529e0b7c46668bda1da9b8efc6864ef7a080
--- /dev/null
+++ b/tests/py/AnalogIO_AnalogDiscovery_SystemMonitor.py
@@ -0,0 +1,53 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+deviceVoltage = c_double()
+deviceCurrent = c_double()
+deviceTemperature = c_double()
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+print("Device USB supply voltage, current and device temperature:")
+#monitor voltage, current, temperature
+#60 times, once per second
+for i in range(1, 61):
+    # wait between readings; the update rate is approximately 1Hz
+    time.sleep(1)
+    # fetch analog IO status from device
+    dwf.FDwfAnalogIOStatus(hdwf)
+    # get system monitor readings
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(2), c_int(0), byref(deviceVoltage))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(2), c_int(1), byref(deviceCurrent))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(2), c_int(2), byref(deviceTemperature))
+    print(str(deviceVoltage.value) + " V\t" + str(deviceCurrent.value) + " A\t " + str(deviceTemperature.value) + "degC")
+    
+#close the device
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/AnalogIO_DigitalDiscovery.py b/tests/py/AnalogIO_DigitalDiscovery.py
new file mode 100644
index 0000000000000000000000000000000000000000..5e8eb1c2dde8819ecc216cd4e92549ac82800617
--- /dev/null
+++ b/tests/py/AnalogIO_DigitalDiscovery.py
@@ -0,0 +1,84 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+IsEnabled = c_int()
+voltage = c_double()
+current = c_double()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+# set digital voltage between 1.2 and 3.3V
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(0), c_double(1.8))
+# enable VIO output
+dwf.FDwfAnalogIOEnableSet(hdwf, c_int(True))
+
+# configure week pull for DIN lines, 0.0 low, 0.5 middle, 1 high
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(1), c_double(0.5)) 
+
+# pull enable for DIO 39 to 24, bit 15 to 0
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(2), c_double(0x0081)) # DIO7 and DIO0
+# pull up/down for DIO
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(3), c_double(0x0080)) # DIO7 pull up and DIO0 pull down
+
+# drive strength for DIO lines: 0 (auto based on digital voltage), 2, 4, 6, 8, 12, 16 (mA)
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(4), c_double(8)) 
+# slew rate for DIO lines: 0 quietio, 1 slow, 2 fast
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(5), c_double(0)) 
+
+
+for i in range(1, 11):
+    #wait 1 second between readings
+    time.sleep(1)
+    #fetch analogIO status from device
+    if dwf.FDwfAnalogIOStatus(hdwf) == 0:
+        break
+
+    # USB monitor
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(2), c_int(0), byref(voltage))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(2), c_int(1), byref(current))
+    print("USB: " + str(round(voltage.value,3)) + "V\t" + str(round(current.value,3)) + "A")
+    
+    # VIO monitor
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(1), c_int(0), byref(voltage))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(1), c_int(1), byref(current))
+    print("VIO: " + str(round(voltage.value,3)) + "V\t" + str(round(current.value,3)) + "A")
+
+    # in case of over-current condition the supplies are disabled
+    dwf.FDwfAnalogIOEnableStatus(hdwf, byref(IsEnabled))
+    if not IsEnabled:
+        #re-enable supplies
+        print("Restart")
+        dwf.FDwfAnalogIOEnableSet(hdwf, c_int(False)) 
+        dwf.FDwfAnalogIOEnableSet(hdwf, c_int(True))
+
+#close the device
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/AnalogIO_ElectronicsExplorer.py b/tests/py/AnalogIO_ElectronicsExplorer.py
new file mode 100644
index 0000000000000000000000000000000000000000..9dad0d34762542a2cb6a597e1d35d30605d8c3b3
--- /dev/null
+++ b/tests/py/AnalogIO_ElectronicsExplorer.py
@@ -0,0 +1,108 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+voltage = c_double()
+current = c_double()
+vmtr1 = c_double()
+vmtr2 = c_double()
+vmtr3 = c_double()
+vmtr4 = c_double()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+# set up analog IO channel nodes
+
+# enable fixed supply supply
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(0), c_double(True)) 
+# set voltage 3.3V or 5V
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(1), c_double(3.3)) 
+
+# enable positive supply
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(1), c_int(0), c_double(True)) 
+# set voltage between 0 and 9V
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(1), c_int(1), c_double(6.0)) 
+# set current limitation 0 and 1.5A
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(1), c_int(2), c_double(0.5)) 
+
+# enable negative supply
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(2), c_int(0), c_double(True)) 
+# set voltage between 0 and -9V
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(2), c_int(1), c_double(-6.0)) 
+# set current limitation between 0 and -1.5A
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(2), c_int(2), c_double(-0.5))
+
+# enable voltage reference 1
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(3), c_int(0), c_double(True)) 
+# set voltage between -10 and 10V
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(3), c_int(1), c_double(7.0)) 
+
+# enable voltage reference 2
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(4), c_int(0), c_double(True)) 
+# set voltage between -10 and 10V
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(4), c_int(1), c_double(-7.0)) 
+
+# master enable
+dwf.FDwfAnalogIOEnableSet(hdwf, c_int(True))
+
+for i in range(1, 11):
+    # wait between readings
+    time.sleep(1)
+    # fetch analogIO status from device
+    if dwf.FDwfAnalogIOStatus(hdwf) == 0:
+        break
+
+    # fixed supply supply readings
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(0), c_int(1), byref(voltage))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(0), c_int(2), byref(current))
+    print("VCC: " + str(round(voltage.value,3)) + "V\t" + str(round(current.value,3)) + "A")
+
+    # positive supply supply readings
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(1), c_int(1), byref(voltage))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(1), c_int(2), byref(current))
+    print("VP+: " + str(round(voltage.value,3)) + "V\t" + str(round(current.value,3)) + "A")
+
+    # negative supply supply readings
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(2), c_int(1), byref(voltage))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(2), c_int(2), byref(current))
+    print("VP-: " + str(round(voltage.value,3)) + "V\t" + str(round(current.value,3)) + "A")
+    
+    # voltmeter readings -15V..15V
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(5), c_int(0), byref(vmtr1, 0))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(6), c_int(0), byref(vmtr2, 1))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(7), c_int(0), byref(vmtr3, 2))
+    dwf.FDwfAnalogIOChannelNodeStatus(hdwf, c_int(8), c_int(0), byref(vmtr4, 3))
+    print("Vmtr1-4: " + str(round(vmtr1.value,3)) + "V\t"+ str(round(vmtr2.value,3)) + "V\t"+ str(round(vmtr3.value,3)) + "V\t"+ str(round(vmtr4.value,3)) + "V\t")
+
+
+# close the device
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/AnalogImpedance_Analyzer.py b/tests/py/AnalogImpedance_Analyzer.py
new file mode 100644
index 0000000000000000000000000000000000000000..bb85dc2cb4fa97b411e7dd8b186913fe0dc9b1da
--- /dev/null
+++ b/tests/py/AnalogImpedance_Analyzer.py
@@ -0,0 +1,104 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-28
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import sys
+import numpy
+import matplotlib.pyplot as plt
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+hdwf = c_int()
+szerr = create_string_buffer(512)
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+# this option will enable dynamic adjustment of analog out settings like: frequency, amplitude...
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(3)) 
+
+sts = c_byte()
+steps = 151
+start = 1e2
+stop = 1e6
+reference = 1e3
+
+print("Reference: "+str(reference)+" Ohm  Frequency: "+str(start)+" Hz ... "+str(stop/1e3)+" kHz for nanofarad capacitors")
+dwf.FDwfAnalogImpedanceReset(hdwf)
+dwf.FDwfAnalogImpedanceModeSet(hdwf, c_int(8)) # 0 = W1-C1-DUT-C2-R-GND, 1 = W1-C1-R-C2-DUT-GND, 8 = AD IA adapter
+dwf.FDwfAnalogImpedanceReferenceSet(hdwf, c_double(reference)) # reference resistor value in Ohms
+dwf.FDwfAnalogImpedanceFrequencySet(hdwf, c_double(start)) # frequency in Hertz
+dwf.FDwfAnalogImpedanceAmplitudeSet(hdwf, c_double(1)) # 1V amplitude = 2V peak2peak signal
+dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(1)) # start
+time.sleep(2)
+
+rgHz = [0.0]*steps
+rgRs = [0.0]*steps
+rgXs = [0.0]*steps
+for i in range(steps):
+    hz = stop * pow(10.0, 1.0*(1.0*i/(steps-1)-1)*math.log10(stop/start)) # exponential frequency steps
+    print("Step: "+str(i)+" "+str(hz)+"Hz")
+    rgHz[i] = hz
+    dwf.FDwfAnalogImpedanceFrequencySet(hdwf, c_double(hz)) # frequency in Hertz
+    # if settle time is required for the DUT, wait and restart the acquisition
+    # time.sleep(0.01) 
+    # dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(1))
+    while True:
+        if dwf.FDwfAnalogImpedanceStatus(hdwf, byref(sts)) == 0:
+            dwf.FDwfGetLastErrorMsg(szerr)
+            print(str(szerr.value))
+            quit()
+        if sts.value == 2:
+            break
+    resistance = c_double()
+    reactance = c_double()
+    dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceResistance, byref(resistance))
+    dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceReactance, byref(reactance))
+    rgRs[i] = abs(resistance.value) # absolute value for logarithmic plot
+    rgXs[i] = abs(reactance.value)
+    
+    for iCh in range(2):
+        warn = c_int()
+        dwf.FDwfAnalogImpedanceStatusWarning(hdwf, c_int(iCh), byref(warn))
+        if warn.value:
+            dOff = c_double()
+            dRng = c_double()
+            dwf.FDwfAnalogInChannelOffsetGet(hdwf, c_int(iCh), byref(dOff))
+            dwf.FDwfAnalogInChannelRangeGet(hdwf, c_int(iCh), byref(dRng))
+            if warn.value & 1:
+                print("Out of range on Channel "+str(iCh+1)+" <= "+str(dOff.value - dRng.value/2)+"V")
+            if warn.value & 2:
+                print("Out of range on Channel "+str(iCh+1)+" >= "+str(dOff.value + dRng.value/2)+"V")
+
+dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(0)) # stop
+dwf.FDwfDeviceClose(hdwf)
+
+plt.plot(rgHz, rgRs, rgHz, rgXs)
+ax = plt.gca()
+ax.set_xscale('log')
+ax.set_yscale('log')
+plt.show()
+
diff --git a/tests/py/AnalogImpedance_Compensation.py b/tests/py/AnalogImpedance_Compensation.py
new file mode 100644
index 0000000000000000000000000000000000000000..c25cd46ef723b19d24e23ab1dc2d98774abacbd7
--- /dev/null
+++ b/tests/py/AnalogImpedance_Compensation.py
@@ -0,0 +1,107 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-29
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import sys
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown
+
+hdwf = c_int()
+szerr = create_string_buffer(512)
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+sts = c_byte()
+frequecy = 1e5
+reference = 1e5
+
+print("Reference: "+str(reference)+" Ohm  Frequency: "+str(frequecy/1e3)+" kHz for picofarad capacitors")
+dwf.FDwfAnalogImpedanceReset(hdwf)
+dwf.FDwfAnalogImpedanceModeSet(hdwf, c_int(8)) # 0 = W1-C1-DUT-C2-R-GND, 1 = W1-C1-R-C2-DUT-GND, 8 = AD IA adapter
+dwf.FDwfAnalogImpedanceReferenceSet(hdwf, c_double(reference)) # reference resistor value in Ohms
+dwf.FDwfAnalogImpedanceFrequencySet(hdwf, c_double(frequecy)) # frequency in Hertz
+dwf.FDwfAnalogImpedanceAmplitudeSet(hdwf, c_double(1))
+dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(1)) # start
+time.sleep(2)
+
+if True:
+    # open compensation is important for high frequency or high resistor values
+    print("Leave the inputs open to perform open compensation.")
+    try: input = raw_input
+    except NameError: pass
+    input("Press enter to continue.")
+    dwf.FDwfAnalogImpedanceCompReset(hdwf)
+    dwf.FDwfAnalogImpedanceStatus(hdwf, None) # ignore last capture, force a new one
+    # do averaging of multiple measurements
+    openResistance = 0
+    openReactance = 0
+    for i in range(10):
+        while True:
+            dwf.FDwfAnalogImpedanceStatus(hdwf, byref(sts))
+            if sts.value == 2:
+                break
+        v1 = c_double()
+        v2 = c_double()
+        dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceResistance, byref(v1))
+        dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceReactance, byref(v2))
+        openResistance += v1.value/10
+        openReactance += v2.value/10
+
+    dwf.FDwfAnalogImpedanceCompSet(hdwf, c_double(openResistance), c_double(openReactance), c_double(0), c_double(0)) # apply open compensation
+ 
+input("Connect the load and press enter to continue.")
+dwf.FDwfAnalogImpedanceStatus(hdwf, None) # ignore last capture, force a new one
+for i in range(10):
+    while True:
+        if dwf.FDwfAnalogImpedanceStatus(hdwf, byref(sts)) == 0:
+            dwf.FDwfGetLastErrorMsg(szerr)
+            print(str(szerr.value))
+            quit()
+        if sts.value == 2:
+            break
+    capacitance = c_double()
+    resistance = c_double()
+    reactance = c_double()
+    phase = c_double()
+    dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceResistance, byref(resistance))
+    dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceReactance, byref(reactance))
+    dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceSeriesCapacitance, byref(capacitance))
+    print(str(i)+" Resistance: "+str(resistance.value)+" Ohm  Reactance: "+str(reactance.value/1e3)+" kOhm  Capacitance: "+str(capacitance.value*1e12)+" pF")
+    gain0 = c_double()
+    gain = c_double()
+    phase = c_double()
+    dwf.FDwfAnalogImpedanceStatusInput(hdwf, c_int(0), byref(gain0), None)
+    dwf.FDwfAnalogImpedanceStatusInput(hdwf, c_int(1), byref(gain), byref(phase))
+    print(" AWG/C1: "+str(gain0.value)+" C1/C2: "+str(gain.value)+" phase: "+str(phase.value/math.pi*180))
+      
+    time.sleep(0.2)
+
+dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(0)) # stop
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/AnalogImpedance_Input.py b/tests/py/AnalogImpedance_Input.py
new file mode 100644
index 0000000000000000000000000000000000000000..d6c237921d00df3b33349b626d146dcd8894f3c0
--- /dev/null
+++ b/tests/py/AnalogImpedance_Input.py
@@ -0,0 +1,107 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2019-07-12
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import sys
+import numpy
+import matplotlib.pyplot as plt
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+hdwf = c_int()
+szerr = create_string_buffer(512)
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+# this option will enable dynamic adjustment of analog out settings like: frequency, amplitude...
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(3)) 
+
+sts = c_byte()
+steps = 151
+start = 1e2
+stop = 1e5
+reference = 1e3
+amplitude = 1
+
+t1 = c_double()
+t2 = c_double()
+
+print("Frequency: "+str(start)+" Hz ... "+str(stop/1e3)+" kHz Steps: "+str(steps))
+dwf.FDwfAnalogImpedanceReset(hdwf)
+dwf.FDwfAnalogImpedanceModeSet(hdwf, c_int(0)) # 0 = W1-C1-DUT-C2-R-GND, 1 = W1-C1-R-C2-DUT-GND, 8 = AD IA adapter
+dwf.FDwfAnalogImpedanceReferenceSet(hdwf, c_double(reference)) # reference resistor value in Ohms
+dwf.FDwfAnalogImpedanceFrequencySet(hdwf, c_double(start)) # frequency in Hertz
+dwf.FDwfAnalogImpedanceAmplitudeSet(hdwf, c_double(amplitude)) # 1V amplitude = 2V peak2peak signal
+dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(1)) # start
+time.sleep(2)
+
+rgHz = [0.0]*steps
+rgGaC2 = [0.0]*steps
+rgPhC2 = [0.0]*steps
+rgCs = [0.0]*steps
+for i in range(steps):
+    hz = stop * pow(10.0, 1.0*(1.0*i/(steps-1)-1)*math.log10(stop/start)) # exponential frequency steps
+    rgHz[i] = hz
+    dwf.FDwfAnalogImpedanceFrequencySet(hdwf, c_double(hz)) # frequency in Hertz
+    time.sleep(0.01)  # settle time for DUT, resonant circuits may require more time
+    dwf.FDwfAnalogImpedanceStatus(hdwf, None) # ignore last capture since we changed the frequency
+    while True:
+        if dwf.FDwfAnalogImpedanceStatus(hdwf, byref(sts)) == 0:
+            dwf.FDwfGetLastErrorMsg(szerr)
+            print(str(szerr.value))
+            quit()
+        if sts.value == 2:
+            break
+    gain2 = c_double()
+    phase2 = c_double()
+    dwf.FDwfAnalogImpedanceStatusInput(hdwf, c_int(1), byref(gain2), byref(phase2)) # relative to Channel 1, C1/C#
+    rgGaC2[i] = 20.0*math.log10(abs(gain2.value-1.0))
+    rgPhC2[i] = phase2.value*180/math.pi
+    cs = c_double()
+    dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceSeriesCapacitance, byref(cs)) 
+    rgCs[i] = cs.value
+    
+
+dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(0)) # stop
+dwf.FDwfDeviceClose(hdwf)
+
+
+plt.subplot(311)
+plt.plot(rgHz, rgGaC2, color='blue')
+ax = plt.gca()
+ax.set_title("{0:.2f}Hz : {1:.2f}dB {2:.2f}* {3:.2f}nF".format(rgHz[0], rgGaC2[0], rgPhC2[0], rgCs[0]*1e9))
+ax.set_xscale('log')
+plt.subplot(312)
+plt.plot(rgHz, rgPhC2)
+ax = plt.gca()
+ax.set_xscale('log')
+plt.subplot(313)
+plt.plot(rgHz, rgCs)
+ax = plt.gca()
+ax.set_xscale('log')
+plt.show()
+
diff --git a/tests/py/AnalogImpedance_Meter.py b/tests/py/AnalogImpedance_Meter.py
new file mode 100644
index 0000000000000000000000000000000000000000..f1ec10ac974b478aea7ca0280758279770870276
--- /dev/null
+++ b/tests/py/AnalogImpedance_Meter.py
@@ -0,0 +1,78 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-28
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import sys
+import numpy
+
+# load dwf library
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+# print version information
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+hdwf = c_int()
+szerr = create_string_buffer(512)
+# try to connect to the first available device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+# print error message if connection fails
+if hdwf.value == hdwfNone.value:
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+# configure impedance measurement
+frequnecy = 1e3
+reference = 1e3
+print("Reference: "+str(reference)+" Ohm  Frequency: "+str(frequnecy/1e3)+" kHz for nanofarad capacitors")
+dwf.FDwfAnalogImpedanceReset(hdwf)
+dwf.FDwfAnalogImpedanceModeSet(hdwf, c_int(8)) # 0 = W1-C1-DUT-C2-R-GND, 1 = W1-C1-R-C2-DUT-GND, 8 = AD IA adapter
+dwf.FDwfAnalogImpedanceReferenceSet(hdwf, c_double(reference)) # reference resistor value in Ohms
+dwf.FDwfAnalogImpedanceFrequencySet(hdwf, c_double(frequnecy)) # frequency in Hertz
+dwf.FDwfAnalogImpedanceAmplitudeSet(hdwf, c_double(1))
+dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(1)) # start
+time.sleep(1)
+
+dwf.FDwfAnalogImpedanceStatus(hdwf, None) # ignore last capture, force a new one
+
+sts = c_byte()
+capacitance = c_double()
+resistance = c_double()
+reactance = c_double()
+
+# measurement reading loop
+for i in range(10):
+    while True:
+        if dwf.FDwfAnalogImpedanceStatus(hdwf, byref(sts)) == 0: # handle error
+            dwf.FDwfGetLastErrorMsg(szerr)
+            print(str(szerr.value))
+            quit()
+        if sts.value == 2:
+            break
+    dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceResistance, byref(resistance))
+    dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceReactance, byref(reactance))
+    dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceSeriesCapacitance, byref(capacitance))
+    print(str(i)+" Resistance: "+str(resistance.value)+" Ohm  Reactance: "+str(reactance.value/1e3)+" kOhm  Capacitance: "+str(capacitance.value*1e9)+" nF")
+    time.sleep(0.2)
+
+dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(0)) # stop
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/AnalogImpedance_ThinkSpeak.py b/tests/py/AnalogImpedance_ThinkSpeak.py
new file mode 100644
index 0000000000000000000000000000000000000000..cea11a5ebdacd869dac40fc440ddb296829a9f55
--- /dev/null
+++ b/tests/py/AnalogImpedance_ThinkSpeak.py
@@ -0,0 +1,87 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2019-10-21
+
+   Requires:                       
+       Python 2.7, 3
+   Desciption:
+   Performs impedance measurements and pushes to ThingSpeak.com
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import sys
+import numpy
+import requests 
+
+url = "https://api.thingspeak.com/update?api_key=8C############BU"
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+hdwf = c_int()
+szerr = create_string_buffer(512)
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+sts = c_byte()
+frequnecy = 1e3
+reference = 1e6
+capacitance = c_double()
+resistance = c_double()
+reactance = c_double()
+
+print("Reference: "+str(reference)+" Ohm  Frequency: "+str(frequnecy/1e3)+" kHz")
+dwf.FDwfAnalogImpedanceReset(hdwf)
+dwf.FDwfAnalogImpedanceModeSet(hdwf, c_int(8)) # 0 = W1-C1-DUT-C2-R-GND, 1 = W1-C1-R-C2-DUT-GND, 8 = AD IA adapter
+dwf.FDwfAnalogImpedanceReferenceSet(hdwf, c_double(reference)) # reference resistor value in Ohms
+dwf.FDwfAnalogImpedanceFrequencySet(hdwf, c_double(frequnecy)) # frequency in Hertz
+dwf.FDwfAnalogImpedanceAmplitudeSet(hdwf, c_double(1))
+dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(1)) # start
+time.sleep(1)
+
+dwf.FDwfAnalogImpedanceStatus(hdwf, None) # ignore last capture, force a new one
+
+print("Press Ctrl+C to stop...")
+
+try:
+    for i in range(1000) :
+        time.sleep(60) # seconds
+        if dwf.FDwfAnalogImpedanceStatus(hdwf, byref(sts)) == 0:
+            dwf.FDwfGetLastErrorMsg(szerr)
+            print(str(szerr.value))
+            quit()
+        if sts.value != 2:
+            print("Measurement not done")
+            continue
+        dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceResistance, byref(resistance))
+        dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceReactance, byref(reactance))
+        dwf.FDwfAnalogImpedanceStatusMeasure(hdwf, DwfAnalogImpedanceSeriesCapacitance, byref(capacitance))
+        print(str(i)+" Resistance: "+str(resistance.value)+" Ohm  Reactance: "+str(reactance.value/1e6)+" MOhm  Capacitance: "+str(capacitance.value*1e12)+" pF")
+        r = requests.get(url+"&field1="+str(resistance.value)+"&field2="+str(reactance.value/1e6)+"&field3="+str(capacitance.value*1e12))
+        if r.status_code != 200:
+            print(r)
+            break
+
+except KeyboardInterrupt: # Ctrl+C
+    pass
+
+dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(0)) # stop
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/AnalogInDigitalIn_Acquisition.py b/tests/py/AnalogInDigitalIn_Acquisition.py
new file mode 100644
index 0000000000000000000000000000000000000000..b54eeac85f5c1e98e4f990756a5daf747fb01e96
--- /dev/null
+++ b/tests/py/AnalogInDigitalIn_Acquisition.py
@@ -0,0 +1,132 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+cSamples = 4000
+rgdAnalog = (c_double*cSamples)()
+rgwDigital = (c_uint16*cSamples)()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # 0 = the device will only be configured when FDwf###Configure is called
+
+print("Generating signal on DIO 0")
+# generate on DIO-0 25khz pulse (100MHz/10000/(7+3)), 30% duty (7low 3high)
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(0), c_int(100))
+dwf.FDwfDigitalOutCounterSet(hdwf, c_int(0), c_int(7), c_int(3))
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+
+# For synchronous analog/digital acquisition set DigitalInTriggerSource to AnalogIn, start DigitalIn then AnalogIn
+
+# configure DigitalIn
+dwf.FDwfDigitalInTriggerSourceSet(hdwf, c_ubyte(4)) # trigsrcAnalogIn
+#sample rate = system frequency / divider, 100MHz/1
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(1))
+# 16bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(16))
+# set number of sample to acquire
+dwf.FDwfDigitalInBufferSizeSet(hdwf, c_int(cSamples))
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(int(cSamples/2))) # trigger position in middle of buffer
+
+# configure AnalogIn
+dwf.FDwfAnalogInFrequencySet(hdwf, c_double(1e8))
+dwf.FDwfAnalogInBufferSizeSet(hdwf, c_int(cSamples)) 
+dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(0)) # trigger position in middle of buffer
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfAnalogInChannelOffsetSet(hdwf, c_int(0), c_double(-2.0))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(5.0))
+
+#trigger on digital signal
+#dwf.FDwfAnalogInTriggerSourceSet(hdwf, c_byte(3)) # trigsrcDetectorDigitalIn
+#dwf.FDwfDigitalInTriggerSet(hdwf, c_int(0), c_int(0), c_int(1), c_int(0)) # DIO-0 rising edge
+
+# trigger on analog signal
+dwf.FDwfAnalogInTriggerSourceSet(hdwf, c_byte(2)) # trigsrcDetectorAnalogIn
+dwf.FDwfAnalogInTriggerTypeSet(hdwf, c_int(0)) # trigtypeEdge
+dwf.FDwfAnalogInTriggerChannelSet(hdwf, c_int(0)) # first channel
+dwf.FDwfAnalogInTriggerLevelSet(hdwf, c_double(1.5)) # 1.5V
+dwf.FDwfAnalogInTriggerConditionSet(hdwf, c_int(0))  # trigcondRisingPositive
+dwf.FDwfAnalogInConfigure(hdwf, c_int(True), c_int(False))
+
+#wait at least 2 seconds for the offset to stabilize
+time.sleep(2)
+
+# start DigitalIn and AnalogIn
+dwf.FDwfDigitalInConfigure(hdwf, c_int(True), c_int(True))
+dwf.FDwfAnalogInConfigure(hdwf, c_int(True), c_int(True))
+
+while True: # wait to be armed
+  dwf.FDwfDigitalInStatus(hdwf, c_int(0), byref(sts))
+  print("DigitalIn state: "+str(sts.value))
+  if sts.value == 5 :
+    continue
+  dwf.FDwfAnalogInStatus(hdwf, c_int(0), byref(sts))
+  print("AnalogIn state: "+str(sts.value))
+  if sts.value == 5 :
+    continue
+  break
+  
+while True:
+    time.sleep(1)
+    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+    if sts.value == 2 : # done
+       dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+       break
+
+# read data
+dwf.FDwfDigitalInStatusData(hdwf, rgwDigital, c_int(sizeof(c_uint16)*cSamples)) 
+dwf.FDwfAnalogInStatusData(hdwf, c_int(0), rgdAnalog, c_int(cSamples)) # get channel 1 data
+#dwf.FDwfAnalogInStatusData(hdwf, 1, rgdAnalog, cSamples) # get channel 2 data
+
+
+dwf.FDwfDigitalOutReset(hdwf)
+dwf.FDwfDeviceCloseAll()
+
+# plot
+rgIndex=[0.0]*(cSamples)
+rgAnalog=[0.0]*(cSamples)
+rgDigital=[0.0]*(cSamples)
+for i in range(0,cSamples):
+    rgIndex[i]=i
+    rgAnalog[i]=rgdAnalog[i]
+    rgDigital[i]=rgwDigital[i]&1 # mask DIO0
+
+plt.plot(rgIndex, rgAnalog, rgIndex, rgDigital)
+plt.show()
+
+
diff --git a/tests/py/AnalogIn_Acquisition.py b/tests/py/AnalogIn_Acquisition.py
new file mode 100644
index 0000000000000000000000000000000000000000..dcb275107f34f32ca2936215d077ad4f33d8f191
--- /dev/null
+++ b/tests/py/AnalogIn_Acquisition.py
@@ -0,0 +1,86 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+#declare ctype variables
+hdwf = c_int()
+sts = c_byte()
+rgdSamples = (c_double*4000)()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(szerr.value)
+    print("failed to open device")
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # 0 = the device will only be configured when FDwf###Configure is called
+
+cBufMax = c_int()
+dwf.FDwfAnalogInBufferSizeInfo(hdwf, 0, byref(cBufMax))
+print("Device buffer size: "+str(cBufMax.value)) 
+
+#set up acquisition
+dwf.FDwfAnalogInFrequencySet(hdwf, c_double(20000000.0))
+dwf.FDwfAnalogInBufferSizeSet(hdwf, c_int(4000)) 
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(-1), c_int(1))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(-1), c_double(5))
+dwf.FDwfAnalogInChannelFilterSet(hdwf, c_int(-1), filterDecimate)
+#dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0))
+
+# wait at least 2 seconds for the offset to stabilize
+time.sleep(2)
+
+print("Starting oscilloscope")
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(1))
+
+
+while True:
+    dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+    if sts.value == DwfStateDone.value :
+        break
+    time.sleep(0.1)
+print("Acquisition done")
+
+dwf.FDwfAnalogInStatusData(hdwf, 0, rgdSamples, 4000) # get channel 1 data
+#dwf.FDwfAnalogInStatusData(hdwf, 1, rgdSamples, 4000) # get channel 2 data
+dwf.FDwfDeviceCloseAll()
+
+#plot window
+dc = sum(rgdSamples)/len(rgdSamples)
+print("DC: "+str(dc)+"V")
+
+plt.plot(numpy.fromiter(rgdSamples, dtype = numpy.float))
+plt.show()
+
+
diff --git a/tests/py/AnalogIn_Logger.py b/tests/py/AnalogIn_Logger.py
new file mode 100644
index 0000000000000000000000000000000000000000..c9011136ded7ce06f15b61f2310b0e2f59f5062f
--- /dev/null
+++ b/tests/py/AnalogIn_Logger.py
@@ -0,0 +1,102 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+   Description:
+   Generates AM modulated signal on AWG1 channel
+   Scope performs scan shift acquisition and logs DC and AC/DC-RMS values
+"""
+
+from ctypes import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+secLog = 1.0 # logging rate in seconds
+nSamples = 8000
+rgdSamples = (c_double*nSamples)()
+cValid = c_int(0)
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # 0 = the device will only be configured when FDwf###Configure is called
+
+print("Generating AM sine wave...")
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(0), c_int(1)) # carrier
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(0), c_int(1)) # sine
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(0), c_double(50))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(0), c_double(1))
+dwf.FDwfAnalogOutNodeOffsetSet(hdwf, c_int(0), c_int(0), c_double(0.5))
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(2), c_int(1)) # AM
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(2), c_int(3)) # triangle
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(2), c_double(0.1))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(2), c_double(50))
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
+
+#set up acquisition
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(5))
+dwf.FDwfAnalogInAcquisitionModeSet(hdwf, c_int(1)) #acqmodeScanShift
+dwf.FDwfAnalogInFrequencySet(hdwf, c_double(nSamples/secLog))
+dwf.FDwfAnalogInBufferSizeSet(hdwf, c_int(nSamples))
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0))
+
+#wait at least 2 seconds for the offset to stabilize
+time.sleep(1)
+
+#begin acquisition
+dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
+
+print("Press Ctrl+C to stop")
+try:
+    while True:
+        time.sleep(secLog)
+        dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+        dwf.FDwfAnalogInStatusSamplesValid(hdwf, byref(cValid))
+        for iChannel in range(2):
+            dwf.FDwfAnalogInStatusData(hdwf, c_int(iChannel), byref(rgdSamples), cValid) # get channel 1 data
+            dc = 0
+            for i in range(nSamples):
+                dc += rgdSamples[i]
+            dc /= nSamples
+            dcrms = 0
+            acrms = 0
+            for i in range(nSamples):
+                dcrms += rgdSamples[i] ** 2
+                acrms += (rgdSamples[i]-dc) ** 2
+            dcrms /= nSamples
+            dcrms = math.sqrt(dcrms)
+            acrms /= nSamples
+            acrms = math.sqrt(acrms)
+            print(f"CH:{iChannel+1} DC:{dc:.3f}V DCRMS:{dcrms:.3f}V ACRMS:{acrms:.3f}V")
+except KeyboardInterrupt:
+    pass
+
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(0))
+dwf.FDwfDeviceCloseAll()
+
diff --git a/tests/py/AnalogIn_Record.py b/tests/py/AnalogIn_Record.py
new file mode 100644
index 0000000000000000000000000000000000000000..aaa75a5cd2a1bf6a6aa8f7c2f132d6a31ee5ecd4
--- /dev/null
+++ b/tests/py/AnalogIn_Record.py
@@ -0,0 +1,120 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+#declare ctype variables
+hdwf = c_int()
+sts = c_byte()
+hzAcq = c_double(100000)
+nSamples = 200000
+rgdSamples = (c_double*nSamples)()
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+fLost = 0
+fCorrupted = 0
+
+#print(DWF version
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # 0 = the device will only be configured when FDwf###Configure is called
+
+print("Generating sine wave...")
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), AnalogOutNodeCarrier, c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), AnalogOutNodeCarrier, funcSine)
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), AnalogOutNodeCarrier, c_double(1))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), AnalogOutNodeCarrier, c_double(2))
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
+
+#set up acquisition
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(5))
+dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord)
+dwf.FDwfAnalogInFrequencySet(hdwf, hzAcq)
+dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(nSamples/hzAcq.value)) # -1 infinite record length
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0))
+
+#wait at least 2 seconds for the offset to stabilize
+time.sleep(2)
+
+print("Starting oscilloscope")
+dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
+
+cSamples = 0
+
+while cSamples < nSamples:
+    dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+    if cSamples == 0 and (sts == DwfStateConfig or sts == DwfStatePrefill or sts == DwfStateArmed) :
+        # Acquisition not yet started.
+        continue
+
+    dwf.FDwfAnalogInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+    
+    cSamples += cLost.value
+
+    if cLost.value :
+        fLost = 1
+    if cCorrupted.value :
+        fCorrupted = 1
+
+    if cAvailable.value==0 :
+        continue
+
+    if cSamples+cAvailable.value > nSamples :
+        cAvailable = c_int(nSamples-cSamples)
+    
+    dwf.FDwfAnalogInStatusData(hdwf, c_int(0), byref(rgdSamples, sizeof(c_double)*cSamples), cAvailable) # get channel 1 data
+    #dwf.FDwfAnalogInStatusData(hdwf, c_int(1), byref(rgdSamples, sizeof(c_double)*cSamples), cAvailable) # get channel 2 data
+    cSamples += cAvailable.value
+
+dwf.FDwfAnalogOutReset(hdwf, c_int(0))
+dwf.FDwfDeviceCloseAll()
+
+print("Recording done")
+if fLost:
+    print("Samples were lost! Reduce frequency")
+if fCorrupted:
+    print("Samples could be corrupted! Reduce frequency")
+
+f = open("record.csv", "w")
+for v in rgdSamples:
+    f.write("%s\n" % v)
+f.close()
+  
+plt.plot(numpy.fromiter(rgdSamples, dtype = numpy.float))
+plt.show()
+
+
diff --git a/tests/py/AnalogIn_Record_Trigger.py b/tests/py/AnalogIn_Record_Trigger.py
new file mode 100644
index 0000000000000000000000000000000000000000..e2f98a97edcd19f75f7667b6b07e151982dd9e5d
--- /dev/null
+++ b/tests/py/AnalogIn_Record_Trigger.py
@@ -0,0 +1,150 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+#declare ctype variables
+hdwf = c_int()
+sts = c_byte()
+hzAcq = c_double(100000)
+nSamples = 200000
+rgdSamples1 = (c_double*nSamples)()
+rgdSamples2 = (c_double*nSamples)()
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+fLost = 0
+fCorrupted = 0
+
+#print(DWF version
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+if dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf)) != 1 or hdwf.value == hdwfNone.value:
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # 0 = the device will only be configured when FDwf###Configure is called
+
+print("Generating sine wave...")
+#                                    AWG 1     carrier
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(0), c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(0), funcSine)
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(0), c_double(1))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(0), c_double(2))
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
+
+#set up acquisition
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(5))
+dwf.FDwfAnalogInAcquisitionModeSet(hdwf, c_int(3)) # record
+dwf.FDwfAnalogInFrequencySet(hdwf, hzAcq)
+sRecord = nSamples/hzAcq.value
+dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(sRecord)) # -1 infinite record length
+dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(-0.25*sRecord)) # -0.25 = trigger at 25%
+
+#set up trigger
+dwf.FDwfAnalogInTriggerAutoTimeoutSet(hdwf, c_double(10)) # 10 second auto trigger timeout
+dwf.FDwfAnalogInTriggerSourceSet(hdwf, c_ubyte(2)) # trigsrcDetectorAnalogIn
+dwf.FDwfAnalogInTriggerTypeSet(hdwf, c_int(0)) # trigtypeEdge
+dwf.FDwfAnalogInTriggerChannelSet(hdwf, c_int(0)) # channel 1
+dwf.FDwfAnalogInTriggerLevelSet(hdwf, c_double(0)) # 0V
+dwf.FDwfAnalogInTriggerHysteresisSet(hdwf, c_double(0.01)) # 0.01V
+dwf.FDwfAnalogInTriggerConditionSet(hdwf, c_int(0)) # trigcondRisingPositive 
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0))
+
+#wait at least 2 seconds for the offset to stabilize
+time.sleep(2)
+
+print("Starting oscilloscope")
+dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
+
+iSample = 0
+
+# loop to get data chunks
+while True:
+    if dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts)) != 1:
+        print("FDwfAnalogInStatus Error")
+        szerr = create_string_buffer(512)
+        dwf.FDwfGetLastErrorMsg(szerr)
+        print(szerr.value)
+        break
+
+    dwf.FDwfAnalogInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+    iSample += cLost.value
+    iSample %= nSamples
+
+    if cLost.value :
+        fLost = 1
+    if cCorrupted.value :
+        fCorrupted = 1
+
+    iBuffer = 0
+    while cAvailable.value>0:
+        cSamples = cAvailable.value
+        # we are using circular sample buffer, make sure to not overflow our rgdSamples# buffers
+        if iSample+cAvailable.value > nSamples:
+            cSamples = nSamples-iSample
+        dwf.FDwfAnalogInStatusData2(hdwf, c_int(0), byref(rgdSamples1, sizeof(c_double)*iSample), c_int(iBuffer), c_int(cSamples)) # get channel 1 data
+        dwf.FDwfAnalogInStatusData2(hdwf, c_int(1), byref(rgdSamples2, sizeof(c_double)*iSample), c_int(iBuffer), c_int(cSamples)) # get channel 2 data
+        iBuffer += cSamples
+        cAvailable.value -= cSamples
+        iSample += cSamples
+        iSample %= nSamples
+
+    if sts.value == DwfStateDone : # done
+        break
+
+dwf.FDwfAnalogOutReset(hdwf, c_int(0))
+dwf.FDwfDeviceCloseAll()
+
+if iSample != 0 :
+    rgdSamples1 = rgdSamples1[iSample:]+rgdSamples1[:iSample]
+    rgdSamples2 = rgdSamples2[iSample:]+rgdSamples2[:iSample]
+
+print("Recording done")
+if fLost:
+    print("Samples were lost! Reduce frequency")
+if fCorrupted:
+    print("Samples could be corrupted! Reduce frequency")
+
+f = open("record1.csv", "w")
+for v in rgdSamples1:
+    f.write("%s\n" % v)
+f.close()
+
+f = open("record2.csv", "w")
+for v in rgdSamples2:
+    f.write("%s\n" % v)
+f.close()
+
+plt.plot(numpy.fromiter(rgdSamples1, dtype = numpy.float), color='orange')
+plt.plot(numpy.fromiter(rgdSamples2, dtype = numpy.float), color='blue')
+plt.show()
+
+
diff --git a/tests/py/AnalogIn_Record_Trigger_int16.py b/tests/py/AnalogIn_Record_Trigger_int16.py
new file mode 100644
index 0000000000000000000000000000000000000000..e764d5621cd399f72586216c065e48583df33151
--- /dev/null
+++ b/tests/py/AnalogIn_Record_Trigger_int16.py
@@ -0,0 +1,130 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2020-06-04
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+#declare ctype variables
+hdwf = c_int()
+sts = c_byte()
+hzAcq = c_double(1e6)
+nSamples = int(1e5)
+rgSamples1 = (c_int16*nSamples)()
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+fLost = 0
+fCorrupted = 0
+
+#print(DWF version
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # 0 = the device will only be configured when FDwf###Configure is called
+
+print("Generating sine wave...")
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), AnalogOutNodeCarrier, c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), AnalogOutNodeCarrier, funcSine)
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), AnalogOutNodeCarrier, c_double(10.0*hzAcq.value/nSamples))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), AnalogOutNodeCarrier, c_double(2))
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
+
+#set up acquisition
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(5))
+dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord)
+dwf.FDwfAnalogInFrequencySet(hdwf, hzAcq)
+dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(nSamples/hzAcq.value)) # -1 infinite record length
+dwf.FDwfAnalogInTriggerSourceSet(hdwf, c_int(7)) # trigsrcAnalogOut1 
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0))
+
+
+#wait at least 2 seconds for the offset to stabilize
+time.sleep(2)
+
+print("Starting oscilloscope")
+dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
+
+iSample = 0
+
+while True:
+    dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+
+    dwf.FDwfAnalogInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+    
+    iSample += cLost.value
+    iSample %= nSamples
+
+    if cLost.value :
+        fLost = 1
+    if cCorrupted.value :
+        fCorrupted = 1
+
+    iBuffer = 0
+    while cAvailable.value>0:
+        cSamples = cAvailable.value
+        # we are using circular sample buffer, make sure to not overflow
+        if iSample+cAvailable.value > nSamples:
+            cSamples = nSamples-iSample
+        dwf.FDwfAnalogInStatusData16(hdwf, c_int(0), byref(rgSamples1, sizeof(c_int16)*iSample), c_int(iBuffer), c_int(cSamples)) # get channel 1 data
+        iBuffer += cSamples
+        cAvailable.value -= cSamples
+        iSample += cSamples
+        iSample %= nSamples
+
+    if sts.value == 2 : # done
+        break
+
+
+dwf.FDwfAnalogOutReset(hdwf, c_int(0))
+dwf.FDwfDeviceCloseAll()
+
+# align recorded data
+if iSample != 0 :
+    rgSamples1 = rgSamples1[iSample:]+rgSamples1[:iSample]
+
+print("Recording done "+str(iSample))
+if fLost:
+    print("Samples were lost! Reduce frequency")
+if fCorrupted:
+    print("Samples could be corrupted! Reduce frequency")
+
+f = open("record.csv", "w")
+for v in rgSamples1:
+    f.write("%s\n" % v)
+f.close()
+
+plt.plot(numpy.fromiter(rgSamples1, dtype = numpy.int16))
+plt.show()
+
+
diff --git a/tests/py/AnalogIn_Record_Wave_Mono.py b/tests/py/AnalogIn_Record_Wave_Mono.py
new file mode 100644
index 0000000000000000000000000000000000000000..527d6625f7c1973fec5fb7eea40d99e1fa6ee0f8
--- /dev/null
+++ b/tests/py/AnalogIn_Record_Wave_Mono.py
@@ -0,0 +1,151 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+   Desciption:
+   - generates sine on AWG1
+   - records data on Scope 1
+   - writes data to 16 bit WAV file
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+import numpy
+import wave
+import datetime
+import os
+import array
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+#declare ctype variables
+hdwf = c_int()
+sts = c_byte()
+vOffset = c_double(1.41)
+vAmplitude = c_double(1.41)
+hzSignal = c_double(80)
+hzAcq = c_double(80000)
+nSamples = 800000
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+fLost = 0
+fCorrupted = 0
+
+#print(DWF version
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # 0 = the device will only be configured when FDwf###Configure is called
+
+print("Generating sine wave...")
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), AnalogOutNodeCarrier, c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), AnalogOutNodeCarrier, funcSine)
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), AnalogOutNodeCarrier, hzSignal)
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), AnalogOutNodeCarrier, vAmplitude)
+dwf.FDwfAnalogOutNodeOffsetSet(hdwf, c_int(0), AnalogOutNodeCarrier, vOffset)
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
+
+#set up acquisition
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(2.0*vAmplitude.value))
+dwf.FDwfAnalogInChannelOffsetSet(hdwf, c_int(0), vOffset)
+dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord)
+dwf.FDwfAnalogInFrequencySet(hdwf, hzAcq)
+dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(-1)) # -1 infinite record length
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0))
+
+#wait at least 2 seconds for the offset to stabilize
+time.sleep(2)
+
+print("Starting oscilloscope")
+dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
+
+cSamples = 0
+
+print("Generating "+str(hzSignal.value)+"Hz, recording "+str(hzAcq.value)+"Hz for "+str(nSamples/hzAcq.value)+"s, press Ctrl+C to stop...");
+#get the proper file name
+
+#open WAV file
+starttime = datetime.datetime.now();
+startfilename = "AD2_" + "{:04d}".format(starttime.year) + "{:02d}".format(starttime.month) + "{:02d}".format(starttime.day) + "_" + "{:02d}".format(starttime.hour) + "{:02d}".format(starttime.minute) + "{:02d}".format(starttime.second) + ".wav";
+print("Writing WAV file '" + startfilename + "'");
+waveWrite = wave.open(startfilename, "wb");
+waveWrite.setnchannels(1);				# 1 channels 
+waveWrite.setsampwidth(2);				# 16 bit / sample
+waveWrite.setframerate(hzAcq.value);
+waveWrite.setcomptype("NONE","No compression");
+
+try:
+    while cSamples < nSamples:
+        dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+        if cSamples == 0 and (sts == DwfStateConfig or sts == DwfStatePrefill or sts == DwfStateArmed) :
+            # Acquisition not yet started.
+            continue
+
+        dwf.FDwfAnalogInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+        
+        cSamples += cLost.value
+
+        if cLost.value :
+            fLost = 1
+        if cCorrupted.value :
+            fCorrupted = 1
+
+        if cAvailable.value==0 :
+            continue
+
+        if cSamples+cAvailable.value > nSamples :
+            cAvailable = c_int(nSamples-cSamples)
+        
+        rgSamples = (c_int16*cAvailable.value)()
+
+        dwf.FDwfAnalogInStatusData16(hdwf, c_int(0), rgSamples, c_int(0), cAvailable) # get channel 1 data chunk
+        cSamples += cAvailable.value
+        waveWrite.writeframes(rgSamples)
+        
+except KeyboardInterrupt:
+    pass	
+
+endtime = datetime.datetime.now();
+dwf.FDwfAnalogOutReset(hdwf, c_int(0))
+dwf.FDwfDeviceCloseAll()
+
+print(" done")
+if fLost:
+    print("Samples were lost! Reduce frequency")
+if fCorrupted:
+    print("Samples could be corrupted! Reduce frequency")
+
+waveWrite.close();
+
+endfilename = "AD2_" + "{:04d}".format(starttime.year) + "{:02d}".format(starttime.month) + "{:02d}".format(starttime.day) + "_" + "{:02d}".format(starttime.hour) + "{:02d}".format(starttime.minute) + "{:02d}".format(starttime.second) + "-" + "{:02d}".format(endtime.hour) + "{:02d}".format(endtime.minute) + "{:02d}".format(endtime.second) + ".wav";
+print("Renaming file from '" + startfilename + "' to '" + endfilename + "'");
+os.rename(startfilename, endfilename);
+
+print(" done")
+
diff --git a/tests/py/AnalogIn_Record_int16.py b/tests/py/AnalogIn_Record_int16.py
new file mode 100644
index 0000000000000000000000000000000000000000..d4cb86862c8debe370e374c9894e5a3c1958d46a
--- /dev/null
+++ b/tests/py/AnalogIn_Record_int16.py
@@ -0,0 +1,120 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+#declare ctype variables
+hdwf = c_int()
+sts = c_byte()
+hzAcq = c_double(1e6)
+nSamples = 2**17
+rgSamples = (c_int16*nSamples)()
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+fLost = 0
+fCorrupted = 0
+
+#print(DWF version
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # 0 = the device will only be configured when FDwf###Configure is called
+
+print("Generating sine wave...")
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), AnalogOutNodeCarrier, c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), AnalogOutNodeCarrier, funcSine)
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), AnalogOutNodeCarrier, c_double(1e8/2**16))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), AnalogOutNodeCarrier, c_double(2))
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
+
+#set up acquisition
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(5))
+dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord)
+dwf.FDwfAnalogInFrequencySet(hdwf, hzAcq)
+dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(nSamples/hzAcq.value)) # -1 infinite record length
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0))
+
+#wait at least 2 seconds for the offset to stabilize
+time.sleep(2)
+
+print("Starting oscilloscope")
+dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
+
+cSamples = 0
+
+while cSamples < nSamples:
+    dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+    if cSamples == 0 and (sts == DwfStateConfig or sts == DwfStatePrefill or sts == DwfStateArmed) :
+        # Acquisition not yet started.
+        continue
+
+    dwf.FDwfAnalogInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+    
+    cSamples += cLost.value
+
+    if cLost.value :
+        fLost = 1
+    if cCorrupted.value :
+        fCorrupted = 1
+
+    if cAvailable.value==0 :
+        continue
+
+    if cSamples+cAvailable.value > nSamples :
+        cAvailable = c_int(nSamples-cSamples)
+    
+    dwf.FDwfAnalogInStatusData16(hdwf, c_int(0), byref(rgSamples, sizeof(c_int16)*cSamples), c_int(0), cAvailable) # get channel 1 data
+    #dwf.FDwfAnalogInStatusData16(hdwf, c_int(1), byref(rgSamples, sizeof(c_int16)*cSamples), c_int(c), Available) # get channel 2 data
+    cSamples += cAvailable.value
+
+dwf.FDwfAnalogOutReset(hdwf, c_int(0))
+dwf.FDwfDeviceCloseAll()
+
+print("Recording done")
+if fLost:
+    print("Samples were lost! Reduce frequency")
+if fCorrupted:
+    print("Samples could be corrupted! Reduce frequency")
+
+f = open("record.csv", "w")
+for v in rgSamples:
+    f.write("%s\n" % v)
+f.close()
+
+plt.plot(numpy.fromiter(rgSamples, dtype = numpy.int16))
+plt.show()
+
+
diff --git a/tests/py/AnalogIn_Sample.py b/tests/py/AnalogIn_Sample.py
new file mode 100644
index 0000000000000000000000000000000000000000..830e05c1d1f98f47d627a8c09294ff7b177399df
--- /dev/null
+++ b/tests/py/AnalogIn_Sample.py
@@ -0,0 +1,61 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+#declare ctype variables
+hdwf = c_int()
+voltage1 = c_double()
+voltage2 = c_double()
+
+#print(DWF version
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+"Opening first device..."
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(szerr.value)
+    print("failed to open device")
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # 0 = the device will only be configured when FDwf###Configure is called
+
+print("Preparing to read sample...")
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1)) 
+dwf.FDwfAnalogInChannelOffsetSet(hdwf, c_int(0), c_double(0)) 
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(5)) 
+dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(0))
+
+time.sleep(2)
+
+for i in range(5):
+    time.sleep(1)
+    dwf.FDwfAnalogInStatus(hdwf, c_int(False), None) # fetch status and samples from device
+    dwf.FDwfAnalogInStatusSample(hdwf, c_int(0), byref(voltage1))
+    dwf.FDwfAnalogInStatusSample(hdwf, c_int(1), byref(voltage2))
+    print("Channel 1:  " + str(voltage1.value)+" V")
+    print("Channel 2:  " + str(voltage2.value)+" V")
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/AnalogIn_ShiftScreen.py b/tests/py/AnalogIn_ShiftScreen.py
new file mode 100644
index 0000000000000000000000000000000000000000..74093d167848499d4f677ebb0d05493998154067
--- /dev/null
+++ b/tests/py/AnalogIn_ShiftScreen.py
@@ -0,0 +1,91 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+hzAcq = c_double(200)
+nSamples = 1000
+rgdSamples = (c_double*nSamples)()
+cValid = c_int(0)
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # 0 = the device will only be configured when FDwf###Configure is called
+
+print("Generating sine wave...")
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(0), c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(0), c_int(1)) #sine
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(0), c_double(1))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(0), c_double(2))
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
+
+#set up acquisition
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(5))
+dwf.FDwfAnalogInAcquisitionModeSet(hdwf, c_int(1)) #acqmodeScanShift
+dwf.FDwfAnalogInFrequencySet(hdwf, hzAcq)
+dwf.FDwfAnalogInBufferSizeSet(hdwf, c_int(nSamples))
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0))
+
+#wait at least 2 seconds for the offset to stabilize
+time.sleep(2)
+
+#begin acquisition
+dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
+
+plt.axis([0, len(rgdSamples), -2.5, 2.5])
+plt.ion()
+hl, = plt.plot([], [])
+hl.set_xdata(range(0, len(rgdSamples)))
+
+start = time.time()
+print("Press Ctrl+C to stop")
+try:
+    while True: #time.time()-start < 10:
+        dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+
+        dwf.FDwfAnalogInStatusSamplesValid(hdwf, byref(cValid))
+
+        dwf.FDwfAnalogInStatusData(hdwf, c_int(0), byref(rgdSamples), cValid) # get channel 1 data
+        #dwf.FDwfAnalogInStatusData(hdwf, c_int(1), byref(rgdSamples), cValid) # get channel 2 data
+        #print(cValid.value)
+        hl.set_ydata(rgdSamples)
+        plt.draw()
+        plt.pause(0.01)
+except KeyboardInterrupt:
+    pass
+
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(0))
+dwf.FDwfDeviceCloseAll()
+
diff --git a/tests/py/AnalogIn_Trigger.py b/tests/py/AnalogIn_Trigger.py
new file mode 100644
index 0000000000000000000000000000000000000000..d8c10b6e4caa2302fc2afdb7938ab6d1e872c8c6
--- /dev/null
+++ b/tests/py/AnalogIn_Trigger.py
@@ -0,0 +1,121 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2022-03-08
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import sys
+import matplotlib.pyplot as plt
+import numpy
+
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+# 2nd configuration for Analog Discovery with 16k analog-in buffer
+#dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(1), byref(hdwf)) 
+
+if hdwf.value == hdwfNone.value:
+    szError = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szError);
+    print("failed to open device\n"+str(szError.value))
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # 0 = the device will only be configured when FDwf###Configure is called
+
+print("Generating signal...")
+#                                    AWG 1     carrier
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(0), c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(0), funcSine)
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(0), c_double(123e3))
+dwf.FDwfAnalogOutNodeOffsetSet(hdwf, c_int(0), c_int(0), c_double(0.0))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(0), c_double(1.0))
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
+
+cSamples = 1024
+hzRate = 100e6
+rgdSamples = (c_double*cSamples)()
+
+#set up acquisition
+dwf.FDwfAnalogInFrequencySet(hdwf, c_double(hzRate))
+dwf.FDwfAnalogInBufferSizeSet(hdwf, c_int(cSamples)) 
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(5))
+
+#set up trigger
+dwf.FDwfAnalogInTriggerAutoTimeoutSet(hdwf, c_double(0)) #disable auto trigger
+dwf.FDwfAnalogInTriggerSourceSet(hdwf, trigsrcDetectorAnalogIn) #one of the analog in channels
+dwf.FDwfAnalogInTriggerTypeSet(hdwf, trigtypeEdge)
+dwf.FDwfAnalogInTriggerChannelSet(hdwf, c_int(0)) # first channel
+dwf.FDwfAnalogInTriggerLevelSet(hdwf, c_double(0.0)) # 0.0V
+dwf.FDwfAnalogInTriggerConditionSet(hdwf, DwfTriggerSlopeRise) 
+# relative to middle of the buffer, with time base/2 T0 will bt the first sample
+dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(0.5*cSamples/hzRate)) 
+
+#or use trigger from other instruments or external trigger
+#dwf.FDwfAnalogInTriggerSourceSet(hdwf, trigsrcExternal1) 
+#dwf.FDwfAnalogInTriggerConditionSet(hdwf, DwfTriggerSlopeEither) 
+
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0))
+# wait at least 2 seconds with Analog Discovery for the offset to stabilize, before the first reading after device open or offset/range change
+time.sleep(2)
+
+print("Starting repeated acquisitions")
+dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
+
+for iTrigger in range(10):
+    # new acquisition is started automatically after done state 
+
+    while True:
+        dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+        if sts.value == DwfStateDone.value :
+            break
+        time.sleep(0.001)
+    
+    dwf.FDwfAnalogInStatusData(hdwf, 0, rgdSamples, cSamples) # get channel 1 data
+    #dwf.FDwfAnalogInStatusData(hdwf, 1, rgdSamples, cSamples) # get channel 2 data
+    
+    dc = sum(rgdSamples)/len(rgdSamples)
+    print("Acquisition #"+str(iTrigger)+" average: "+str(dc)+"V")
+    
+    sec = c_uint()
+    tick = c_uint()
+    ticksec = c_uint()
+    # acquisition software time for Analog Discovery and T0 with 8-10ns precision for ADP3X50
+    dwf.FDwfAnalogInStatusTime(hdwf, byref(sec), byref(tick), byref(ticksec))
+    s = time.localtime(sec.value)
+    ns = 1e9/ticksec.value*tick.value
+    ms = math.floor(ns/1e6)
+    ns -= ms*1e6
+    us = math.floor(ns/1e3)
+    ns -= us*1e3
+    ns = math.floor(ns)
+    print(time.strftime("%Y-%m-%d %H:%M:%S", s)+"."+str(ms).zfill(3)+"."+str(us).zfill(3)+"."+str(ns).zfill(3))
+    
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(0))
+dwf.FDwfDeviceCloseAll()
+
+plt.plot(numpy.fromiter(rgdSamples, dtype = numpy.float))
+plt.show()
+
+
diff --git a/tests/py/AnalogNetwork_Analyzer.py b/tests/py/AnalogNetwork_Analyzer.py
new file mode 100644
index 0000000000000000000000000000000000000000..896baff3333dec601313e064972dd812c67a672b
--- /dev/null
+++ b/tests/py/AnalogNetwork_Analyzer.py
@@ -0,0 +1,103 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2019-07-12
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import sys
+import numpy
+import matplotlib.pyplot as plt
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+hdwf = c_int()
+szerr = create_string_buffer(512)
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    print("failed to open device")
+    quit()
+
+# this option will enable dynamic adjustment of analog out settings like: frequency, amplitude...
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(3)) 
+
+sts = c_byte()
+steps = 101
+start = 1e2
+stop = 1e6
+reference = 1e4
+amplitude = 1
+
+print("Frequency: "+str(start)+" Hz ... "+str(stop/1e3)+" kHz Steps: "+str(steps))
+dwf.FDwfAnalogImpedanceReset(hdwf)
+dwf.FDwfAnalogImpedanceModeSet(hdwf, c_int(0)) # 0 = W1-C1-DUT-C2-R-GND, 1 = W1-C1-R-C2-DUT-GND, 8 = AD IA adapter
+dwf.FDwfAnalogImpedanceReferenceSet(hdwf, c_double(reference)) # reference resistor value in Ohms
+dwf.FDwfAnalogImpedanceFrequencySet(hdwf, c_double(start)) # frequency in Hertz
+dwf.FDwfAnalogImpedanceAmplitudeSet(hdwf, c_double(amplitude)) # 1V amplitude = 2V peak2peak signal
+dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(1)) # start
+time.sleep(2)
+
+rgHz = [0.0]*steps
+rgGaC1 = [0.0]*steps
+rgGaC2 = [0.0]*steps
+rgPhC2 = [0.0]*steps
+for i in range(steps):
+    hz = stop * pow(10.0, 1.0*(1.0*i/(steps-1)-1)*math.log10(stop/start)) # exponential frequency steps
+    rgHz[i] = hz
+    dwf.FDwfAnalogImpedanceFrequencySet(hdwf, c_double(hz)) # frequency in Hertz
+    time.sleep(0.01) 
+    dwf.FDwfAnalogImpedanceStatus(hdwf, None) # ignore last capture since we changed the frequency
+    while True:
+        if dwf.FDwfAnalogImpedanceStatus(hdwf, byref(sts)) == 0:
+            dwf.FDwfGetLastErrorMsg(szerr)
+            print(str(szerr.value))
+            quit()
+        if sts.value == 2:
+            break
+    gain1 = c_double()
+    gain2 = c_double()
+    phase2 = c_double()
+    dwf.FDwfAnalogImpedanceStatusInput(hdwf, c_int(0), byref(gain1), 0) # relative to FDwfAnalogImpedanceAmplitudeSet Amplitude/C1
+    dwf.FDwfAnalogImpedanceStatusInput(hdwf, c_int(1), byref(gain2), byref(phase2)) # relative to Channel 1, C1/C#
+    rgGaC1[i] = 1.0/gain1.value
+    rgGaC2[i] = 1.0/gain2.value
+    rgPhC2[i] = -phase2.value*180/math.pi
+    # peak voltage value:
+    # rgGaC1[i] = amplitude/gain1.value 
+    # rgGaC2[i] = amplitude/gain1.value/gain2.value 
+
+
+dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(0)) # stop
+dwf.FDwfDeviceClose(hdwf)
+
+plt.subplot(211)
+plt.plot(rgHz, rgGaC1, color='orange')
+plt.plot(rgHz, rgGaC2, color='blue')
+ax = plt.gca()
+ax.set_xscale('log')
+ax.set_yscale('log')
+plt.subplot(212)
+plt.plot(rgHz, rgPhC2)
+ax = plt.gca()
+ax.set_xscale('log')
+plt.show()
+
diff --git a/tests/py/AnalogOutIn.py b/tests/py/AnalogOutIn.py
new file mode 100644
index 0000000000000000000000000000000000000000..82c09170e675a5b7fd54f09beea89fe656c400cb
--- /dev/null
+++ b/tests/py/AnalogOutIn.py
@@ -0,0 +1,86 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import time
+from dwfconstants import *
+import sys
+import matplotlib.pyplot as plt
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("Version: "+str(version.value))
+
+cdevices = c_int()
+dwf.FDwfEnum(c_int(0), byref(cdevices))
+print("Number of Devices: "+str(cdevices.value))
+
+if cdevices.value == 0:
+    print("no device detected")
+    quit()
+
+print("Opening first device")
+hdwf = c_int()
+dwf.FDwfDeviceOpen(c_int(0), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+print("Configure and start first analog out channel")
+dwf.FDwfAnalogOutEnableSet(hdwf, c_int(0), c_int(1)) # 1 = Sine wave")
+dwf.FDwfAnalogOutFunctionSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfAnalogOutFrequencySet(hdwf, c_int(0), c_double(3000))
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
+
+print("Configure analog in")
+dwf.FDwfAnalogInFrequencySet(hdwf, c_double(1000000))
+print("Set range for all channels")
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(-1), c_double(4))
+dwf.FDwfAnalogInBufferSizeSet(hdwf, c_int(1000))
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0))
+
+print("Wait after first device opening the analog in offset to stabilize")
+time.sleep(2)
+
+print("Starting acquisition...")
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(1))
+
+sts = c_int()
+while True:
+    dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+    if sts.value == DwfStateDone.value :
+        break
+    time.sleep(0.1)
+print("   done")
+
+rg = (c_double*1000)()
+dwf.FDwfAnalogInStatusData(hdwf, c_int(0), rg, len(rg)) # get channel 1 data
+#dwf.FDwfAnalogInStatusData(hdwf, c_int(1), rg, len(rg)) # get channel 2 data
+
+dwf.FDwfAnalogOutReset(hdwf, c_int(0))
+dwf.FDwfDeviceCloseAll()
+
+dc = sum(rg)/len(rg)
+print("DC: "+str(dc)+"V")
+
+plt.plot(numpy.fromiter(rg, dtype = numpy.float))
+plt.show()
+
diff --git a/tests/py/AnalogOutIn_PlayRecord.py b/tests/py/AnalogOutIn_PlayRecord.py
new file mode 100644
index 0000000000000000000000000000000000000000..2d9a81b565918bcdddb50f9c1f39050b0d3097b2
--- /dev/null
+++ b/tests/py/AnalogOutIn_PlayRecord.py
@@ -0,0 +1,176 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2019-07-23
+
+   Requires:                       
+       Python 2.7, 3
+   Description:
+   Play mono WAV file on AWG1 channel 1
+   Record to stereo WAV file from Scope 1 and 2
+"""
+
+from dwfconstants import *
+import ctypes
+import sys
+import wave
+import numpy
+
+
+print("Load audio.wav file")
+play = wave.open('audio.wav', "rb")
+channels = play.getnchannels()
+rate = play.getframerate()
+width = play.getsampwidth()
+length = play.getnframes()
+data_raw = play.readframes(length)
+print("Rate: "+str(rate))
+print("Size: "+str(length))
+print("Channels: "+str(length))
+print("Type: " +str(type))
+# AnalogOut expects double normalized to +/-1 value
+data_array = numpy.fromiter(data_raw, dtype = numpy.float64)
+if width == 1 :
+    print("Scaling: UINT8")
+    data_array /= 128.0
+    data_array -= 1.0
+elif numpy.dtype(data[0]) == numpy.int16 :
+    print("Scaling: INT16")
+    data_array /= 32768.0
+elif numpy.dtype(data[0]) == numpy.int32 :
+    print("Scaling: INT32")
+    data_array /= 2147483648.0
+data = (ctypes.c_double * length)(*data_array)
+sRun = 1.0*length/rate
+# plt.plot(data)
+# plt.show()
+
+
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+hdwf = c_int()
+print("Opening first device...")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("Failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+print("Staring record...")
+iRecord = 0
+record1 = (c_int16*length)()
+record2 = (c_int16*length)()
+#set up acquisition
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1)) # channel 1
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(1), c_int(1)) # channel 2
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(-1), c_double(5.0))
+dwf.FDwfAnalogInChannelOffsetSet(hdwf, c_int(-1), c_double(0))
+dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord)
+dwf.FDwfAnalogInFrequencySet(hdwf, c_double(rate))
+dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(sRun))
+dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(0))
+dwf.FDwfAnalogInTriggerSourceSet(hdwf, trigsrcAnalogOut1)
+dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
+
+
+print("Playing audio...")
+iPlay = 0
+channel = c_int(0) # AWG 1
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, channel, 0, c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, channel, 0, funcPlay)
+dwf.FDwfAnalogOutRepeatSet(hdwf, channel, c_int(1))
+print("Length: "+str(sRun))
+dwf.FDwfAnalogOutRunSet(hdwf, channel, c_double(sRun))
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, channel, 0, c_double(rate))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel, 0, c_double(2.0))
+# prime the buffer with the first chunk of data
+cBuffer = c_int(0)
+dwf.FDwfAnalogOutNodeDataInfo(hdwf, channel, 0, 0, byref(cBuffer))
+if cBuffer.value > length : cBuffer.value = length
+dwf.FDwfAnalogOutNodeDataSet(hdwf, channel, 0, data, cBuffer)
+iPlay += cBuffer.value
+dwf.FDwfAnalogOutConfigure(hdwf, channel, c_int(1))
+
+
+dataLost = c_int(0)
+dataFree = c_int(0)
+dataAvailable = c_int(0)
+dataCorrupted = c_int(0)
+sts = c_ubyte(0)
+totalLost = 0
+totalCorrupted = 0
+
+# loop to send out and read in data chunks
+while iRecord < length :
+    if dwf.FDwfAnalogOutStatus(hdwf, channel, byref(sts)) != 1: # handle error
+        print("Error")
+        szerr = create_string_buffer(512)
+        dwf.FDwfGetLastErrorMsg(szerr)
+        print(szerr.value)
+        break
+    
+    # play, analog out data chunk
+    if sts.value == DwfStateRunning.value and iPlay < length :  # running and more data to stream
+        dwf.FDwfAnalogOutNodePlayStatus(hdwf, channel, 0, byref(dataFree), byref(dataLost), byref(dataCorrupted))
+        totalLost += dataLost.value
+        totalCorrupted += dataCorrupted.value
+        if iPlay + dataFree.value > length : # last chunk might be less than the free buffer size
+            dataFree.value = length - iPlay
+        if dataFree.value > 0 : 
+            if dwf.FDwfAnalogOutNodePlayData(hdwf, channel, 0, byref(data, iPlay*8), dataFree) != 1: # offset for double is *8 (bytes) 
+                print("Error")
+                break
+            iPlay += dataFree.value
+    
+    if dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts)) != 1: # handle error
+        print("Error")
+        szerr = create_string_buffer(512)
+        dwf.FDwfGetLastErrorMsg(szerr)
+        print(szerr.value)
+        break
+    
+    # record, analog in data chunk
+    if sts.value == DwfStateRunning.value or sts.value == DwfStateDone.value : # recording or done
+        dwf.FDwfAnalogInStatusRecord(hdwf, byref(dataAvailable), byref(dataLost), byref(dataCorrupted))
+        iRecord += dataLost.value
+        totalLost += dataLost.value
+        totalCorrupted += dataCorrupted.value
+        if dataAvailable.value > 0 :
+            if iRecord+dataAvailable.value > length :
+                dataAvailable = c_int(length-iRecord)
+            dwf.FDwfAnalogInStatusData16(hdwf, c_int(0), byref(record1, 2*iRecord), c_int(0), dataAvailable) # get channel 1 data chunk, offset for 16bit data is 2*
+            dwf.FDwfAnalogInStatusData16(hdwf, c_int(1), byref(record2, 2*iRecord), c_int(0), dataAvailable) # get channel 2 data chunk
+            iRecord += dataAvailable.value
+
+
+print("Lost: "+str(totalLost))
+print("Corrupted: "+str(totalCorrupted))
+print("done")
+dwf.FDwfAnalogOutReset(hdwf, channel)
+dwf.FDwfDeviceClose(hdwf)
+
+
+print("Writing record.wav file");
+record = wave.open('record.wav', "wb");
+record.setnchannels(2);				# 2 channels 
+record.setsampwidth(2);				# 16 bit / sample
+record.setframerate(rate);
+record.setcomptype("NONE", "No compression");
+record.writeframesraw(numpy.dstack((record1, record2)))
+print("done")
diff --git a/tests/py/AnalogOutIn_Synchronization.py b/tests/py/AnalogOutIn_Synchronization.py
new file mode 100644
index 0000000000000000000000000000000000000000..8e5a9e3ad51fa526808f2efcc755e1bb26ada9e2
--- /dev/null
+++ b/tests/py/AnalogOutIn_Synchronization.py
@@ -0,0 +1,116 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import sys
+import time
+import matplotlib.pyplot as plt
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+rghdwf = []
+cChannel = c_int()
+cDevices = c_int()
+voltage = c_double();
+sts = c_byte()
+cSamples = 8192
+rgdSamples = (c_double*cSamples)()
+
+# declare string variables
+devicename = create_string_buffer(64)
+serialnum = create_string_buffer(16)
+
+# print(DWF version
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# enumerate connected devices
+dwf.FDwfEnum(c_int(0), byref(cDevices))
+if cDevices.value == 0:
+    print("No device found")
+    dwf.FDwfDeviceCloseAll()
+    sys.exit(0)
+    
+print("Number of Devices: "+str(cDevices.value))
+
+# open devices
+for iDevice in range(0, cDevices.value):
+    dwf.FDwfEnumDeviceName(c_int(iDevice), devicename)
+    dwf.FDwfEnumSN(c_int(iDevice), serialnum)
+    print("------------------------------")
+    print("Device "+str(iDevice+1)+" : \t" + str(devicename.value) + "\t" + str(serialnum.value))
+    dwf.FDwfDeviceOpen(c_int(iDevice), byref(hdwf))
+    if hdwf.value == 0:
+        szerr = create_string_buffer(512)
+        dwf.FDwfGetLastErrorMsg(szerr)
+        print(str(szerr.value))
+        dwf.FDwfDeviceCloseAll()
+        sys.exit(0)
+    
+    # the device will only be configured when FDwf###Configure is called
+    dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+    
+    rghdwf.append(hdwf.value)
+        
+    dwf.FDwfAnalogInFrequencySet(hdwf, c_double(1e8))
+    dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(-1), c_int(1)) 
+    dwf.FDwfAnalogInChannelOffsetSet(hdwf, c_int(-1), c_double(0)) 
+    dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(-1), c_double(5)) 
+    dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(cSamples*4/10/1e8)) # 0 is middle, 4/10 = 10%
+    # trigger source external trigger 1
+    dwf.FDwfAnalogInTriggerSourceSet(hdwf, c_byte(11)) # 11 = trigsrcExternal1, T1
+    dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0)) 
+
+    if iDevice == 0:
+        # trigger output on external trigger 2 of analog-out (AWG) 1 
+        dwf.FDwfDeviceTriggerSet(hdwf, c_int(0), c_byte(7)) # 0 = T1 , 7 = trigsrcAnalogOut1
+        dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(0), c_int(1))
+        dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(0), c_byte(1)) # funcSine
+        dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(0), c_double(5e4))
+        dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(0), c_double(1.5))
+        dwf.FDwfAnalogOutNodeOffsetSet(hdwf, c_int(0), c_int(0), c_double(0))
+
+# wait at least 2 seconds for the device offset to stabilize
+time.sleep(2)
+
+# start analog-in (Scope)
+for iDevice in range(len(rghdwf)):
+    hdwf.value = rghdwf[iDevice]
+    dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
+
+print("This example expects Trigger 1 of each device to be connected together for synchronization triggering!")
+for iAcq in range(0, 1):
+    hdwf.value = rghdwf[0]
+    dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1)) # start analog-out (AWG) 1 of first device
+    
+    for iDevice in range(len(rghdwf)):
+        hdwf.value = rghdwf[iDevice]
+        while True:
+            dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+            if sts.value == 2 : # DwfStateDone
+                break
+            time.sleep(0.1)
+        
+        dwf.FDwfAnalogInChannelCount(hdwf, byref(cChannel)) 
+        for iChannel in range(0, cChannel.value):
+            dwf.FDwfAnalogInStatusData(hdwf, c_int(iChannel), rgdSamples, c_int(cSamples)) # get channel 1 data
+
+            plt.plot(numpy.fromiter(rgdSamples, dtype = numpy.float))
+            
+    plt.show()
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/AnalogOut_Custom.py b/tests/py/AnalogOut_Custom.py
new file mode 100644
index 0000000000000000000000000000000000000000..8369937031577bc0914bbe8e35624634b759b6e8
--- /dev/null
+++ b/tests/py/AnalogOut_Custom.py
@@ -0,0 +1,66 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hzFreq = 1e4
+cSamples = 4096
+hdwf = c_int()
+rgdSamples = (c_double*cSamples)()
+channel = c_int(0)
+
+# samples between -1 and +1
+for i in range(0,len(rgdSamples)):
+    rgdSamples[i] = 1.0*i/cSamples;
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# without this the outputs stops on close
+dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown
+
+#open device
+"Opening first device..."
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+print("Generating custom waveform...")
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, channel, AnalogOutNodeCarrier, c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, channel, AnalogOutNodeCarrier, funcCustom) 
+dwf.FDwfAnalogOutNodeDataSet(hdwf, channel, AnalogOutNodeCarrier, rgdSamples, c_int(cSamples))
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, channel, AnalogOutNodeCarrier, c_double(hzFreq)) 
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel, AnalogOutNodeCarrier, c_double(2.0)) 
+
+dwf.FDwfAnalogOutRunSet(hdwf, channel, c_double(2.0/hzFreq)) # run for 2 periods
+dwf.FDwfAnalogOutWaitSet(hdwf, channel, c_double(1.0/hzFreq)) # wait one pulse time
+dwf.FDwfAnalogOutRepeatSet(hdwf, channel, c_int(3)) # repeat 5 times
+
+dwf.FDwfAnalogOutConfigure(hdwf, channel, c_int(1))
+
+print("Generating waveform...")
+
+dwf.FDwfAnalogOutReset(hdwf, channel)
+dwf.FDwfDeviceCloseAll() 
diff --git a/tests/py/AnalogOut_Pattern.py b/tests/py/AnalogOut_Pattern.py
new file mode 100644
index 0000000000000000000000000000000000000000..0fb645f3c03bd3b2548abcf4cdce282c085759a7
--- /dev/null
+++ b/tests/py/AnalogOut_Pattern.py
@@ -0,0 +1,65 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#declare ctype variables
+hdwf = c_int()
+
+#open device
+"Opening first device..."
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+hzRate = 1e6
+cSamples = 100
+channel = c_int(0)
+rgdSamples = (c_double*cSamples)()
+# samples between -1 and +1
+for i in range(0,cSamples):
+    if i % 2 == 0:
+        rgdSamples[i] = 0;
+    else:
+        rgdSamples[i] = 1.0*i/cSamples;
+
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, channel, AnalogOutNodeCarrier, c_int(1))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel, AnalogOutNodeCarrier, c_double(2.0)) 
+dwf.FDwfAnalogOutIdleSet(hdwf, channel, c_int(1)) # DwfAnalogOutIdleOffset
+
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, channel, AnalogOutNodeCarrier, funcPlayPattern)
+dwf.FDwfAnalogOutNodeDataSet(hdwf, channel, AnalogOutNodeCarrier, rgdSamples, cSamples)
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, channel, AnalogOutNodeCarrier, c_double(hzRate)) 
+dwf.FDwfAnalogOutRunSet(hdwf, channel, c_double(cSamples/hzRate)) # run for pattern duration
+dwf.FDwfAnalogOutRepeatSet(hdwf, channel, c_int(1)) # repeat once
+
+dwf.FDwfAnalogOutConfigure(hdwf, channel, c_int(1))
+
+print("Generating pattern...")
+time.sleep(5)
+
+print("done")
+dwf.FDwfAnalogOutReset(hdwf, channel)
+dwf.FDwfDeviceCloseAll() 
diff --git a/tests/py/AnalogOut_Play.py b/tests/py/AnalogOut_Play.py
new file mode 100644
index 0000000000000000000000000000000000000000..e42f6b36107018d47a32308026bbd5a204558074
--- /dev/null
+++ b/tests/py/AnalogOut_Play.py
@@ -0,0 +1,122 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+import numpy as np
+import scipy.io.wavfile
+import matplotlib.pyplot as plt
+import ctypes
+from ctypes import *
+import sys
+
+print("Load audio.WAV file")
+rate, data = scipy.io.wavfile.read('audio.wav')
+print("Rate: "+str(rate))
+print("Size: "+str(data.size))
+print("Type: " +str(np.dtype(data[0])))
+# AnalogOut expects double normalized to +/-1 value
+dataf = data.astype(np.float64)
+if np.dtype(data[0]) == np.int8 or np.dtype(data[0]) == np.uint8 :
+    print("Scaling: UINT8")
+    dataf /= 128.0
+    dataf -= 1.0
+elif np.dtype(data[0]) == np.int16 :
+    print("Scaling: INT16")
+    dataf /= 32768.0
+elif np.dtype(data[0]) == np.int32 :
+    print("Scaling: INT32")
+    dataf /= 2147483648.0
+data_c = (ctypes.c_double * len(dataf))(*dataf)
+plt.plot(data)
+plt.show()
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+# declare ctype variables
+hdwf = c_int()
+channel = c_int(0) # AWG 1
+
+# print(DWF version
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# open device
+print("Opening first device...")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("Failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+print("Playing audio...")
+iPlay = 0
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, channel, 0, c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, channel, 0, c_int(31)) #funcPlay
+dwf.FDwfAnalogOutRepeatSet(hdwf, channel, c_int(1))
+sRun = 1.0*data.size/rate
+print("Length: "+str(sRun))
+dwf.FDwfAnalogOutRunSet(hdwf, channel, c_double(sRun))
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, channel, 0, c_double(rate))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel, 0, c_double(1.0))
+# prime the buffer with the first chunk of data
+cBuffer = c_int(0)
+dwf.FDwfAnalogOutNodeDataInfo(hdwf, channel, 0, 0, byref(cBuffer))
+if cBuffer.value > data.size : cBuffer.value = data.size
+dwf.FDwfAnalogOutNodeDataSet(hdwf, channel, 0, data_c, cBuffer)
+iPlay += cBuffer.value
+dwf.FDwfAnalogOutConfigure(hdwf, channel, c_int(1))
+
+dataLost = c_int(0)
+dataFree = c_int(0)
+dataCorrupted = c_int(0)
+sts = c_ubyte(0)
+totalLost = 0
+totalCorrupted = 0
+
+while True :
+    # fetch analog in info for the channel
+    if dwf.FDwfAnalogOutStatus(hdwf, channel, byref(sts)) != 1:
+        print("Error")
+        szerr = create_string_buffer(512)
+        dwf.FDwfGetLastErrorMsg(szerr)
+        print(szerr.value)
+        break
+    
+    if sts.value != 3: break # not running !DwfStateRunning
+    if iPlay >= data.size : continue # no more data to stream
+
+    dwf.FDwfAnalogOutNodePlayStatus(hdwf, channel, 0, byref(dataFree), byref(dataLost), byref(dataCorrupted))
+    totalLost += dataLost.value
+    totalCorrupted += dataCorrupted.value
+
+    if iPlay + dataFree.value > data.size : # last chunk might be less than the free buffer size
+        dataFree.value = data.size - iPlay
+    if dataFree.value == 0 : continue
+    if dwf.FDwfAnalogOutNodePlayData(hdwf, channel, 0, byref(data_c, iPlay*8), dataFree) != 1: # offset for double is *8 (bytes) 
+        print("Error")
+        break
+    iPlay += dataFree.value
+
+print("Lost: "+str(totalLost))
+print("Corrupted: "+str(totalCorrupted))
+
+print("done")
+dwf.FDwfAnalogOutReset(hdwf, channel)
+dwf.FDwfDeviceClose(hdwf)
\ No newline at end of file
diff --git a/tests/py/AnalogOut_Pulse.py b/tests/py/AnalogOut_Pulse.py
new file mode 100644
index 0000000000000000000000000000000000000000..1e36dce80b087ba2190a43e6e96eb52f5fa19aad
--- /dev/null
+++ b/tests/py/AnalogOut_Pulse.py
@@ -0,0 +1,58 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2019-10-16
+
+   Requires:                       
+       Python 2.7, 3
+   Generate a single given lenght pulse
+"""
+
+from ctypes import *
+from dwfconstants import *
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+channel = c_int(0)
+pulse = 510e-9
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# without this the outputs stops on close
+dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown
+
+#open device
+print("Opening first device...")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, channel, AnalogOutNodeCarrier, c_int(1))
+dwf.FDwfAnalogOutIdleSet(hdwf, channel, DwfAnalogOutIdleOffset)
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, channel, AnalogOutNodeCarrier, funcSquare)
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, channel, AnalogOutNodeCarrier, c_double(0)) # low frequency
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel, AnalogOutNodeCarrier, c_double(3.3))
+dwf.FDwfAnalogOutNodeOffsetSet(hdwf, channel, AnalogOutNodeCarrier, c_double(0))
+dwf.FDwfAnalogOutRunSet(hdwf, channel, c_double(pulse)) # pulse length
+dwf.FDwfAnalogOutWaitSet(hdwf, channel, c_double(0)) # wait length
+dwf.FDwfAnalogOutRepeatSet(hdwf, channel, c_int(1)) # repeat once
+
+print("Generating pulse")
+dwf.FDwfAnalogOutConfigure(hdwf, channel, c_int(1))
+
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/AnalogOut_Sine.py b/tests/py/AnalogOut_Sine.py
new file mode 100644
index 0000000000000000000000000000000000000000..9a5b449a070c7287e284303f1792e6cfdafca641
--- /dev/null
+++ b/tests/py/AnalogOut_Sine.py
@@ -0,0 +1,53 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import time
+from dwfconstants import *
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+channel = c_int(0)
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# prevent temperature drift
+dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown
+
+#open device
+print("Opening first device...")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, channel, AnalogOutNodeCarrier, c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, channel, AnalogOutNodeCarrier, funcSine)
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, channel, AnalogOutNodeCarrier, c_double(1000))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel, AnalogOutNodeCarrier, c_double(1.41))
+dwf.FDwfAnalogOutNodeOffsetSet(hdwf, channel, AnalogOutNodeCarrier, c_double(1.41))
+
+print("Generating sine wave...")
+dwf.FDwfAnalogOutConfigure(hdwf, channel, c_int(1))
+
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/AnalogOut_Sweep.py b/tests/py/AnalogOut_Sweep.py
new file mode 100644
index 0000000000000000000000000000000000000000..6ee7b91965a2b882102b76d2aaf2b47fce37d954
--- /dev/null
+++ b/tests/py/AnalogOut_Sweep.py
@@ -0,0 +1,108 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import time
+from dwfconstants import *
+import sys
+import matplotlib.pyplot as plt
+import numpy
+
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+# continue running after device close, prevent temperature drifts
+dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown
+
+#print(DWF version
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+hdwf = c_int()
+print("Opening first device...")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+hzStart = 1e3
+hzStop = 20e3
+hzMid = (hzStart+hzStop)/2
+secSweep = 5e-3
+channel = c_int(0)
+
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, channel, AnalogOutNodeCarrier, c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, channel, AnalogOutNodeCarrier, funcSine)
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, channel, AnalogOutNodeCarrier, c_double(hzMid))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel, AnalogOutNodeCarrier, c_double(1.0))
+dwf.FDwfAnalogOutNodeOffsetSet(hdwf, channel, AnalogOutNodeCarrier, c_double(0.0))
+
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, channel, AnalogOutNodeFM, c_int(1))
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, channel, AnalogOutNodeFM, funcRampUp)
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, channel, AnalogOutNodeFM, c_double(1.0/secSweep))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel, AnalogOutNodeFM, c_double(100.0*(hzStop-hzMid)/hzMid))
+dwf.FDwfAnalogOutNodeSymmetrySet(hdwf, channel, AnalogOutNodeFM, c_double(100.0))
+
+dwf.FDwfAnalogOutRunSet(hdwf, channel, c_double(secSweep))
+dwf.FDwfAnalogOutRepeatSet(hdwf, channel, c_int(1))
+
+
+hzRate = 1e6 
+cSamples = 8*1024
+rgdSamples1 = (c_double*cSamples)()
+rgdSamples2 = (c_double*cSamples)()
+sts = c_int()
+
+print("Configure analog in")
+dwf.FDwfAnalogInFrequencySet(hdwf, c_double(hzRate))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(-1), c_double(4))
+dwf.FDwfAnalogInBufferSizeSet(hdwf, c_int(cSamples))
+dwf.FDwfAnalogInTriggerSourceSet(hdwf, trigsrcAnalogOut1) 
+dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(0.3*cSamples/hzRate)) # trigger position at 20%, 0.5-0.3
+
+print("Starting acquisition...")
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(1))
+
+while True:
+    dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+    if sts.value == DwfStateArmed.value :
+        break
+    time.sleep(0.1)
+print("   armed")
+
+time.sleep(2.0) # wait for the offsets to stabilize
+
+dwf.FDwfAnalogOutConfigure(hdwf, channel, c_int(1))
+
+while True:
+    dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+    if sts.value == DwfStateDone.value :
+        break
+    time.sleep(0.1)
+print("   done")
+
+dwf.FDwfAnalogInStatusData(hdwf, c_int(0), rgdSamples1, len(rgdSamples1)) # get channel 1 data
+dwf.FDwfAnalogInStatusData(hdwf, c_int(1), rgdSamples2, len(rgdSamples2)) # get channel 2 data
+
+
+dwf.FDwfDeviceCloseAll()
+
+plt.plot(numpy.linspace(0, cSamples-1, cSamples), numpy.fromiter(rgdSamples1, dtype = numpy.float), numpy.linspace(0, cSamples-1, cSamples), numpy.fromiter(rgdSamples2, dtype = numpy.float))
+plt.show()
diff --git a/tests/py/AnalogOut_Sync.py b/tests/py/AnalogOut_Sync.py
new file mode 100644
index 0000000000000000000000000000000000000000..94d96ccbd2bef41fd4bc3c71c0fe8ac5f37f2ed4
--- /dev/null
+++ b/tests/py/AnalogOut_Sync.py
@@ -0,0 +1,64 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import time
+from dwfconstants import *
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# continue running after device close, prevent temperature drifts
+dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown
+
+#open device
+print("Opening first device...")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+# enable two channels
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), AnalogOutNodeCarrier, c_int(True))
+dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(1), AnalogOutNodeCarrier, c_int(True))
+# for second channel set master the first channel
+dwf.FDwfAnalogOutMasterSet(hdwf, c_int(1), c_int(0));
+# slave channel is controlled by the master channel
+# it is enough to set trigger, wait, run and repeat paramters for master channel
+
+# configure enabled channels
+dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(-1), AnalogOutNodeCarrier, funcSine)
+dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(-1), AnalogOutNodeCarrier, c_double(1000.0))
+dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(-1), AnalogOutNodeCarrier, c_double(1.0))
+
+#set phase for second channel
+dwf.FDwfAnalogOutNodePhaseSet(hdwf, c_int(1), AnalogOutNodeCarrier, c_double(180.0))
+
+print("Generating sine wave")
+# start signal generation, 
+# the second, slave channel will start too
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
+
+dwf.FDwfAnalogOutReset(hdwf, c_int(-1))
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/Analog_Transistor.py b/tests/py/Analog_Transistor.py
new file mode 100644
index 0000000000000000000000000000000000000000..e02470e2d9469239d82b65193d95defbdc9f7e32
--- /dev/null
+++ b/tests/py/Analog_Transistor.py
@@ -0,0 +1,108 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2020-12-09
+
+   Requires:                       
+       Python 2.7, 3
+   NPN transistor test
+"""
+
+from ctypes import *
+import time
+from dwfconstants import *
+import sys
+import matplotlib.pyplot as plt
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("Version: "+str(version.value))
+
+cdevices = c_int()
+dwf.FDwfEnum(c_int(0), byref(cdevices))
+print("Number of Devices: "+str(cdevices.value))
+
+if cdevices.value == 0:
+    print("no device detected")
+    quit()
+
+dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown
+
+print("Opening first device")
+hdwf = c_int()
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # 0 = the device will only be configured when FDwf###Configure is called
+
+print("Configuring device...")
+# collector: 0V to 5V triangle output and 50Hz, 20ms
+dwf.FDwfAnalogOutEnableSet(hdwf, c_int(0), c_int(1)) 
+dwf.FDwfAnalogOutFunctionSet(hdwf, c_int(0), funcTriangle)
+dwf.FDwfAnalogOutPhaseSet(hdwf, c_int(0), c_double(270.0))
+dwf.FDwfAnalogOutFrequencySet(hdwf, c_int(0), c_double(50))
+dwf.FDwfAnalogOutOffsetSet(hdwf, c_int(0), c_double(2.5))
+dwf.FDwfAnalogOutAmplitudeSet(hdwf, c_int(0), c_double(2.5))
+dwf.FDwfAnalogOutMasterSet(hdwf, c_int(0), c_int(1));
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(0))
+
+# base: 1V to 2V in 5 steps at 10Hz, 100ms total length
+dwf.FDwfAnalogOutEnableSet(hdwf, c_int(1), c_int(1)) 
+dwf.FDwfAnalogOutFunctionSet(hdwf, c_int(1), funcCustom)
+dwf.FDwfAnalogOutFrequencySet(hdwf, c_int(1), c_double(10))
+dwf.FDwfAnalogOutOffsetSet(hdwf, c_int(1), c_double(1.5))
+dwf.FDwfAnalogOutAmplitudeSet(hdwf, c_int(1), c_double(0.5))
+# values normalized to +-1 
+rgSteps = (c_double*5)(-1.0, -0.5, 0, 0.5, 1.0)
+dwf.FDwfAnalogOutDataSet(hdwf, c_int(1), rgSteps, c_int(len(rgSteps)))
+dwf.FDwfAnalogOutRunSet(hdwf, c_int(1), c_double(0.1))
+dwf.FDwfAnalogOutRepeatSet(hdwf, c_int(1), c_int(1))
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(1), c_int(0))
+
+# scope: 5000 samples at 50kHz, 100ms
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(1), c_int(1))
+dwf.FDwfAnalogInFrequencySet(hdwf, c_double(50e3))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(10.0))
+dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(1), c_double(10.0))
+dwf.FDwfAnalogInBufferSizeSet(hdwf, c_int(5000))
+dwf.FDwfAnalogInTriggerSourceSet(hdwf, trigsrcAnalogOut2) 
+dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(0.05)) # 5ms, trigger at first sample
+dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0))
+
+print("Wait for the offset to stabilize...")
+time.sleep(1)
+
+print("Starting test...")
+dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
+dwf.FDwfAnalogOutConfigure(hdwf, c_int(1), c_int(1))
+
+sts = c_int()
+while True:
+    dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+    if sts.value == DwfStateDone.value :
+        break
+    time.sleep(0.001)
+print("done")
+
+rgc1 = (c_double*5000)()
+rgc2 = (c_double*5000)()
+dwf.FDwfAnalogInStatusData(hdwf, c_int(0), rgc1, len(rgc1)) # get channel 1 data
+dwf.FDwfAnalogInStatusData(hdwf, c_int(1), rgc2, len(rgc2)) # get channel 2 data
+
+dwf.FDwfDeviceCloseAll()
+
+plt.plot(numpy.fromiter(rgc2, dtype = numpy.float), numpy.fromiter(rgc1, dtype = numpy.float))
+plt.show()
+
diff --git a/tests/py/Device_Enumeration.py b/tests/py/Device_Enumeration.py
new file mode 100644
index 0000000000000000000000000000000000000000..ce9e73647b46b4fbd279669bc92ea40a888261ec
--- /dev/null
+++ b/tests/py/Device_Enumeration.py
@@ -0,0 +1,83 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import sys
+from dwfconstants import *
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+#check library loading errors
+szerr = create_string_buffer(512)
+dwf.FDwfGetLastErrorMsg(szerr)
+if szerr[0] != b'\0':
+    print(str(szerr.value))
+
+#declare ctype variables
+hdwf = c_int()
+cDevice = c_int()
+cConfig = c_int()
+cInfo = c_int()
+iDevId = c_int()
+iDevRev = c_int()
+
+#declare string variables
+devicename = create_string_buffer(64)
+serialnum = create_string_buffer(16)
+
+#print DWF version
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#enumerate and print device information
+dwf.FDwfEnum(enumfilterAll, byref(cDevice))
+#dwf.FDwfEnum(devidDiscovery2, byref(cDevice)) only Analog Discovery 2 devices
+#dwf.FDwfEnum(c_int(enumfilterType.value|enumfilterUSB.value), byref(cDevice)) # only USB devices
+print("Number of Devices: "+str(cDevice.value))
+
+for iDev in range(0, cDevice.value):
+    dwf.FDwfEnumDeviceName (c_int(iDev), devicename)
+    dwf.FDwfEnumSN (c_int(iDev), serialnum)
+    dwf.FDwfEnumDeviceType (c_int(iDev), byref(iDevId), byref(iDevRev))
+    others = create_string_buffer(128)
+    print("------------------------------")
+    print("Device "+str(iDev)+" : ")
+    print("\tName: " + str(devicename.value.decode()) + " " + str(serialnum.value.decode()))
+    print("\tID: "+str(iDevId.value)+" rev: "+chr(0x40+(iDevRev.value&0xF))+" "+hex(iDevRev.value)) # LSbits of rev represent 1=A, 2=B
+
+    print("\tConfigurations:")
+    dwf.FDwfEnumConfig(c_int(iDev), byref(cConfig))
+    for iCfg in range (0, cConfig.value):
+        sz = "\t"+str(iCfg)+"."
+        dwf.FDwfEnumConfigInfo(c_int(iCfg), c_int(1), byref(cInfo)) # DECIAnalogInChannelCount
+        sz += " AnalogIn: "+str(cInfo.value)
+        dwf.FDwfEnumConfigInfo(c_int(iCfg), c_int(7), byref(cInfo)) # DECIAnalogInBufferSize
+        sz += " x "+str(cInfo.value)
+        dwf.FDwfEnumConfigInfo(c_int(iCfg), c_int(2), byref(cInfo)) # DECIAnalogOutChannelCount
+        sz += " \tAnalogOut: "+str(cInfo.value)
+        dwf.FDwfEnumConfigInfo(c_int(iCfg), c_int(8), byref(cInfo)) # DECIAnalogOutBufferSize
+        sz += " x "+str(cInfo.value)
+        dwf.FDwfEnumConfigInfo(c_int(iCfg), c_int(4), byref(cInfo)) # DECIDigitalInChannelCount
+        sz += " \tDigitalIn: "+str(cInfo.value)
+        dwf.FDwfEnumConfigInfo(c_int(iCfg), c_int(9), byref(cInfo)) # DECIDigitalInBufferSize
+        sz += " x "+str(cInfo.value)
+        dwf.FDwfEnumConfigInfo(c_int(iCfg), c_int(5), byref(cInfo)) # DECIDigitalOutChannelCount
+        sz += " \tDigitalOut: "+str(cInfo.value)
+        dwf.FDwfEnumConfigInfo(c_int(iCfg), c_int(10), byref(cInfo)) # DECIDigitalOutBufferSize
+        sz += " x "+str(cInfo.value)
+        dwf.FDwfEnumConfigInfo(c_int(iCfg), c_int(-2), byref(others)) # other text info
+        szothers = str(others.value.decode())
+        if len(szothers) > 1 : sz += " \t"+szothers
+        print(sz)
diff --git a/tests/py/Device_Info.py b/tests/py/Device_Info.py
new file mode 100644
index 0000000000000000000000000000000000000000..0dda10bd4df11b14fcd24bfd6795241ff2cdc69a
--- /dev/null
+++ b/tests/py/Device_Info.py
@@ -0,0 +1,178 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+# check library loading errors
+szerr = create_string_buffer(512)
+dwf.FDwfGetLastErrorMsg(szerr)
+if szerr[0] != b'\0':
+    print(str(szerr.value))
+
+# declare variables
+hdwf = c_int()
+int0 = c_int()
+int1 = c_int()
+uint0 = c_uint()
+dbl0 = c_double()
+dbl1 = c_double()
+dbl2 = c_double()
+sz0 = create_string_buffer(256)
+sz1 = create_string_buffer(256)
+cDevice = c_int()
+cChannel = c_int()
+cNode = c_int()
+rgszAnalogOutNode = ["Carrier", "FM", "AM"]
+
+# declare string variables
+devicename = create_string_buffer(64)
+serialnum = create_string_buffer(16)
+
+# print(DWF version
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# enumerate connected devices
+dwf.FDwfEnum(c_int(0), byref(cDevice))
+print("Number of Devices: "+str(cDevice.value))
+
+# open devices
+for iDevice in range(0, cDevice.value):
+    dwf.FDwfEnumDeviceName(c_int(iDevice), devicename)
+    dwf.FDwfEnumSN(c_int(iDevice), serialnum)
+    print("------------------------------")
+    print("Device "+str(iDevice+1)+" : ")
+    print("\t" + str(devicename.value))
+    print("\t" + str(serialnum.value))
+    dwf.FDwfDeviceOpen(c_int(iDevice), byref(hdwf))
+    if hdwf.value == 0:
+        szerr = create_string_buffer(512)
+        dwf.FDwfGetLastErrorMsg(szerr)
+        print(szerr.value)
+        continue
+    
+    print("")
+    dwf.FDwfAnalogInChannelCount(hdwf, byref(int0))
+    print("AnalogIn channels: "+str(int0.value))
+
+    dwf.FDwfAnalogInBufferSizeInfo(hdwf, 0, byref(int0))
+    print(" Buffer size: "+str(int0.value))
+
+    dwf.FDwfAnalogInBitsInfo(hdwf, byref(int0))
+    print(" ADC bits: "+str(int0.value))
+
+    dwf.FDwfAnalogInChannelRangeInfo(hdwf, byref(dbl0), byref(dbl1), byref(dbl2))
+    print(" Range from "+str(dbl0.value)+" to "+str(dbl1.value)+" in "+str(dbl2.value)+" steps")
+
+    dwf.FDwfAnalogInChannelOffsetInfo(hdwf, byref(dbl0), byref(dbl1), byref(dbl2))
+    print(" Offset from "+str(dbl0.value)+" to "+str(dbl1.value)+" in "+str(dbl2.value)+" steps")
+
+    
+    print("")
+    dwf.FDwfAnalogOutCount(hdwf, byref(cChannel))
+    print("AnalogOut channels: "+str(cChannel.value))
+    
+    for iChannel in range(0, cChannel.value):
+        print(" Channel "+str(iChannel+1))
+
+        fsnodes = c_int()
+        dwf.FDwfAnalogOutNodeInfo(hdwf, c_int(iChannel), byref(fsnodes))
+
+        for iNode in range(0, 2):
+            if (fsnodes.value & (1<<iNode)) == 0:  # bits: AM | FM | Carrier
+                continue
+                
+            print("  Node: "+rgszAnalogOutNode[iNode])
+
+            dwf.FDwfAnalogOutNodeDataInfo(hdwf, iChannel, iNode, 0, byref(int0))
+            print("   Buffer size: "+str(int0.value))
+            
+            dwf.FDwfAnalogOutNodeAmplitudeInfo(hdwf, iChannel, iNode, byref(dbl0), byref(dbl1))
+            print("   Amplitude from "+str(dbl0.value)+" to "+str(dbl1.value))
+
+            dwf.FDwfAnalogOutNodeOffsetInfo(hdwf, iChannel, iNode, byref(dbl0), byref(dbl1))
+            print("   Offset from "+str(dbl0.value)+" to "+str(dbl1.value))
+
+            dwf.FDwfAnalogOutNodeFrequencyInfo(hdwf, iChannel, iNode, byref(dbl0), byref(dbl1))
+            print("   Frequency from "+str(dbl0.value)+" to "+str(dbl1.value))
+
+    print("")
+    dwf.FDwfAnalogIOChannelCount(hdwf, byref(cChannel))
+    print("AnalogIO channels: "+str(cChannel.value))
+
+    dwf.FDwfAnalogIOEnableInfo(hdwf, byref(int0), byref(int1))
+    print(" Master Enable: "+("Setting " if int0!=0 else "")+("Reading " if int1!=0 else ""))
+
+    for iChannel in range(0, cChannel.value):
+
+        dwf.FDwfAnalogIOChannelName(hdwf, iChannel, sz0, sz1)
+        print(" Channel "+str(iChannel+1)+" Name: "+str(sz0.value)+" Label: "+str(sz1.value))
+
+        dwf.FDwfAnalogIOChannelInfo(hdwf, iChannel, byref(cNode))
+        
+        for iNode in range(0, cNode.value):
+            dwf.FDwfAnalogIOChannelNodeName(hdwf, iChannel, iNode, sz0, sz1)
+            print("  Node "+str(iNode+1)+" Name: "+str(sz0.value)+" Unit: "+str(sz1.value))
+
+            dwf.FDwfAnalogIOChannelNodeSetInfo(hdwf, iChannel, iNode, byref(dbl0), byref(dbl1), byref(int0))
+            if int0.value==1 :
+                if dbl0.value == dbl1.value  :
+                    print("   Constant output "+str(dbl0.value))
+                else:
+                    print("   Non settable range from "+str(dbl0)+" to "+str(dbl1))
+            elif int0.value>1 :
+                print("   Setting from "+str(dbl0.value)+" to "+str(dbl1.value)+" in "+str(int0.value)+" steps")
+
+            dwf.FDwfAnalogIOChannelNodeStatusInfo(hdwf, iChannel, iNode, byref(dbl0), byref(dbl1), byref(int0))
+            if int0.value==1 :
+                if dbl0.value == dbl1.value  :
+                    print("   Constant input "+str(dbl0.value))
+                else:
+                    print("   Input range from "+str(dbl0.value)+" to "+str(dbl1.value))
+            elif int0.value>1 :
+                print("   Reading from "+str(dbl0.value)+" to "+str(dbl1.value)+" in "+str(int0.value)+" steps")
+
+                
+    print("")
+    dwf.FDwfDigitalInBitsInfo(hdwf, byref(int0))
+    print("DigitalIn channels: "+str(int0.value))
+
+    dwf.FDwfDigitalInBufferSizeInfo(hdwf, byref(int0))
+    print(" Buffer size: "+str(int0.value))
+
+    
+    print("")
+    dwf.FDwfDigitalOutCount(hdwf, byref(int0))
+    print("DigitalOut channels: "+str(int0.value))
+
+    dwf.FDwfDigitalOutDataInfo(hdwf, c_int(0), byref(int0))
+    print(" Custom size: "+str(int0.value))
+
+    
+    print("")
+    print("DigitalIO information:")
+    dwf.FDwfDigitalIOOutputEnableInfo(hdwf, byref(uint0))
+    print(" OE Mask: "+hex(uint0.value))
+    dwf.FDwfDigitalIOOutputInfo(hdwf, byref(uint0))
+    print(" Output : "+hex(uint0.value))
+    dwf.FDwfDigitalIOInputInfo(hdwf, byref(uint0))
+    print(" Input  : "+hex(uint0.value))
+
+# ensure all devices are closed
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Device_InfoEx.py b/tests/py/Device_InfoEx.py
new file mode 100644
index 0000000000000000000000000000000000000000..f0a8e1af3a3a1c9f584fd6cbe15e069e08d5c8dd
--- /dev/null
+++ b/tests/py/Device_InfoEx.py
@@ -0,0 +1,178 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+# check library loading errors
+szerr = create_string_buffer(512)
+dwf.FDwfGetLastErrorMsg(szerr)
+if szerr[0] != b'\0':
+    print(str(szerr.value))
+
+# declare variables
+hdwf = c_int()
+int0 = c_int()
+int1 = c_int()
+uint0 = c_uint()
+dbl0 = c_double()
+dbl1 = c_double()
+dbl2 = c_double()
+sz0 = create_string_buffer(256)
+sz1 = create_string_buffer(256)
+cDevice = c_int()
+cChannel = c_int()
+cNode = c_int()
+rgszAnalogOutNode = ["Carrier", "FM", "AM"]
+
+# declare string variables
+devicename = create_string_buffer(64)
+serialnum = create_string_buffer(16)
+
+# print(DWF version
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# enumerate connected devices
+dwf.FDwfEnum(c_int(0), byref(cDevice))
+print("Number of Devices: "+str(cDevice.value))
+
+# open devices
+for iDevice in range(0, cDevice.value):
+    dwf.FDwfEnumDeviceName(c_int(iDevice), devicename)
+    dwf.FDwfEnumSN(c_int(iDevice), serialnum)
+    print("------------------------------")
+    print("Device "+str(iDevice+1)+" : ")
+    print("\t" + str(devicename.value))
+    print("\t" + str(serialnum.value))
+    print("Opening configuration 0 (1st)")
+    dwf.FDwfDeviceConfigOpen(c_int(iDevice), c_int(0), byref(hdwf))
+    if hdwf.value == 0:
+        szerr = create_string_buffer(512)
+        dwf.FDwfGetLastErrorMsg(szerr)
+        print(str(szerr.value))
+        continue
+    
+    print("")
+    dwf.FDwfAnalogInChannelCount(hdwf, byref(int0))
+    print("AnalogIn channels: "+str(int0.value))
+
+    dwf.FDwfAnalogInBufferSizeInfo(hdwf, 0, byref(int0))
+    print("Buffer size: "+str(int0.value))
+
+    dwf.FDwfAnalogInBitsInfo(hdwf, byref(int0))
+    print("ADC bits: "+str(int0.value))
+
+    dwf.FDwfAnalogInChannelRangeInfo(hdwf, byref(dbl0), byref(dbl1), byref(dbl2))
+    print("Range from "+str(dbl0.value)+" to "+str(dbl1.value)+" in "+str(dbl2.value)+" steps")
+
+    dwf.FDwfAnalogInChannelOffsetInfo(hdwf, byref(dbl0), byref(dbl1), byref(dbl2))
+    print("Offset from "+str(dbl0.value)+" to "+str(dbl1.value)+" in "+str(dbl2.value)+" steps")
+
+    
+    print("")
+    dwf.FDwfAnalogOutCount(hdwf, byref(cChannel))
+    print("AnalogOut channels: "+str(cChannel.value))
+    
+    for iChannel in range(0, cChannel.value):
+        print("Channel "+str(iChannel+1))
+
+        fsnodes = c_int()
+        dwf.FDwfAnalogOutNodeInfo(hdwf, c_int(iChannel), byref(fsnodes))
+
+        for iNode in range(0, 2):
+            if (fsnodes.value & (1<<iNode)) == 0:  # bits: AM | FM | Carrier
+                continue
+                
+            print("Node: "+rgszAnalogOutNode[iNode])
+
+            dwf.FDwfAnalogOutNodeDataInfo(hdwf, iChannel, iNode, 0, byref(int0))
+            print("Buffer size: "+str(int0.value))
+            
+            dwf.FDwfAnalogOutNodeAmplitudeInfo(hdwf, iChannel, iNode, byref(dbl0), byref(dbl1))
+            print("Amplitude from "+str(dbl0.value)+" to "+str(dbl1.value))
+
+            dwf.FDwfAnalogOutNodeOffsetInfo(hdwf, iChannel, iNode, byref(dbl0), byref(dbl1))
+            print("Offset from "+str(dbl0.value)+" to "+str(dbl1.value))
+
+            dwf.FDwfAnalogOutNodeFrequencyInfo(hdwf, iChannel, iNode, byref(dbl0), byref(dbl1))
+            print("Frequency from "+str(dbl0.value)+" to "+str(dbl1.value))
+
+    print("")
+    dwf.FDwfAnalogIOChannelCount(hdwf, byref(cChannel))
+    print("AnalogIO channels: "+str(cChannel.value))
+
+    dwf.FDwfAnalogIOEnableInfo(hdwf, byref(int0), byref(int1))
+    print("Master Enable: "+("Setting " if int0!=0 else "")+("Reading " if int1!=0 else ""))
+
+    for iChannel in range(0, cChannel.value):
+
+        dwf.FDwfAnalogIOChannelName(hdwf, iChannel, sz0, sz1)
+        print("Channel "+str(iChannel+1)+" Name: \""+str(sz0.value)+"\" Label: \""+str(sz1.value)+"\"")
+
+        dwf.FDwfAnalogIOChannelInfo(hdwf, iChannel, byref(cNode))
+        
+        for iNode in range(0, cNode.value):
+            dwf.FDwfAnalogIOChannelNodeName(hdwf, iChannel, iNode, sz0, sz1)
+            print("Node "+str(iNode+1)+" Name: \""+str(sz0.value)+"\" Unit: \""+str(sz1.value)+"\"")
+
+            dwf.FDwfAnalogIOChannelNodeSetInfo(hdwf, iChannel, iNode, byref(dbl0), byref(dbl1), byref(int0))
+            if int0.value==1 :
+                if dbl0.value == dbl1.value  :
+                    print("Constant output "+str(dbl0.value))
+                else:
+                    print("Non settable range from "+str(dbl0)+" to "+str(dbl1))
+            elif int0.value>1 :
+                print("Setting from "+str(dbl0.value)+" to "+str(dbl1.value)+" in "+str(int0.value)+" steps")
+
+            dwf.FDwfAnalogIOChannelNodeStatusInfo(hdwf, iChannel, iNode, byref(dbl0), byref(dbl1), byref(int0))
+            if int0.value==1 :
+                if dbl0.value == dbl1.value  :
+                    print("Constant input "+str(dbl0.value))
+                else:
+                    print("Input range from "+str(dbl0.value)+" to "+str(dbl1.value))
+            elif int0.value>1 :
+                print("Reading from "+str(dbl0.value)+" to "+str(dbl1.value)+" in "+str(int0.value)+" steps")
+
+                
+    print("")
+    dwf.FDwfDigitalInBitsInfo(hdwf, byref(int0))
+    print("DigitalIn channels: "+str(int0.value))
+
+    dwf.FDwfDigitalInBufferSizeInfo(hdwf, byref(int0))
+    print("Buffer size: "+str(int0.value))
+
+    print("")
+    dwf.FDwfDigitalOutCount(hdwf, byref(int0))
+    print("DigitalOut channels: "+str(int0.value))
+
+    dwf.FDwfDigitalOutDataInfo(hdwf, c_int(0), byref(int0))
+    print("Custom size: "+str(int0.value))
+
+    
+    print("")
+    print("DigitalIO information:")
+    dwf.FDwfDigitalIOOutputEnableInfo(hdwf, byref(uint0))
+    print("OE Mask: "+hex(uint0.value))
+    dwf.FDwfDigitalIOOutputInfo(hdwf, byref(uint0))
+    print("Output : "+hex(uint0.value))
+    dwf.FDwfDigitalIOInputInfo(hdwf, byref(uint0))
+    print("Input  : "+hex(uint0.value))
+
+# ensure all devices are closed
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Device_Synchronization.py b/tests/py/Device_Synchronization.py
new file mode 100644
index 0000000000000000000000000000000000000000..4996f6d2b7920a4ef923c9b63a3ab0d0517507e0
--- /dev/null
+++ b/tests/py/Device_Synchronization.py
@@ -0,0 +1,122 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-24
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import sys
+import time
+import matplotlib.pyplot as plt
+import numpy as np
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+szerr = create_string_buffer(512)
+dwf.FDwfGetLastErrorMsg(szerr)
+if szerr[0] != b'\0':
+    print(str(szerr.value))
+
+hdwf = c_int()
+rghdwf = []
+cChannel = c_int()
+cDevice = c_int()
+sts = c_byte()
+cSamples = 8192
+rgdSamples = (c_double*cSamples)()
+
+devicename = create_string_buffer(32)
+serialnum = create_string_buffer(32)
+
+version = create_string_buffer(32)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# enumerate connected devices
+dwf.FDwfEnum(c_int(0), byref(cDevice))
+print("Number of Devices: "+str(cDevice.value))
+
+# open devices
+for idevice in range(0, cDevice.value):
+    dwf.FDwfEnumDeviceName(c_int(idevice), devicename)
+    dwf.FDwfEnumSN(c_int(idevice), serialnum)
+    print("------------------------------")
+    print("Device "+str(idevice+1)+" : ")
+    print("\t" + str(devicename.value))
+    print("\t" + str(serialnum.value))
+    
+    dwf.FDwfDeviceOpen(c_int(idevice), byref(hdwf))
+    if hdwf.value == 0:
+        dwf.FDwfGetLastErrorMsg(szerr)
+        print(str(szerr.value))
+        dwf.FDwfDeviceCloseAll()
+        sys.exit(0)
+        
+    rghdwf.append(hdwf.value)
+    
+    if idevice == 0:
+        # on first device drive External T1 (0) with trigsrcPC (1) 
+        # expects T1 of each device to be connected together for synchronization
+        dwf.FDwfDeviceTriggerSet(hdwf, c_int(0), c_int(1)) # 1 = trigsrcPC
+        print("Generating sine wave...")
+        dwf.FDwfAnalogOutTriggerSourceSet(hdwf, c_int(0), c_int(11)) # 11 = trigsrcExternal1
+        dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(0), c_int(1))
+        dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(0), c_int(1))
+        dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(0), c_double(1e3))
+        dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(0), c_double(2))
+        dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
+
+
+    dwf.FDwfAnalogInTriggerSourceSet(hdwf, c_int(11)) # 11 = trigsrcExternal1
+    dwf.FDwfAnalogInFrequencySet(hdwf, c_double(1e6))
+    dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(1)) 
+
+# wait at least 2 seconds with Analog Discovery for the offset to stabilize, before the first reading after device open or offset/range change
+time.sleep(2)
+
+ 
+# wait for the last configured device to armed too
+hdwf.value = rghdwf[cDevice.value-1]
+while True:
+    dwf.FDwfAnalogInStatus(hdwf, c_int(0), byref(sts))
+    if sts.value == 1 : # DwfStateArmed
+        break
+
+# generate trigger signal
+hdwf.value = rghdwf[0]
+dwf.FDwfDeviceTriggerPC(hdwf)
+
+# wait for acquisition to be done
+while True:
+    dwf.FDwfAnalogInStatus(hdwf, c_int(0), byref(sts))
+    if sts.value == 2 : # DwfStateDone
+        break
+
+plt.figure(1)
+for iDevice in range(0, cDevice.value):
+    hdwf.value = rghdwf[iDevice]
+    print("Device " + str(iDevice+1))
+    
+    dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
+    if sts.value != 2 : # DwfStateDone
+        print("Not triggered!")
+        continue
+    
+    # get data of each channel
+    dwf.FDwfAnalogInChannelCount(hdwf, byref(cChannel))
+    for iChannel in range(0, cChannel.value):
+        dwf.FDwfAnalogInStatusData(hdwf, iChannel, rgdSamples, c_int(cSamples))
+        print("Average on Channel " + str(iChannel+1)+" : "+ str(sum(rgdSamples)/cSamples)+"V")
+        plt.plot(np.fromiter(rgdSamples, dtype = np.float))
+
+plt.show()
+# ensure all devices are closed
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/DigitalDiscovery_PlayRecord.py b/tests/py/DigitalDiscovery_PlayRecord.py
new file mode 100644
index 0000000000000000000000000000000000000000..b9fe5e2ead29ca55725368d39a4c573f5c40290e
--- /dev/null
+++ b/tests/py/DigitalDiscovery_PlayRecord.py
@@ -0,0 +1,143 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2020-03-02
+
+   Requires:           
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import sys
+import time
+import matplotlib.pyplot as plt
+import numpy
+
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_ubyte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+dwf.FDwfParamSet(DwfParamOnClose, c_int(1)) # 0 = run, 1 = stop, 2 = shutdown
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0))# 0 = the device will be configured only when calling FDwf###Configure
+
+print("Configuring Digital Out / In...")
+
+hzPlay = 100e6
+nPlay = 1e6
+rgwPlay = (c_uint16*int(nPlay))()
+
+for i in range(len(rgwPlay)):
+    rgwPlay[i] = i
+
+dwf.FDwfDigitalOutPlayRateSet(hdwf, c_double(hzPlay)) # play sample rate
+dwf.FDwfDigitalOutRepeatSet(hdwf, c_int(1)) # repeat once
+dwf.FDwfDigitalOutRunSet(hdwf, c_double(nPlay/hzPlay)) # run length
+dwf.FDwfDigitalOutTriggerSourceSet(hdwf, trigsrcDigitalIn)
+
+# enable play mode for the wanted signals
+for i in range(0, 16):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1)) # enable
+    dwf.FDwfDigitalOutTypeSet(hdwf, c_int(i), c_int(5)) # DwfDigitalOutTypePlay
+    dwf.FDwfDigitalOutIdleSet(hdwf, c_int(i), DwfDigitalOutIdleLow)
+
+# set play data array of 16 bit samples
+dwf.FDwfDigitalOutPlayDataSet(hdwf, byref(rgwPlay), c_int(16), c_int(int(nPlay)))
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+
+hzRecord = 100e6
+nRecord = int(2e6)
+rgwRecord = (c_uint16*nRecord)()
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+iSample = 0
+fLost = 0
+fCorrupted = 0
+hzDI = c_double()
+
+dwf.FDwfDigitalInInternalClockInfo(hdwf, byref(hzDI))
+print("DigitanIn base freq: "+str(hzDI.value))
+
+# in record mode samples after trigger are acquired only
+dwf.FDwfDigitalInAcquisitionModeSet(hdwf, acqmodeRecord)
+# sample rate = system frequency / divider
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(int(hzDI.value/hzRecord)))
+# 16bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(16))
+# number of samples after trigger
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(int(nRecord*3/4)))
+# number of samples before trigger
+dwf.FDwfDigitalInTriggerPrefillSet(hdwf, c_int(int(nRecord*1/4)))
+# for Digital Discovery bit order: DIO24:39; with 32 bit sampling [DIO24:39 + DIN0:15]
+dwf.FDwfDigitalInInputOrderSet(hdwf, c_int(1))
+# begin acquisition
+dwf.FDwfDigitalInConfigure(hdwf, c_int(1), c_int(1))
+
+print("Recording...")
+
+while True:
+    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+    dwf.FDwfDigitalInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+    
+    iSample += cLost.value
+    iSample %= nRecord
+    
+    if cLost.value :
+        fLost = 1
+    if cCorrupted.value :
+        fCorrupted = 1
+
+    iBuffer = 0
+    while cAvailable.value>0:
+        cSamples = cAvailable.value
+        if iSample+cAvailable.value > nRecord: # we are using circular sample buffer, prevent overflow
+            cSamples = nRecord-iSample
+        dwf.FDwfDigitalInStatusData2(hdwf, byref(rgwRecord, 2*iSample), c_int(iBuffer), c_int(2*cSamples))
+        iBuffer += cSamples
+        cAvailable.value -= cSamples
+        iSample += cSamples
+        iSample %= nRecord
+
+    if sts.value == DwfStateDone.value :
+        break
+
+dwf.FDwfDeviceClose(hdwf)
+
+if iSample != 0 :
+    rgwRecord = rgwRecord[iSample:]+rgwRecord[:iSample]
+
+print("  done")
+if fLost:
+    print("Samples were lost! Reduce sample rate")
+if fCorrupted:
+    print("Samples could be corrupted! Reduce sample rate")
+
+
+plt.plot(numpy.fromiter(rgwRecord, dtype = numpy.uint16))
+plt.show()
diff --git a/tests/py/DigitalDiscovery_RecordToFile.py b/tests/py/DigitalDiscovery_RecordToFile.py
new file mode 100644
index 0000000000000000000000000000000000000000..2c1515c415f273cdc0dc43c3f7dde730a761af53
--- /dev/null
+++ b/tests/py/DigitalDiscovery_RecordToFile.py
@@ -0,0 +1,134 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2020-03-02
+
+   Requires:           
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import sys
+import time
+import matplotlib.pyplot as plt
+import numpy
+
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_ubyte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+dwf.FDwfParamSet(DwfParamOnClose, c_int(1)) # 0 = run, 1 = stop, 2 = shutdown
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0))# 0 = the device will be configured only when calling FDwf###Configure
+
+print("Configuring Digital In...")
+
+
+# set system frequency [50-100/125MHz] to 96MHz
+dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(6), c_double(96e6)) 
+# DigitalIn base freq will be 8 times this
+
+# divider sampling by
+divSample = 32
+
+#samples to capture
+nRecord = int(1e9)
+
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+fLost = 0
+fCorrupted = 0
+hzDI = c_double()
+iRecord = int(0)
+
+dwf.FDwfDigitalInInternalClockInfo(hdwf, byref(hzDI))
+print("Base freq: "+str(hzDI.value/1e6)+"Mhz")
+print("Sampling freq: "+str(hzDI.value/divSample/1e6)+"MHz")
+print("Samples: "+str(nRecord))
+
+# in record mode samples after trigger are acquired only
+dwf.FDwfDigitalInAcquisitionModeSet(hdwf, acqmodeRecord)
+# sample rate = system frequency / divider = 96MHz/4 = 24MHz
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(divSample))
+# 8bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(8))
+# number of samples after trigger
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(0))
+# trigger when all digital pins are low
+dwf.FDwfDigitalInTriggerSourceSet(hdwf, trigsrcNone)
+# for Digital Discovery 
+# with order 0: DIN0:7;   with 32 bit sampling [DIN0:23  + DIO24:31]
+# with order 1: DIO24:31; with 32 bit sampling [DIO24:39 + DIN0:15]
+dwf.FDwfDigitalInInputOrderSet(hdwf, c_int(0))
+# begin acquisition
+dwf.FDwfDigitalInConfigure(hdwf, c_int(0), c_int(1))
+
+print("Recording...")
+
+file = open("record.bin", "wb")
+
+
+while True:
+    if dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts)) == 0:
+        print("Error")
+        break
+    
+    dwf.FDwfDigitalInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+    
+    if cAvailable.value == 0:
+        break
+        
+    if cLost.value :
+        fLost = 1
+    if cCorrupted.value :
+        fCorrupted = 1
+
+    cChunk = min(cAvailable.value, nRecord-iRecord)
+
+    # print(str(iRecord)+" "+str(cChunk))
+    
+    rgbBuffer = (c_uint8*cChunk)()
+    
+    dwf.FDwfDigitalInStatusData(hdwf, byref(rgbBuffer), c_int(cChunk))
+    
+    file.write(numpy.fromiter(rgbBuffer, dtype = numpy.byte))
+
+    iRecord += cChunk
+
+    if iRecord >= nRecord:
+        print("Done")
+        break;
+
+dwf.FDwfDeviceClose(hdwf)
+
+file.close()
+
+if fLost:
+    print("Samples were lost! Reduce sample rate")
+if fCorrupted:
+    print("Samples could be corrupted! Reduce sample rate")
+
diff --git a/tests/py/DigitalDiscovery_RecordToFile16.py b/tests/py/DigitalDiscovery_RecordToFile16.py
new file mode 100644
index 0000000000000000000000000000000000000000..8829d3eb4c51907bbd1f3794bf15db1922f78f70
--- /dev/null
+++ b/tests/py/DigitalDiscovery_RecordToFile16.py
@@ -0,0 +1,128 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2020-03-02
+
+   Requires:           
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import sys
+import time
+import matplotlib.pyplot as plt
+import numpy
+
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_ubyte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+dwf.FDwfParamSet(DwfParamOnClose, c_int(1)) # 0 = run, 1 = stop, 2 = shutdown
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0))# 0 = the device will be configured only when calling FDwf###Configure
+
+print("Configuring Digital In...")
+
+# divider sampling by
+divSample = 80 # 10MHz = 800Mhz/80, max ~40MBps, ~20M UShort / s
+
+#samples to capture
+nRecord = int(1e9)
+
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+fLost = 0
+fCorrupted = 0
+hzDI = c_double()
+iRecord = int(0)
+
+dwf.FDwfDigitalInInternalClockInfo(hdwf, byref(hzDI))
+print("Base freq: "+str(hzDI.value/1e6)+"Mhz")
+print("Sampling freq: "+str(hzDI.value/divSample/1e6)+"MHz")
+print("Samples: "+str(nRecord))
+
+# in record mode samples after trigger are acquired only
+dwf.FDwfDigitalInAcquisitionModeSet(hdwf, acqmodeRecord)
+# sample rate = system frequency / divider
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(divSample))
+# 8bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(16))
+# number of samples after trigger
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(0))
+# trigger when all digital pins are low
+dwf.FDwfDigitalInTriggerSourceSet(hdwf, trigsrcNone)
+# for Digital Discovery 
+# with order 0: DIN0:7;   with 32 bit sampling [DIN0:23  + DIO24:31]
+# with order 1: DIO24:31; with 32 bit sampling [DIO24:39 + DIN0:15]
+dwf.FDwfDigitalInInputOrderSet(hdwf, c_int(0))
+# begin acquisition
+dwf.FDwfDigitalInConfigure(hdwf, c_int(1), c_int(1))
+
+print("Recording...")
+
+file = open("record.bin", "wb")
+
+while True:
+    if dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts)) == 0:
+        print("Error")
+        break
+    
+    dwf.FDwfDigitalInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+    
+    if cLost.value :
+        fLost = 1
+    if cCorrupted.value :
+        fCorrupted = 1
+
+    if cAvailable.value == 0:
+        break
+    
+    cChunk = min(cAvailable.value, nRecord-iRecord)
+
+    # print(str(iRecord)+" "+str(cChunk))
+    
+    rgBuffer = (c_uint16*cChunk)()
+    
+    dwf.FDwfDigitalInStatusData(hdwf, byref(rgBuffer), c_int(2*cChunk))
+    
+    file.write(numpy.fromiter(rgBuffer, dtype = numpy.ushort))
+
+    iRecord += cChunk
+
+    if iRecord >= nRecord:
+        print("Done")
+        break
+
+dwf.FDwfDeviceClose(hdwf)
+
+file.close()
+
+if fLost != 0:
+    print("Samples were lost! Reduce sample rate")
+if fCorrupted != 0:
+    print("Samples could be corrupted! Reduce sample rate")
+
diff --git a/tests/py/DigitalIO.py b/tests/py/DigitalIO.py
new file mode 100644
index 0000000000000000000000000000000000000000..7aa4017e7e3e77dfd1b380a073d7d032ab04c10c
--- /dev/null
+++ b/tests/py/DigitalIO.py
@@ -0,0 +1,63 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+dwRead = c_uint32()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == hdwfNone.value:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+# enable output/mask on 8 LSB IO pins, from DIO 0 to 7
+dwf.FDwfDigitalIOOutputEnableSet(hdwf, c_int(0x00FF)) 
+# set value on enabled IO pins
+dwf.FDwfDigitalIOOutputSet(hdwf, c_int(0x12)) 
+dwf.FDwfDigitalIOConfigure(hdwf) 
+
+# fetch digital IO information from the device 
+dwf.FDwfDigitalIOStatus(hdwf) 
+# read state of all pins, regardless of output enable
+dwf.FDwfDigitalIOInputStatus(hdwf, byref(dwRead)) 
+
+print("DIO-0:", (dwRead.value>>0)&1)
+print("DIO-1:", (dwRead.value>>1)&1)
+
+#print(dwRead as bitfield (32 digits, removing 0b at the front)
+print("Digital IO Pins: ", bin(dwRead.value)[2:].zfill(16))
+
+dwf.FDwfDeviceClose(hdwf)
+
+
+
diff --git a/tests/py/DigitalIn_Acquisition.py b/tests/py/DigitalIn_Acquisition.py
new file mode 100644
index 0000000000000000000000000000000000000000..055ed1e7dd3ae31982fbbef0b6a591abd3664413
--- /dev/null
+++ b/tests/py/DigitalIn_Acquisition.py
@@ -0,0 +1,84 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+
+# generate on DIO-0 1Mhz pulse (100MHz/25/(3+1)), 25% duty (3low 1high)
+#dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
+#dwf.FDwfDigitalOutDividerSet(hdwf, c_int(i), c_int(25))
+#dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), c_int(3), c_int(1))
+    
+# generate counter
+for i in range(0, 16):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
+    dwf.FDwfDigitalOutDividerSet(hdwf, c_int(i), c_int(1<<i))
+    dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), c_int(1), c_int(1))
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+# sample rate = system frequency / divider
+hzDI = c_double()
+dwf.FDwfDigitalInInternalClockInfo(hdwf, byref(hzDI))
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(int(hzDI.value/100e6))) # 100MHz
+# 16bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(16))
+# set number of sample to acquire
+cSamples = 1000
+rgwSamples = (c_uint16*cSamples)()
+dwf.FDwfDigitalInBufferSizeSet(hdwf, c_int(cSamples))
+
+# begin acquisition
+dwf.FDwfDigitalInConfigure(hdwf, c_int(0), c_int(1))
+
+print("Waiting for acquisition...")
+while True:
+    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+    if sts.value == stsDone.value :
+        break
+    time.sleep(1)
+print("   done")
+
+# get samples, byte size
+dwf.FDwfDigitalInStatusData(hdwf, rgwSamples, 2*cSamples)
+dwf.FDwfDeviceCloseAll()
+
+plt.plot(numpy.fromiter(rgwSamples, dtype = numpy.uint16))
+plt.show()
diff --git a/tests/py/DigitalIn_Acquisition_8x100k.py b/tests/py/DigitalIn_Acquisition_8x100k.py
new file mode 100644
index 0000000000000000000000000000000000000000..01f8a6e8ea55b0640ecd3521d6fee4bd8baf9b41
--- /dev/null
+++ b/tests/py/DigitalIn_Acquisition_8x100k.py
@@ -0,0 +1,89 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2019-08-16
+
+   Requires:                       
+       Python 2.7, 3
+   Description:
+   For devices with at least 100k DigitalIn buffer, like Digital Discovery.
+   The DigitalOut generates counter at ~256.41kHz 100M/390, ~256 steps in 1ms 100k*10ns.
+   The DigitalIn captures 100k samples at 8 bits triggering on DIO7 falling edge.
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+
+# generate counter
+for i in range(0, 16):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
+    dwf.FDwfDigitalOutDividerSet(hdwf, c_int(i), c_int(1<<i))
+    dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), c_int(390), c_int(390)) # 100000/256
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+hzDI = c_double()
+dwf.FDwfDigitalInInternalClockInfo(hdwf, byref(hzDI))
+print("DigitanIn base freq: "+str(hzDI.value))
+#divider = system frequency / sample rate
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(int(hzDI.value/1e8))) # 100MHz
+# 16bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(8))
+# set number of sample to acquire
+cSamples = 100000
+rgbSamples = (c_uint8*cSamples)()
+dwf.FDwfDigitalInInputOrderSet(hdwf, c_int(1)) # with 8 bits DIO-0:7
+dwf.FDwfDigitalInBufferSizeSet(hdwf, c_int(cSamples))
+dwf.FDwfDigitalInTriggerSourceSet(hdwf, c_ubyte(3)) # trigsrcDetectorDigitalIn
+dwf.FDwfDigitalInTriggerSet(hdwf, c_int(0), c_int(0), c_int(0), c_int(1<<7)) # DIO7 falling edge
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(cSamples-1))
+
+# start acquisition
+dwf.FDwfDigitalInConfigure(hdwf, c_int(0), c_int(1))
+
+print("Waiting for acquisition...")
+while True:
+    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+    if sts.value == stsDone.value :
+        break
+    time.sleep(1)
+print("   done")
+
+# get samples, byte size
+dwf.FDwfDigitalInStatusData(hdwf, rgbSamples, cSamples)
+dwf.FDwfDeviceCloseAll()
+
+#print(str(rgbSamples[0]),str(rgbSamples[1]),str(rgbSamples[2]))
+plt.plot(numpy.fromiter(rgbSamples, dtype = numpy.uint8))
+plt.show()
diff --git a/tests/py/DigitalIn_Acquisition_8x256M.py b/tests/py/DigitalIn_Acquisition_8x256M.py
new file mode 100644
index 0000000000000000000000000000000000000000..5a2af54b79a01a186f210fe8f94151ea06e0c556
--- /dev/null
+++ b/tests/py/DigitalIn_Acquisition_8x256M.py
@@ -0,0 +1,101 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+   - supported devices: Digital Discovery
+   - generates 8 bit 100MHz Gray Counter on DIO-0:7
+   - captures 256M samples at 8bit 100MHz
+   - write data to binary file
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+
+
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+#open device
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+
+print("Generating gray counter")
+for i in range(0, 8):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
+    dwf.FDwfDigitalOutDividerSet(hdwf, c_int(i), c_int(1<<(i+1)))
+    if i!=7:
+        dwf.FDwfDigitalOutDividerInitSet(hdwf, c_int(i), c_int(1<<i))
+    dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), c_int(1), c_int(1))
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+print("Configuring DigitalIn")
+sts = c_byte()
+hzDI = c_double()
+cSamples = 256*1024*1024;
+rgbSamples = (c_byte*cSamples)()
+t = c_int()
+
+dwf.FDwfDigitalInInternalClockInfo(hdwf, byref(hzDI))
+print("DigitanIn base freq: "+str(hzDI.value))
+#divider = system frequency / sample rate
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(int(hzDI.value/1e8))) # 100MHz
+dwf.FDwfDigitalInDividerGet(hdwf, byref(t)) 
+print("Sample rate: "+str(hzDI.value/t.value))
+# 8bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(8))
+# set number of sample to acquire
+dwf.FDwfDigitalInBufferSizeSet(hdwf, c_int(cSamples))
+dwf.FDwfDigitalInBufferSizeGet(hdwf, byref(t))
+print("Buffer size: "+str(t.value))
+# for Digital Discovery bit order: DIO24:39; with 32 bit sampling [DIO24:39 + DIN0:15]
+dwf.FDwfDigitalInInputOrderSet(hdwf, c_int(1)) # with 8 bits DIO-0:7
+
+# begin acquisition
+dwf.FDwfDigitalInConfigure(hdwf, c_int(0), c_int(1))
+
+print("Waiting for acquisition...")
+while True:
+    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+    if sts.value == stsDone.value :
+        break
+    time.sleep(.1)
+print("   done")
+
+# get samples, byte size
+dwf.FDwfDigitalInStatusData(hdwf, rgbSamples, 1*cSamples)
+dwf.FDwfDeviceCloseAll()
+
+print("Writing to file...")
+f = open("record.bin", "wb")
+f.write(numpy.fromiter(rgbSamples, dtype = numpy.byte))
+f.close()
+print("   done")
+
diff --git a/tests/py/DigitalIn_PulseTrigger.py b/tests/py/DigitalIn_PulseTrigger.py
new file mode 100644
index 0000000000000000000000000000000000000000..f27848087e1aa53f32b381352b2d16cf4db03e3e
--- /dev/null
+++ b/tests/py/DigitalIn_PulseTrigger.py
@@ -0,0 +1,82 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2020-04-03
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+
+hzDI = c_double()
+dwf.FDwfDigitalInInternalClockInfo(hdwf, byref(hzDI))
+print("DigitanIn base freq: "+str(hzDI.value/1e6)+"MHz")
+#sample rate = system frequency / divider, 1kHz
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(int(hzDI.value/1000)))
+
+# 16bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(8))
+# set number of sample to acquire
+cSamples = 2048
+rgbSamples = (c_ubyte*cSamples)()
+dwf.FDwfDigitalInBufferSizeSet(hdwf, c_int(cSamples))
+dwf.FDwfDigitalInTriggerSourceSet(hdwf, c_ubyte(3)) # trigsrcDetectorDigitalIn
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(int(cSamples/2-1)))
+
+# positive pulse of at least 0.5 seconds on DIO 7
+dwf.FDwfDigitalInTriggerResetSet(hdwf, c_int(0), c_int(0), c_int(1<<7), c_int(0))
+dwf.FDwfDigitalInTriggerSet(hdwf, c_int(0), c_int(1<<7), c_int(0), c_int(0))
+dwf.FDwfDigitalInTriggerLengthSet(hdwf, c_double(0.5), c_double(-1), c_int(0))
+dwf.FDwfDigitalInTriggerCountSet(hdwf, c_int(1), c_int(0))
+
+# begin acquisition
+dwf.FDwfDigitalInConfigure(hdwf, c_int(0), c_int(1))
+print("Waiting for acquisition...")
+
+while True:
+    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+    print("Status:", str(sts.value))
+    if sts.value == 2 : # done
+        break
+    time.sleep(1)
+print("   done")
+
+# get samples, byte size
+dwf.FDwfDigitalInStatusData(hdwf, rgbSamples, 1*cSamples)
+dwf.FDwfDeviceCloseAll()
+
+plt.plot(numpy.fromiter(rgbSamples, dtype = numpy.ubyte))
+plt.show()
+
+
diff --git a/tests/py/DigitalIn_Record.py b/tests/py/DigitalIn_Record.py
new file mode 100644
index 0000000000000000000000000000000000000000..20bb093ba05b5dd75719730d368c52a9f66ec676
--- /dev/null
+++ b/tests/py/DigitalIn_Record.py
@@ -0,0 +1,132 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import sys
+import matplotlib.pyplot as plt
+import numpy
+
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_ubyte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring Digital Out / In...")
+
+# generate counter
+for i in range(0, 16):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
+    dwf.FDwfDigitalOutDividerSet(hdwf, c_int(i), c_int(1<<i))
+    dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), c_int(1000), c_int(1000))
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+# set number of sample to acquire
+nSamples = 100000
+rgwSamples = (c_uint16*nSamples)()
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+iSample = 0
+fLost = 0
+fCorrupted = 0
+hzDI = c_double()
+
+dwf.FDwfDigitalInInternalClockInfo(hdwf, byref(hzDI))
+print("DigitanIn base freq: "+str(hzDI.value))
+
+# in record mode samples after trigger are acquired only
+dwf.FDwfDigitalInAcquisitionModeSet(hdwf, acqmodeRecord)
+# sample rate = system frequency / divider, 100MHz/1000 = 100kHz
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(int(hzDI.value/100e3)))
+# 16bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(16))
+# number of samples after trigger
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(int(nSamples/2))) # trigger in the middle
+# number of samples before trigger
+dwf.FDwfDigitalInTriggerPrefillSet(hdwf, c_int(nSamples-int(nSamples/2)))
+# trigger when all digital pins are low
+dwf.FDwfDigitalInTriggerSourceSet(hdwf, trigsrcDetectorDigitalIn)
+# trigger detector mask:                  low &   hight & ( rising | falling )
+dwf.FDwfDigitalInTriggerSet(hdwf, c_int(0xFFFF), c_int(0), c_int(0), c_int(0))
+# for Digital Discovery bit order: DIO24:39; with 32 bit sampling [DIO24:39 + DIN0:15]
+dwf.FDwfDigitalInInputOrderSet(hdwf, c_int(1))
+# begin acquisition
+dwf.FDwfDigitalInConfigure(hdwf, c_int(0), c_int(1))
+
+print("Recording...")
+
+
+while True:
+    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+    dwf.FDwfDigitalInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+    
+    iSample += cLost.value
+    iSample %= nSamples
+    
+    if cLost.value :
+        fLost = 1
+    if cCorrupted.value :
+        fCorrupted = 1
+
+    iBuffer = 0
+    while cAvailable.value>0:
+        cSamples = cAvailable.value
+        # we are using circular sample buffer, prevent overflow
+        if iSample+cAvailable.value > nSamples:
+            cSamples = nSamples-iSample
+        dwf.FDwfDigitalInStatusData2(hdwf, byref(rgwSamples, 2*iSample), c_int(iBuffer), c_int(2*cSamples))
+        iBuffer += cSamples
+        cAvailable.value -= cSamples
+        iSample += cSamples
+        iSample %= nSamples
+
+    if sts.value == DwfStateDone.value :
+        break
+
+dwf.FDwfDeviceClose(hdwf)
+
+if iSample != 0 :
+    rgwSamples = rgwSamples[iSample:]+rgwSamples[:iSample]
+
+print("  done")
+if fLost:
+    print("Samples were lost! Reduce sample rate")
+if fCorrupted:
+    print("Samples could be corrupted! Reduce sample rate")
+
+f = open("record.csv", "w")
+for v in rgwSamples:
+    f.write("%s\n" % v)
+f.close()
+
+plt.plot(numpy.fromiter(rgwSamples, dtype = numpy.uint16))
+plt.show()
diff --git a/tests/py/DigitalIn_Record_Compress.py b/tests/py/DigitalIn_Record_Compress.py
new file mode 100644
index 0000000000000000000000000000000000000000..43dcaf30a10b907412a52f95e50880487f4d4d55
--- /dev/null
+++ b/tests/py/DigitalIn_Record_Compress.py
@@ -0,0 +1,136 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import sys
+import matplotlib.pyplot as plt
+import numpy
+
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring Digital Out / In...")
+
+# generate counter
+for i in range(0, 8):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
+    dwf.FDwfDigitalOutDividerSet(hdwf, c_int(i), c_int(1<<i))
+    dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), c_int(1), c_int(1))
+
+dwf.FDwfDigitalOutRunSet(hdwf, c_double(2e-6))
+dwf.FDwfDigitalOutWaitSet(hdwf, c_double(500e-6))
+dwf.FDwfDigitalOutRepeatSet(hdwf, c_int(0))
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+# set number of sample to acquire
+nSamples = 1000000
+rgwSamples = (c_uint16*nSamples)()
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+iSample = 0
+fLost = 0
+fCorrupted = 0
+hzDI = c_double()
+
+dwf.FDwfDigitalInInternalClockInfo(hdwf, byref(hzDI))
+print("DigitanIn base freq: "+str(hzDI.value))
+
+# in record mode samples after trigger are acquired only
+dwf.FDwfDigitalInAcquisitionModeSet(hdwf, acqmodeRecord)
+# sample rate = system frequency / divider, 100MHz/10 = 10MHz
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(int(hzDI.value/100e6)))
+# 16bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(16))
+# number of samples after trigger
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(int(nSamples/2))) # 50%
+# number of samples before trigger
+dwf.FDwfDigitalInTriggerPrefillSet(hdwf, c_int(nSamples-int(nSamples/2)))
+# enable data compression by select used lines
+dwf.FDwfDigitalInSampleSensibleSet(hdwf, c_int(0x00FF))
+# trigger when all digital pins are low
+dwf.FDwfDigitalInTriggerSourceSet(hdwf, trigsrcDetectorDigitalIn)
+# trigger detector mask:                  low &   hight & ( rising | falling )
+dwf.FDwfDigitalInTriggerSet(hdwf, c_uint(0), c_uint(0), c_uint(0), c_uint(0x0040))
+
+# begin acquisition
+dwf.FDwfDigitalInConfigure(hdwf, c_int(1), c_int(1))
+
+print("Recording...")
+
+while True:
+    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+    dwf.FDwfDigitalInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+    
+    iSample += cLost.value
+    iSample %= nSamples
+    
+    if cLost.value :
+        fLost = 1
+    if cCorrupted.value :
+        fCorrupted = 1
+
+    iBuffer = 0
+    while cAvailable.value>0:
+        cSamples = cAvailable.value
+        # we are using circular sample buffer, prevent overflow
+        if iSample+cAvailable.value > nSamples:
+            cSamples = nSamples-iSample
+        dwf.FDwfDigitalInStatusData2(hdwf, byref(rgwSamples, 2*iSample), c_int(iBuffer), c_int(2*cSamples))
+        iBuffer += cSamples
+        cAvailable.value -= cSamples
+        iSample += cSamples
+        iSample %= nSamples
+
+    if sts.value == DwfStateDone.value :
+        print(str(iSample))
+        break
+
+dwf.FDwfDeviceClose(hdwf)
+
+if iSample != 0 :
+    rgwSamples = rgwSamples[iSample:]+rgwSamples[:iSample]
+
+print("   done")
+if fLost:
+    print("Samples were lost! Reduce sample rate")
+if cCorrupted:
+    print("Samples could be corrupted! Reduce sample rate")
+
+f = open("record.csv", "w")
+for v in rgwSamples:
+    f.write("%s\n" % v)
+f.close()
+
+plt.plot(numpy.fromiter(rgwSamples, dtype = numpy.uint16))
+plt.show()
diff --git a/tests/py/DigitalIn_Spi_Spy.py b/tests/py/DigitalIn_Spi_Spy.py
new file mode 100644
index 0000000000000000000000000000000000000000..e54ac42f792163cd98d1c770be15aa34dfced0cd
--- /dev/null
+++ b/tests/py/DigitalIn_Spi_Spy.py
@@ -0,0 +1,145 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+#dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+#  device configuration of index 3 (4th) for Analog Discovery has 16kS digital-in buffer
+dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf)) 
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring Digital In...")
+
+nSamples = 100000000 # 100MiB, ~12Mi of 8bit SPI
+rgbSamples = (c_uint8*nSamples)()
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+cSamples = 0
+fLost = 0
+fCorrupted = 0
+
+idxCS = 0
+idxClk = 1
+idxMosi = 2
+idxMiso = 3
+nBits = 8
+
+# record mode
+dwf.FDwfDigitalInAcquisitionModeSet(hdwf, acqmodeRecord)
+# for sync mode set divider to -1 
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(-1))
+# 8bit per sample format, DIO 0-7
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(8))
+# continuous sampling 
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(-1))
+# in sync mode the trigger is used for sampling condition
+# trigger detector mask:          low &     hight & ( rising | falling )
+dwf.FDwfDigitalInTriggerSet(hdwf, c_int(0), c_int(0), c_int((1<<idxClk)|(1<<idxCS)), c_int(0))
+# sample on clock rising edge for sampling bits, or CS rising edge to detect frames
+
+print("Starting spy, press Ctrl+C to stop...")
+dwf.FDwfDigitalInConfigure(hdwf, c_int(0), c_int(1))
+
+try:
+    while cSamples < nSamples:
+        dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+        dwf.FDwfDigitalInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+        cSamples += cLost.value
+        
+        if cLost.value :
+            fLost = 1
+        if cCorrupted.value :
+            fCorrupted = 1
+
+        if cAvailable.value!=0 :
+            if cSamples+cAvailable.value > nSamples :
+                cAvailable = c_int(nSamples-cSamples)
+            # get samples
+            dwf.FDwfDigitalInStatusData(hdwf, byref(rgbSamples, cSamples), c_int(cAvailable.value))
+            cSamples += cAvailable.value
+        
+        if sts != DwfStateRunning :
+            continue
+
+except KeyboardInterrupt: # Ctrl+C
+    pass
+
+dwf.FDwfDeviceClose(hdwf)
+
+print("   done", str(cSamples), "samples")
+if fLost:
+    print("Samples were lost!")
+elif cCorrupted:
+    print("Samples could be corrupted!")
+
+print("Decoding data and saving to file")
+
+fsMosi = 0
+fsMiso = 0
+cBit = 0
+
+fMosi = open("record_mosi.csv", "w")
+fMiso = open("record_miso.csv", "w")
+
+for i in range(0,cSamples):
+    v = rgbSamples[i]
+    if (v>>idxCS)&1: # CS high, inactive
+        if cBit != 0: # log leftover bits, frame not multiple of nBits
+            fMosi.write("X%s %s " % (cBit, hex(fsMosi)))
+            fMiso.write("X%s %s " % (cBit, hex(fsMiso)))
+        cBit = 0
+        fsMosi = 0
+        fsMiso = 0
+        fMosi.write("\n")
+        fMiso.write("\n")
+    else:
+        cBit+=1
+        fsMosi <<= 1 # MSB first
+        fsMiso <<= 1 # MSB first
+        if (v>>idxMosi)&1 :
+            fsMosi |= 1
+        if (v>>idxMiso)&1 :
+            fsMiso |= 1
+        if cBit >= nBits: # got nBits of bits
+            fMosi.write("%s " % hex(fsMosi))
+            fMiso.write("%s " % hex(fsMiso))
+            cBit = 0
+            fsMosi = 0
+            fsMiso = 0
+fMosi.close()
+fMiso.close()
+
+
+
+
diff --git a/tests/py/DigitalIn_Sync.py b/tests/py/DigitalIn_Sync.py
new file mode 100644
index 0000000000000000000000000000000000000000..233b918cf541bcb9ff2690cb39634bf5fac51623
--- /dev/null
+++ b/tests/py/DigitalIn_Sync.py
@@ -0,0 +1,112 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring Digital Out / In...")
+
+# generate counter
+for i in range(0, 16):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
+    dwf.FDwfDigitalOutDividerSet(hdwf, c_int(i), c_int(1<<i))
+    dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), c_int(1000), c_int(1000))
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+# set number of sample to acquire
+nSamples = 100000
+rgwSamples = (c_uint16*nSamples)()
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+cSamples = 0
+fLost = 0
+fCorrupted = 0
+
+# record mode
+dwf.FDwfDigitalInAcquisitionModeSet(hdwf, acqmodeRecord)
+# for sync mode set divider to -1 
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(-1))
+# 16bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(16))
+# number of samples 
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(nSamples))
+# in sync mode the trigger is used for sampling condition
+# trigger detector mask:          low &     hight & ( rising | falling )
+dwf.FDwfDigitalInTriggerSet(hdwf, c_int(0), c_int(0), c_int(1<<0), c_int(0)) # DIO-0 rising edge
+
+# begin acquisition
+dwf.FDwfDigitalInConfigure(hdwf, c_int(0), c_int(1))
+
+print("Starting sync record...")
+
+while cSamples < nSamples:
+    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+    if cSamples == 0 and (sts == DwfStateConfig or sts == DwfStatePrefill or sts == DwfStateArmed) :
+        # acquisition not yet started.
+        continue
+
+    dwf.FDwfDigitalInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+
+    cSamples += cLost.value
+    
+    if cLost.value :
+        fLost = 1
+    if cCorrupted.value :
+        fCorrupted = 1
+
+    if cAvailable.value==0 :
+        continue
+
+    if cSamples+cAvailable.value > nSamples :
+        cAvailable = c_int(nSamples-cSamples)
+    
+    # get samples
+    dwf.FDwfDigitalInStatusData(hdwf, byref(rgwSamples, 2*cSamples), c_int(2*cAvailable.value))
+    cSamples += cAvailable.value
+
+dwf.FDwfDeviceClose(hdwf)
+
+print("   done")
+if fLost:
+    print("Samples were lost! Reduce sample rate")
+if cCorrupted:
+    print("Samples could be corrupted! Reduce sample rate")
+
+f = open("record.csv", "w")
+for v in rgwSamples:
+    f.write("%s\n" % v)
+f.close()
diff --git a/tests/py/DigitalIn_Trigger.py b/tests/py/DigitalIn_Trigger.py
new file mode 100644
index 0000000000000000000000000000000000000000..13ec9cc1aa4ecf84a23b20d7366a4ed3a4941d06
--- /dev/null
+++ b/tests/py/DigitalIn_Trigger.py
@@ -0,0 +1,92 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+# generate counter
+for i in range(0, 8):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
+    dwf.FDwfDigitalOutDividerSet(hdwf, c_int(i), c_int(1<<i))
+    dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), c_int(1), c_int(1))
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+
+# for Digital Discovery bit order: DIO24:39; with 32 bit sampling [DIO24:39 + DIN0:15]
+dwf.FDwfDigitalInInputOrderSet(hdwf, c_int(1)) # with 8 bits DIO-0:7
+
+hzDI = c_double()
+dwf.FDwfDigitalInInternalClockInfo(hdwf, byref(hzDI))
+print("DigitanIn base freq: "+str(hzDI.value/1e6)+"MHz")
+#sample rate = system frequency / divider
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(int(hzDI.value/1e8)))
+
+# 8 bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(8))
+# set number of sample to acquire
+cSamples = 512
+rgbSamples = (c_ubyte*cSamples)()
+dwf.FDwfDigitalInBufferSizeSet(hdwf, c_int(cSamples))
+dwf.FDwfDigitalInTriggerSourceSet(hdwf, c_ubyte(3)) # trigsrcDetectorDigitalIn
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(int(cSamples/2-1)))
+dwf.FDwfDigitalInTriggerSet(hdwf, c_int(0), c_int(0), c_int(0), c_int(1<<7)) # DIO7 falling edge
+
+# begin acquisition
+dwf.FDwfDigitalInConfigure(hdwf, c_int(0), c_int(1))
+print("Waiting for acquisition...")
+
+while True:
+    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+    print("Status:", str(sts.value))
+    if sts.value == 2 : # done
+        break
+    time.sleep(1)
+print("   done")
+
+# get samples, byte size
+dwf.FDwfDigitalInStatusData(hdwf, rgbSamples, 1*cSamples)
+dwf.FDwfDeviceCloseAll()
+
+plt.plot(numpy.fromiter(rgbSamples, dtype = numpy.ubyte))
+plt.show()
+
+
diff --git a/tests/py/DigitalOut_BinrayCounter.py b/tests/py/DigitalOut_BinrayCounter.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef578d38bafafdc6a76deaff84b252f408f31073
--- /dev/null
+++ b/tests/py/DigitalOut_BinrayCounter.py
@@ -0,0 +1,61 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+hzSys = c_double()
+dwf.FDwfDigitalOutInternalClockInfo(hdwf, byref(hzSys))
+print("Internal frequency is " + str(hzSys.value/1e6)+" MHz")
+
+# 100kHz counter rate, SystemFrequency/100kHz
+cntFreq = c_uint(int(hzSys.value/1e5))
+
+# generate counter
+for i in range(0, 16):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
+    # increase by 2 the period of successive bits
+    dwf.FDwfDigitalOutDividerSet(hdwf, c_int(i), c_int(1<<i))
+    dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), cntFreq, cntFreq)
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+print("Generating binary counter for 10 seconds...")
+time.sleep(10)
+
+dwf.FDwfDigitalOutReset(hdwf)
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/DigitalOut_Clock.py b/tests/py/DigitalOut_Clock.py
new file mode 100644
index 0000000000000000000000000000000000000000..2fdf1bdf7f827ddaabd13a3e4a6b8b13a83c78d2
--- /dev/null
+++ b/tests/py/DigitalOut_Clock.py
@@ -0,0 +1,75 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2019-09-06
+
+   Requires:                       
+       Python 2.7, 3
+   Description:
+   DIO-0 generates a clock of 1kHz
+   DIO-1 driven low for a second then high for a second
+   Clock continues to be generated after the script quits
+"""
+
+from ctypes import *
+import math
+import time
+import sys
+from dwfconstants import *
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# continue running after device close, prevent temperature drifts
+dwf.FDwfParamSet(DwfParamOnClose, c_int(1)) # 0 = run, 1 = stop, 2 = shutdown
+
+print("Opening first device")
+hdwf = c_int()
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+# enable output for DIO 1
+dwf.FDwfDigitalIOOutputEnableSet(hdwf, c_int(0x0002)) # 1<<1
+# set value on enabled IO pins
+dwf.FDwfDigitalIOOutputSet(hdwf, c_int(0x0000)) # DIO-1 low
+dwf.FDwfDigitalIOConfigure(hdwf)
+
+# configure and start clock
+hzSys = c_double()
+dwf.FDwfDigitalOutInternalClockInfo(hdwf, byref(hzSys))
+# 1kHz pulse on DIO-0
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(0), c_int(1))
+# prescaler to 2kHz, SystemFrequency/1kHz/2
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(0), c_int(int(hzSys.value/1e3/2)))
+# 1 tick low, 1 tick high
+dwf.FDwfDigitalOutCounterSet(hdwf, c_int(0), c_int(1), c_int(1))
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+time.sleep(1) # wait a second
+
+dwf.FDwfDigitalIOOutputSet(hdwf, c_int(0x0002)) # DIO-1 high
+dwf.FDwfDigitalIOConfigure(hdwf)
+
+time.sleep(1) # wait a second
+
+dwf.FDwfDigitalIOOutputSet(hdwf, c_int(0x0000)) # DIO-1 low
+dwf.FDwfDigitalIOConfigure(hdwf)
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/DigitalOut_Custom.py b/tests/py/DigitalOut_Custom.py
new file mode 100644
index 0000000000000000000000000000000000000000..f7b024ddda94947ec47d2bc7f0fb1e5548b0c9be
--- /dev/null
+++ b/tests/py/DigitalOut_Custom.py
@@ -0,0 +1,74 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2019-09-02
+
+   Requires:                       
+       Python 2.7, 3
+   Description:
+   Generates a custom pattern
+"""
+
+from ctypes import *
+from dwfconstants import *
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# continue running after device close
+dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+print("Configuring Digital Out")
+
+hzSys = c_double()
+dwf.FDwfDigitalOutInternalClockInfo(hdwf, byref(hzSys))
+
+
+data_py=[0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1]
+
+# how many bytes we need to fit this many bits, (+7)/8
+rgbdata=(c_ubyte*((len(data_py)+7)>>3))(0) 
+
+# array to bits in byte array
+for i in range(len(data_py)):
+    if data_py[i] != 0:
+        rgbdata[i>>3] |= 1<<(i&7)
+        
+        
+pin=0
+# generate pattern
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(pin), c_int(1))
+dwf.FDwfDigitalOutTypeSet(hdwf, c_int(pin), DwfDigitalOutTypeCustom)
+# 100kHz sample rate
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(pin), c_int(int(hzSys.value/100e3))) # set sample rate
+dwf.FDwfDigitalOutDataSet(hdwf, c_int(pin), byref(rgbdata), c_int(len(data_py)))
+
+print("Generating pattern...")
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/DigitalOut_CustomBus.py b/tests/py/DigitalOut_CustomBus.py
new file mode 100644
index 0000000000000000000000000000000000000000..f9cb407969fa82f76ad29e4ceafee6c3913170ee
--- /dev/null
+++ b/tests/py/DigitalOut_CustomBus.py
@@ -0,0 +1,106 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-19
+
+   Requires:                       
+       Python 2.7, 3
+   Description:
+   Generates a custom pattern on 16 channels with 16 samples
+   Captures 32 samples having the generated data in middle
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import sys
+import time
+import matplotlib.pyplot as plt
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+# continue running after device close
+dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown
+
+print("Configuring Digital Out")
+
+hzRate = 1e6 # frequency
+cChannels = 16
+cSamples = 16
+cBytes = int(math.ceil(cSamples/8))
+rgSamples = [0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F]
+
+hzDO = c_double()
+dwf.FDwfDigitalOutInternalClockInfo(hdwf, byref(hzDO))
+
+
+for channel in range(cChannels): # configure output channels
+    rgBits = (cBytes*c_byte)() # custom bit array for each channel
+    for sample in range(cSamples): # using the bits from samples array construct the bit array for the channel
+        if(1&(rgSamples[int(sample)]>>channel)) : rgBits[int(sample/8)] |= 1<<(sample&7)
+        else : rgBits[int(sample/8)] &= ~(1<<(sample&7))
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(channel), c_int(1))
+    dwf.FDwfDigitalOutTypeSet(hdwf, c_int(channel), DwfDigitalOutTypeCustom)
+    dwf.FDwfDigitalOutDividerSet(hdwf, c_int(channel), c_int(int(hzDO.value/hzRate))) # set sample rate
+    dwf.FDwfDigitalOutDataSet(hdwf, c_int(channel), byref(rgBits), c_int(cSamples))
+
+dwf.FDwfDigitalOutRunSet(hdwf, c_double(cSamples/hzRate)) # 160ns = 2*8 bits /100MHz = 16 bits * 10ns
+dwf.FDwfDigitalOutRepeatSet(hdwf, c_int(1)) # once
+
+print("Configuring Digital In")
+dwf.FDwfDigitalInTriggerSourceSet(hdwf, trigsrcDigitalOut)
+hzDI = c_double()
+dwf.FDwfDigitalInInternalClockInfo(hdwf, byref(hzDI))
+# sample rate = system frequency / divider, for Digital Discovery 800MHz/8 = 100MHz sample rate
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(int(hzDI.value/hzRate)))
+# 16bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(16))
+# set number of sample to acquire
+cData = 32
+rgData = (c_uint16*cData)()
+dwf.FDwfDigitalInBufferSizeSet(hdwf, c_int(cData))
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(int(cData-8))) # this number of samples after trigger
+# for Digital Discovery bit order with 16bit samples: DIO24:39
+dwf.FDwfDigitalInInputOrderSet(hdwf, c_int(1)) 
+
+dwf.FDwfDigitalInConfigure(hdwf, c_int(1), c_int(1))
+time.sleep(0.001) # make sure to let the LA to have sufficient prefill time
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+print("Waiting for acquisition...")
+sts = c_byte()
+while True:
+    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+    if sts.value == stsDone.value :
+        break
+    time.sleep(1)
+print ('   done')
+
+# get samples
+dwf.FDwfDigitalInStatusData(hdwf, rgData, 2*cData) # 16 bit samples = 2 byte size
+dwf.FDwfDeviceCloseAll()
+
+plt.plot(numpy.fromiter(rgData, dtype = numpy.uint16))
+plt.show()
diff --git a/tests/py/DigitalOut_Duty.py b/tests/py/DigitalOut_Duty.py
new file mode 100644
index 0000000000000000000000000000000000000000..e586a04de4b233eaf3a64774cce9d84fa071f11c
--- /dev/null
+++ b/tests/py/DigitalOut_Duty.py
@@ -0,0 +1,70 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+iChannel = 0
+hzFreq = 1000 # PWM freq Hz
+prcDuty = 1.23 # duty %
+
+hzSys = c_double()
+maxCnt = c_uint()
+dwf.FDwfDigitalOutInternalClockInfo(hdwf, byref(hzSys))
+dwf.FDwfDigitalOutCounterInfo(hdwf, c_int(0), 0, byref(maxCnt))
+
+# for low frequencies use divider as pre-scaler to satisfy counter limitation of 32k
+cDiv = int(math.ceil(hzSys.value/hzFreq/maxCnt.value))
+# count steps to generate the give frequency
+cPulse = int(round(hzSys.value/hzFreq/cDiv))
+# duty
+cHigh = int(cPulse*prcDuty/100)
+cLow = int(cPulse-cHigh)
+
+print("Generate: "+str(hzSys.value/cPulse/cDiv)+"Hz duty: "+str(100.0*cHigh/cPulse)+"% divider: "+str(cDiv))
+
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(iChannel), c_int(1))
+dwf.FDwfDigitalOutTypeSet(hdwf, c_int(iChannel), c_int(0)) # DwfDigitalOutTypePulse
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(iChannel), c_int(cDiv)) # max 2147483649, for counter limitation or custom sample rate
+dwf.FDwfDigitalOutCounterSet(hdwf, c_int(iChannel), c_int(cLow), c_int(cHigh)) # max 32768
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+print("Generating output for 10 seconds...")
+time.sleep(10)
+
+dwf.FDwfDigitalOutReset(hdwf)
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/DigitalOut_Phase.py b/tests/py/DigitalOut_Phase.py
new file mode 100644
index 0000000000000000000000000000000000000000..8119166df6c8bb18b1d1db6be84cd6a0994d3191
--- /dev/null
+++ b/tests/py/DigitalOut_Phase.py
@@ -0,0 +1,75 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+print("Generating on 2 pins phase 180* with different initial low and high polarity")
+for i in range(0, 2):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
+    dwf.FDwfDigitalOutCounterInitSet(hdwf, c_int(i), c_uint(i==1), c_uint(50)) 
+    dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), c_uint(50), c_uint(50)) # 100MHz base freq /(50+50) = 1MHz
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+print("   for 5 seconds...")
+time.sleep(5)
+
+
+print("Generating on 3 pins 3 phases with different initial counter values")
+dwf.FDwfDigitalOutCounterInitSet(hdwf, c_int(0), c_uint(1), c_uint(0))
+dwf.FDwfDigitalOutCounterInitSet(hdwf, c_int(1), c_uint(0), c_uint(20))
+dwf.FDwfDigitalOutCounterInitSet(hdwf, c_int(2), c_uint(1), c_uint(10))
+for i in range(0, 3):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
+    dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), c_uint(30), c_uint(30)) # 100MHz base freq /(30+30) = 1.67 MHz
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+print("   for 5 seconds...")
+time.sleep(5)
+
+print("Generating on 4 pins 4 phases with different initial counter values")
+for i in range(0, 4):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
+    dwf.FDwfDigitalOutCounterInitSet(hdwf, c_int(i), c_uint((i==2) or (i==3)), c_uint(25 if (i==0 or i==2) else 50))
+    dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), c_uint(50), c_uint(50)) 
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+print("   for 5 seconds...")
+time.sleep(5)
+
+dwf.FDwfDigitalOutReset(hdwf)
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/DigitalOut_Pins.py b/tests/py/DigitalOut_Pins.py
new file mode 100644
index 0000000000000000000000000000000000000000..61b13c637ed4f62d96308b545904c4be1b90d35c
--- /dev/null
+++ b/tests/py/DigitalOut_Pins.py
@@ -0,0 +1,77 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2020-04-07
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+hdwf = c_int()
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+hzSys = c_double()
+dwf.FDwfDigitalOutInternalClockInfo(hdwf, byref(hzSys))
+
+# 1kHz pulse on IO pin 0
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(0), c_int(1))
+# prescaler to 2kHz, SystemFrequency/1kHz/2
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(0), c_int(int(hzSys.value/1e3/2)))
+# 1 tick low, 1 tick high
+dwf.FDwfDigitalOutCounterSet(hdwf, c_int(0), c_int(1), c_int(1))
+
+# 1kHz 25% duty pulse on IO pin 1
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(1), c_int(1))
+# prescaler to 4kHz SystemFrequency/1kHz/2
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(1), c_int(int(hzSys.value/1e3/4)))
+# 3 ticks low, 1 tick high
+dwf.FDwfDigitalOutCounterSet(hdwf, c_int(1), c_int(3), c_int(1))
+
+# 2kHz random on IO pin 2
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(2), c_int(1))
+dwf.FDwfDigitalOutTypeSet(hdwf, c_int(2), DwfDigitalOutTypeRandom)
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(2), c_int(int(hzSys.value/2e3)))
+dwf.FDwfDigitalOutCounterSet(hdwf, c_int(2), c_int(1), c_int(1))
+
+rgdSamples = (c_byte*6)(*[0xFF,0x80,0xC0,0xE0,0xF0,0x00])
+# 10kHz sample rate custom on IO pin 3
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(3), 1)
+dwf.FDwfDigitalOutTypeSet(hdwf, c_int(3), DwfDigitalOutTypeCustom)
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(3), c_int(int(hzSys.value/1e4)))
+dwf.FDwfDigitalOutDataSet(hdwf, c_int(3), byref(rgdSamples), c_int(6*8))
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+print("Generating output for 10 seconds...")
+time.sleep(10)
+
+dwf.FDwfDigitalOutReset(hdwf)
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/DigitalOut_Pulse.py b/tests/py/DigitalOut_Pulse.py
new file mode 100644
index 0000000000000000000000000000000000000000..23d443a96ee0fcabba0f52b7949549f9ba68c542
--- /dev/null
+++ b/tests/py/DigitalOut_Pulse.py
@@ -0,0 +1,89 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2023-01-09
+
+   Requires:                       
+       Python 2.7, 3
+   Generate pulses on trigger
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+iChannel = 0
+hzFreq = 1e6 # freq Hz
+prcDuty = 25.0 # duty %
+fPol = 1 # low or high, 0 or 1
+cPulses = 8 
+sWait = 1e-6
+
+hzSys = c_double()
+maxCnt = c_uint()
+dwf.FDwfDigitalOutInternalClockInfo(hdwf, byref(hzSys))
+dwf.FDwfDigitalOutCounterInfo(hdwf, c_int(0), 0, byref(maxCnt))
+
+# for low frequencies use divider as pre-scaler to satisfy counter limitation of 32k
+cDiv = int(math.ceil(hzSys.value/hzFreq/maxCnt.value))
+# count steps to generate the give frequency
+cPulse = int(round(hzSys.value/hzFreq/cDiv))
+# duty
+cHigh = int(cPulse*prcDuty/100)
+cLow = int(cPulse-cHigh)
+
+print("Generate: "+str(hzSys.value/cPulse/cDiv)+"Hz duty: "+str(100.0*cHigh/cPulse)+"% divider: "+str(cDiv))
+
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(iChannel), c_int(1))
+dwf.FDwfDigitalOutTypeSet(hdwf, c_int(iChannel), DwfDigitalOutTypePulse) # 
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(iChannel), c_int(cDiv)) # max 2147483649, for counter limitation or custom sample rate
+dwf.FDwfDigitalOutCounterSet(hdwf, c_int(iChannel), c_int(cLow), c_int(cHigh)) # max 32768
+dwf.FDwfDigitalOutCounterInitSet(hdwf, c_int(iChannel), c_int(fPol), c_int(0)) 
+dwf.FDwfDigitalOutRunSet(hdwf, c_double(1.0*cPulses*(cLow+cHigh)*cDiv/hzSys.value)) # seconds to run
+dwf.FDwfDigitalOutWaitSet(hdwf, c_double(sWait)) # wait after trigger
+dwf.FDwfDigitalOutRepeatSet(hdwf, c_int(0)) # infinite
+dwf.FDwfDigitalOutRepeatTriggerSet(hdwf, c_int(1))
+
+# trigger on Trigger IO 
+dwf.FDwfDigitalOutTriggerSourceSet(hdwf, trigsrcExternal1)
+
+# trigger on DIOs
+#dwf.FDwfDigitalOutTriggerSourceSet(hdwf, trigsrcDetectorDigitalIn)
+#dwf.FDwfDigitalInTriggerSet(hdwf, c_int(0), c_int(0), c_int(1<<1), c_int(0)) # DIO/DIN-1 rise
+#dwf.FDwfDigitalInConfigure(hdwf, c_int(1), c_int(1))
+
+
+print("Armed")
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/DigitalOut_ROM_Mux.py b/tests/py/DigitalOut_ROM_Mux.py
new file mode 100644
index 0000000000000000000000000000000000000000..2200bbf725a011043dec66bb61b2e4993adb3793
--- /dev/null
+++ b/tests/py/DigitalOut_ROM_Mux.py
@@ -0,0 +1,85 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision: 5/11/2018
+
+   Requires:                       
+       Python 2.7, numpy
+       python-dateutil, pyparsing
+"""
+
+from ctypes import *
+import math
+import numpy
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+hdwf = c_int(0)
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+# For a ROM logic channel the digital IO value addresses the custom buffer.
+# The least significant digital channel, up to the log2 of buffer size will be the address space. 
+# For 1024 buffer size 10 bits, DIO 0-9 will be used as address.
+# These digital IO can be either inputs or outputs.
+# The buffer containing output for each possible address value is required.
+
+customSize = c_uint() # custom buffer size in bits
+dwf.FDwfDigitalOutDataInfo(hdwf, c_int(15), byref(customSize))
+rgbSamples = (c_ubyte*(int(customSize.value/8)))()
+print("Custom size: "+str(customSize.value)+" Address space: "+str(int(numpy.log2(customSize.value))))
+
+# initialize array with zero
+for i in range(0, int(customSize.value/8)):
+    rgbSamples[i] = 0
+
+# Lets create a MUX logic with DIO-0 and 1 as input and DIO-2 as select.
+# Parse each possible address value and set desired output for each bit combination.
+for iAddress in range(0, customSize.value):
+    fDio0 = (iAddress>>0)&1 # first input
+    fDio1 = (iAddress>>1)&1 # second input
+    fDio2 = (iAddress>>2)&1 # select
+    # output 1 when (select is low and first input is high) or (select is high and second input is high):
+    if (fDio2 == 0 and fDio0 == 1) or (fDio2 == 1 and fDio1 == 1) :
+        rgbSamples[int(iAddress/8)] |= 1<<(iAddress%8)
+
+for i in range(0, 3):
+    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(0), c_int(0)) # input
+
+# DIO-15 will be used as output
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(15), c_int(1)) # enable output
+dwf.FDwfDigitalOutTypeSet(hdwf, c_int(15), c_int(3)) # DwfDigitalOutTypeROM
+# The minimum input to output delay is 60ns for Analog Discovery and 80ns for Digital Discovery
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(15), c_int(1)) # specifying division like 10 (100MHz/10 = 10MHz) will add 100ns more delay
+dwf.FDwfDigitalOutDataSet(hdwf, c_int(15), byref(rgbSamples), c_int(customSize.value))
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+try: input = raw_input
+except NameError: pass
+input("Press enter to stop")
+
+dwf.FDwfDigitalOutReset(hdwf);
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/DigitalOut_ResetPattern.py b/tests/py/DigitalOut_ResetPattern.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c5f1321bf70ca86aef36e7525a89e9e30f72a5d
--- /dev/null
+++ b/tests/py/DigitalOut_ResetPattern.py
@@ -0,0 +1,111 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2019-10-29
+
+   Requires:           
+       Python 2.7, 3
+   Description:
+   Generate a reset signal and pattern.
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import matplotlib.pyplot as plt
+import sys
+import numpy
+
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# 0 = run, 1 = stop, 2 = shutdown
+dwf.FDwfParamSet(DwfParamOnClose, c_int(1))
+
+print("Opening first device")
+hdwf = c_int()
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+hzSys = c_double()
+sts = c_byte()
+
+dwf.FDwfDigitalOutInternalClockInfo(hdwf, byref(hzSys))
+
+
+# DIO-0 or DIO-24 on Digital Discovery
+# generate 100ns high pulse after start then remain low
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(0), c_int(1))
+dwf.FDwfDigitalOutIdleSet(hdwf, c_int(0), DwfDigitalOutIdleLow) # DwfDigitalOutIdleLow = 1
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(0), c_int(int(hzSys.value*100e-9))) # 100ns (10MHz) prescaler
+dwf.FDwfDigitalOutCounterInitSet(hdwf, c_int(0), c_int(1), c_int(1)) # start high for 1 count
+dwf.FDwfDigitalOutCounterSet(hdwf, c_int(0), c_int(1), c_int(0)) # low = 1 and high = 0
+
+# DIO-1 or DIO-25 on DD
+# generate 6 byte pattern at 10MHz
+rgdSamples = (c_byte*6)(*[0xAA,0x00,0x12,0x34,0x56,0x78])
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(1), 1)
+dwf.FDwfDigitalOutTypeSet(hdwf, c_int(1), DwfDigitalOutTypeCustom)
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(1), c_int(int(hzSys.value*50e-9))) # 50ns (20MHz) prescaler
+dwf.FDwfDigitalOutDataSet(hdwf, c_int(1), byref(rgdSamples), c_int(6*8)) # 6x8 bits
+dwf.FDwfDigitalOutDividerInitSet(hdwf, c_int(1), c_int(int(hzSys.value*200e-9))) # divider init, first bit length 200ns
+
+# run for the required time: init + (bits-1)/prescaler
+dwf.FDwfDigitalOutRunSet(hdwf, c_double(200e-9 + (6*8 - 1) * 50e-9))
+dwf.FDwfDigitalOutRepeatSet(hdwf, c_int(1)) # repeat once
+
+
+hzDI = c_double()
+dwf.FDwfDigitalInInternalClockInfo(hdwf, byref(hzDI))
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(int(hzDI.value/100e6))) # 100MHz
+# 16bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(16))
+# set number of sample to acquire
+cSamples = 500
+rgwSamples = (c_uint16*cSamples)()
+dwf.FDwfDigitalInBufferSizeSet(hdwf, c_int(cSamples))
+
+# DIO first for Digital Discovery 
+dwf.FDwfDigitalInInputOrderSet(hdwf, c_int(1))
+dwf.FDwfDigitalInTriggerSourceSet(hdwf, c_ubyte(3)) # trigsrcDetectorDigitalIn
+dwf.FDwfDigitalInTriggerSet(hdwf, c_int(0), c_int(0), c_int(0x0003), c_int(0x0003)) 
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(int(cSamples*8/10-1))) # trigger at 20%, 80% after trigger
+
+# begin acquisition
+dwf.FDwfDigitalInConfigure(hdwf, c_int(1), c_int(1))
+time.sleep(1) # wait for prefill
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+print("Waiting for acquisition...")
+while True:
+    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+    if sts.value == stsDone.value :
+        break
+    time.sleep(1)
+print("   done")
+
+# get samples, byte size
+dwf.FDwfDigitalInStatusData(hdwf, rgwSamples, 2*cSamples)
+dwf.FDwfDeviceCloseAll()
+
+plt.plot(numpy.fromiter(rgwSamples, dtype = numpy.uint16))
+plt.show()
\ No newline at end of file
diff --git a/tests/py/DigitalOut_SPI.py b/tests/py/DigitalOut_SPI.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ba771d557fa98fab511d43815cfe46a435d8b51
--- /dev/null
+++ b/tests/py/DigitalOut_SPI.py
@@ -0,0 +1,89 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision: 5/11/2018
+
+   Requires:                       
+       Python 2.7, numpy
+       python-dateutil, pyparsing
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import time
+import sys
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+# continue running after device close
+dwf.FDwfParamSet(DwfParamOnClose, c_int(1))
+
+hdwf = c_int(0)
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+# the device will only be configured when FDwf###Configure is called
+dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) 
+
+hzSys = c_double()
+dwf.FDwfDigitalOutInternalClockInfo(hdwf, byref(hzSys))
+
+# SPI parameters
+CPOL = 0 # or 1
+CPHA = 0 # or 1
+hzFreq = 1e6
+cBits = 16
+rgdData = (2*c_byte)(*[0x12,0x34])
+
+# serialization time length
+dwf.FDwfDigitalOutRunSet(hdwf, c_double((cBits+0.5)/hzFreq))
+
+# DIO 2 Select 
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(2), c_int(1))
+# output high while DigitalOut not running
+dwf.FDwfDigitalOutIdleSet(hdwf, c_int(2), c_int(2)) # 2=DwfDigitalOutIdleHigh
+# output constant low while running
+dwf.FDwfDigitalOutCounterInitSet(hdwf, c_int(2), c_int(0), c_int(0))
+dwf.FDwfDigitalOutCounterSet(hdwf, c_int(2), c_int(0), c_int(0))
+
+# DIO 1 Clock
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(1), c_int(1))
+# set prescaler twice of SPI frequency
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(1), c_int(int(hzSys.value/hzFreq/2)))
+# 1 tick low, 1 tick high
+dwf.FDwfDigitalOutCounterSet(hdwf, c_int(1), c_int(1), c_int(1))
+# start with low or high based on clock polarity
+dwf.FDwfDigitalOutCounterInitSet(hdwf, c_int(1), c_int(CPOL), c_int(1))
+dwf.FDwfDigitalOutIdleSet(hdwf, c_int(1), c_int(1+CPOL)) # 1=DwfDigitalOutIdleLow 2=DwfDigitalOutIdleHigh
+
+# DIO 0 Data
+dwf.FDwfDigitalOutEnableSet(hdwf, c_int(0), 1)
+dwf.FDwfDigitalOutTypeSet(hdwf, c_int(0), c_int(1)) # 1=DwfDigitalOutTypeCustom
+# for high active clock, hold the first bit for 1.5 periods 
+dwf.FDwfDigitalOutDividerInitSet(hdwf, c_int(0), c_int(int((1+0.5*CPHA)*hzSys.value/hzFreq))) 
+# SPI frequency, bit frequency
+dwf.FDwfDigitalOutDividerSet(hdwf, c_int(0), c_int(int(hzSys.value/hzFreq)))
+# data sent out LSB first
+dwf.FDwfDigitalOutDataSet(hdwf, c_int(0), byref(rgdData), c_int(cBits))
+
+
+dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Digital_Can.py b/tests/py/Digital_Can.py
new file mode 100644
index 0000000000000000000000000000000000000000..6aaef1689a48c70d5668a8dea89ca1bdfeff8af4
--- /dev/null
+++ b/tests/py/Digital_Can.py
@@ -0,0 +1,82 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+
+print("Opening first device")
+#dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+# device configuration of index 3 (4th) for Analog Discovery has 16kS digital-in/out buffer
+dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf)) 
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring CAN...")
+
+
+dwf.FDwfDigitalCanRateSet(hdwf, c_double(1e6)) # 1MHz
+dwf.FDwfDigitalCanPolaritySet(hdwf, c_int(0)) # normal
+dwf.FDwfDigitalCanTxSet(hdwf, c_int(0)) # TX = DIO-0
+dwf.FDwfDigitalCanRxSet(hdwf, c_int(1)) # RX = DIO-1
+
+#                    HDWF  ID         Extended  Remote    DLC      *rgTX
+dwf.FDwfDigitalCanTx(hdwf, c_int(-1), c_int(0), c_int(0), c_int(0), None) # initialize TX, drive with idle level
+#                    HDWF *ID   *Exte *Remo *DLC  *rgRX  cRX      *Status 0 = no data, 1 = data received, 2 = bit stuffing error, 3 = CRC error
+dwf.FDwfDigitalCanRx(hdwf, None, None, None, None, None, c_int(0), None) # initialize RX reception
+
+time.sleep(1)
+
+rgbTX = (c_ubyte*4)(0,1,2,3)
+vID  = c_int()
+fExtended  = c_int()
+fRemote  = c_int()
+cDLC = c_int()
+vStatus  = c_int()
+rgbRX = (c_ubyte*8)()
+
+print("Sending on TX...")
+#                    HDWF  ID           fExtended  fRemote   cDLC              *rgTX
+dwf.FDwfDigitalCanTx(hdwf, c_int(0x3FD), c_int(0), c_int(0), c_int(len(rgbTX)), rgbTX) 
+
+tsec = time.clock() + 10 # receive for 10 seconds
+print("Receiving on RX for 10 seconds...")
+while time.clock() < tsec:
+    time.sleep(0.01)
+    #                    HDWF *ID          *Extended        *Remote         *DLC         *rgRX   cRX                  *Status
+    dwf.FDwfDigitalCanRx(hdwf, byref(vID), byref(fExtended), byref(fRemote), byref(cDLC), rgbRX, c_int(sizeof(rgbRX)), byref(vStatus)) 
+    if vStatus.value != 0:
+        print("RX: "+('0x{:08x}'.format(vID.value)) +" "+("Extended " if fExtended.value!=0 else "")+("Remote " if fRemote.value!=0 else "")+"DLC: "+str(cDLC.value))
+        if vStatus.value == 1:
+            print("no error")
+        elif vStatus.value == 2:
+            print("bit stuffing error")
+        elif vStatus.value == 3:
+            print("CRC error")
+        else:
+            print("error")
+        if fRemote.value == 0 and cDLC.value != 0:
+            print("Data: "+(" ".join("0x{:02x}".format(c) for c in rgbRX[0:cDLC.value])))
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Digital_I2c.py b/tests/py/Digital_I2c.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc776ef3a921ab40a070bbe28d0b63bb0474ea2e
--- /dev/null
+++ b/tests/py/Digital_I2c.py
@@ -0,0 +1,69 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+
+print("Opening first device")
+#dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+# device configuration of index 3 (4th) for Analog Discovery has 16kS digital-in/out buffer
+dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf)) 
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring I2C...")
+
+iNak = c_int()
+
+dwf.FDwfDigitalI2cRateSet(hdwf, c_double(1e5)) # 100kHz
+dwf.FDwfDigitalI2cSclSet(hdwf, c_int(0)) # SCL = DIO-0
+dwf.FDwfDigitalI2cSdaSet(hdwf, c_int(1)) # SDA = DIO-1
+dwf.FDwfDigitalI2cClear(hdwf, byref(iNak))
+if iNak.value == 0:
+    print("I2C bus error. Check the pull-ups.")
+    quit()
+time.sleep(1)
+
+rgTX = (c_ubyte*16)(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
+rgRX = (c_ubyte*16)()
+
+print("Separate Write and Read:")
+#                                8bit address  
+dwf.FDwfDigitalI2cWrite(hdwf, c_int(0x1D<<1), rgTX, c_int(16), byref(iNak)) # write 16 bytes
+time.sleep(0.1)
+
+dwf.FDwfDigitalI2cRead(hdwf, c_int(0x1D<<1), rgRX, c_int(16), byref(iNak)) # read 16 bytes
+if iNak.value != 0:
+    print("NAK "+str(iNak.value))
+print(list(rgRX))
+time.sleep(0.1)
+
+print("Write and Read with reStart:")
+dwf.FDwfDigitalI2cWriteRead(hdwf, c_int(0x1D<<1), rgTX, c_int(1), rgRX, c_int(16), byref(iNak)) # write 1 byte restart and read 16 bytes
+if iNak.value != 0:
+    print("NAK "+str(iNak.value))
+print(list(rgRX))
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Digital_I2c_PmodAcl.py b/tests/py/Digital_I2c_PmodAcl.py
new file mode 100644
index 0000000000000000000000000000000000000000..bbf214edc7543697423d04255c4585cc5a4a074b
--- /dev/null
+++ b/tests/py/Digital_I2c_PmodAcl.py
@@ -0,0 +1,93 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2019-02-12
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+
+# continue running after device close
+dwf.FDwfParamSet(c_int(4), c_int(0)) # 4 = DwfParamOnClose, 0 = run 1 = stop 2 = shutdown
+
+hdwf = c_int()
+
+print("Opening first device")
+#dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+# device configuration of index 3 (4th) for Analog Discovery has 16kS digital-in/out buffer
+dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf)) 
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring I2C...")
+
+iNak = c_int()
+
+dwf.FDwfDigitalI2cReset()
+dwf.FDwfDigitalI2cStretchSet(hdwf, c_int(1)) # clock stretching
+dwf.FDwfDigitalI2cRateSet(hdwf, c_double(1e5)) # 100kHz
+dwf.FDwfDigitalI2cSclSet(hdwf, c_int(0)) # SCL = DIO-0
+dwf.FDwfDigitalI2cSdaSet(hdwf, c_int(1)) # SDA = DIO-1
+dwf.FDwfDigitalI2cClear(hdwf, byref(iNak))
+if iNak.value == 0:
+    print("I2C bus error. Check the pull-ups.")
+    quit()
+time.sleep(1)
+
+adr = 0x1D;
+
+#                                8bit address  
+dwf.FDwfDigitalI2cWrite(hdwf, c_int(adr<<1), 0, c_int(0), byref(iNak)) # write 0 bytes
+if iNak.value != 0:
+    print("Device test NAK "+str(iNak.value))
+    quit()
+
+rgPower = (c_ubyte*2)(0x2D, 0x08) # POWER_CTL | Measure
+dwf.FDwfDigitalI2cWrite(hdwf, c_int(adr<<1), rgPower, c_int(2), byref(iNak)) # write 2 bytes
+if iNak.value != 0:
+    print("Device power NAK "+str(iNak.value))
+    quit()
+
+rgFormat = (c_ubyte*2)(0x31, 0x08) # DATA_FORMAT | FULL_RES
+dwf.FDwfDigitalI2cWrite(hdwf, c_int(adr<<1), rgFormat, c_int(2), byref(iNak)) # write 2 bytes
+if iNak.value != 0: 
+    print("Device format NAK"+str(iNak.value))
+    quit()
+
+for i in range(10):
+    time.sleep(0.5);
+
+    rgData = (c_ubyte*1)(0xF2)
+    rgAcc = (c_int16*3)()
+    dwf.FDwfDigitalI2cWriteRead(hdwf, c_int(adr<<1), rgData, c_int(1), rgAcc, c_int(6), byref(iNak)) # write 1 byte, restart, read 6 bytes
+    if iNak.value != 0:
+        print("Device Data NAK "+str(iNak.value))
+        #quit()
+
+    # convert data to gravitational constant
+    x = rgAcc[0]/256 
+    y = rgAcc[1]/256 
+    z = rgAcc[2]/256 
+    g = math.sqrt(math.pow(x,2)+math.pow(y,2)+math.pow(z,2))
+    print(f"G: {g:.3f} \tX: {x:.3f} \tY: {y:.3f} \tZ: {z:.3f}")
+
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Digital_I2c_PmodGyro.py b/tests/py/Digital_I2c_PmodGyro.py
new file mode 100644
index 0000000000000000000000000000000000000000..527ee65719d8dd9a8ebb602955c13f1aba951f52
--- /dev/null
+++ b/tests/py/Digital_I2c_PmodGyro.py
@@ -0,0 +1,107 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2019-02-12
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+
+# continue running after device close
+dwf.FDwfParamSet(c_int(4), c_int(0)) # 4 = DwfParamOnClose, 0 = run 1 = stop 2 = shutdown
+
+hdwf = c_int()
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+# device configuration of index 3 (4th) for Analog Discovery has 16kS digital-in/out buffer
+#dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf)) 
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+# for Digital Discovery:
+# set digital voltage between 1.2 and 3.3V
+#dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(0), c_double(3.3))
+# enable VIO output
+#dwf.FDwfAnalogIOEnableSet(hdwf, c_int(1))
+# pull enable for DIO 39 to 24, bit 15 to 0
+#dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(2), c_double(0xFFFF)) 
+# pull up/down for all DIOs
+#dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(3), c_double(0xFFFF)) 
+
+
+print("Configuring I2C...")
+
+iNak = c_int()
+
+dwf.FDwfDigitalI2cReset()
+dwf.FDwfDigitalI2cStretchSet(hdwf, c_int(1)) # clock stretching
+dwf.FDwfDigitalI2cRateSet(hdwf, c_double(1e5)) # 100kHz
+dwf.FDwfDigitalI2cSclSet(hdwf, c_int(0)) # SCL = DIO-0
+dwf.FDwfDigitalI2cSdaSet(hdwf, c_int(1)) # SDA = DIO-1
+dwf.FDwfDigitalI2cClear(hdwf, byref(iNak))
+if iNak.value == 0:
+    print("I2C bus error. Check the pull-ups.")
+    quit()
+
+
+adr = 0x69;
+
+dwf.FDwfDigitalI2cWrite(hdwf, c_int(adr<<1), 0, c_int(0), byref(iNak)) # write 0 bytes
+if iNak.value != 0:
+    print("Device test NAK "+str(iNak.value))
+    quit()
+
+rgID = (c_ubyte*1)(0x0F)
+dwf.FDwfDigitalI2cWriteRead(hdwf, c_int(adr<<1), rgID, c_int(1), rgID, c_int(1), byref(iNak)) # write 1 byte, restart, read 1 byte
+if iNak.value != 0:
+    print("Device power NAK "+str(iNak.value))
+    quit()
+    
+if rgID[0] != 0xD3:
+    print("Device ID mismatch "+str(rgID[0]))
+    quit()
+
+rgReg1 = (c_ubyte*2)(0x20, 0x0F)
+dwf.FDwfDigitalI2cWrite(hdwf, c_int(adr<<1), rgReg1, c_int(2), byref(iNak)) # write 2 bytes
+if iNak.value != 0:
+    print("Device reg1 NAK "+str(iNak.value))
+    quit()
+
+for i in range(10):
+    time.sleep(0.5);
+
+    rgData = (c_ubyte*1)(0xA8)
+    rgAcc = (c_int16*3)()
+    dwf.FDwfDigitalI2cWriteRead(hdwf, c_int(adr<<1), rgData, c_int(1), rgAcc, c_int(6), byref(iNak)) # write 1 byte, restart, read 6 bytes
+    if iNak.value != 0:
+        print("Device Data NAK "+str(iNak.value))
+        #quit()
+
+    # convert data bits to signed value relative to gravitational constant
+    x = 0.004*rgAcc[0]
+    y = 0.004*rgAcc[1] 
+    z = 0.004*rgAcc[2]
+    a = math.sqrt(math.pow(x,2)+math.pow(y,2)+math.pow(z,2))
+    print(f"A: {a:.3f} \tX: {x:.3f} \tY: {y:.3f} \tZ: {z:.3f}")
+
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Digital_Spi.py b/tests/py/Digital_Spi.py
new file mode 100644
index 0000000000000000000000000000000000000000..1e0c42075caf8f8011afc0f03b9407fb4a1052b7
--- /dev/null
+++ b/tests/py/Digital_Spi.py
@@ -0,0 +1,70 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import sys
+import time
+import numpy
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+
+print("Opening first device")
+#dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+# device configuration of index 3 (4th) for Analog Discovery has 16kS digital-in/out buffer
+dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf)) 
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring SPI...")
+dwf.FDwfDigitalSpiFrequencySet(hdwf, c_double(1e3))
+dwf.FDwfDigitalSpiClockSet(hdwf, c_int(1))
+dwf.FDwfDigitalSpiDataSet(hdwf, c_int(0), c_int(2)) # 0 DQ0_MOSI_SISO = DIO-2
+dwf.FDwfDigitalSpiDataSet(hdwf, c_int(1), c_int(3)) # 1 DQ1_MISO = DIO-3
+dwf.FDwfDigitalSpiIdleSet(hdwf, c_int(0), c_int(3)) # 0 DQ0_MOSI_SISO = DwfDigitalOutIdleZet
+dwf.FDwfDigitalSpiIdleSet(hdwf, c_int(1), c_int(3)) # 1 DQ1_MISO = DwfDigitalOutIdleZet
+dwf.FDwfDigitalSpiModeSet(hdwf, c_int(0))
+dwf.FDwfDigitalSpiOrderSet(hdwf, c_int(1)) # 1 MSB first
+dwf.FDwfDigitalSpiSelectSet(hdwf, c_int(0), c_int(1)) # CS: DIO-0, idle high
+# cDQ 0 SISO, 1 MOSI/MISO, 2 dual, 4 quad
+#                                cDQ       bits 0    data 0
+dwf.FDwfDigitalSpiWriteOne(hdwf, c_int(1), c_int(0), c_int(0)) # start driving the channels, clock and data
+time.sleep(10)
+
+rgbTX = (c_ubyte*10)(0,1,2,3,4,5,6,7,8,9)
+rgbRX = (c_ubyte*10)()
+rgdw = c_uint32()
+
+# cDQ 1 MOSI/MISO, 8bit words, MOSI words, MISO words
+dwf.FDwfDigitalSpiWriteRead(hdwf, c_int(1), c_int(8), rgbTX, c_int(len(rgbTX)), rgbRX, c_int(len(rgbRX))) 
+print("TX: "+str(numpy.fromiter(rgbTX, dtype = numpy.uint8)))
+print("RX: "+str(numpy.fromiter(rgbRX, dtype = numpy.uint8)))
+
+
+dwf.FDwfDigitalSpiWriteOne(hdwf, c_int(1), c_int(8), c_uint(0xAB)) # write 1 byte to MOSI
+
+dwf.FDwfDigitalSpiReadOne(hdwf, c_int(1), c_int(24), byref(rgdw)) # read 24 bits from MISO
+
+dwf.FDwfDigitalSpiWrite(hdwf, c_int(1), c_int(8), rgbTX, c_int(len(rgbTX))) # write array of 8 bit (byte) length elements
+
+dwf.FDwfDigitalSpiRead(hdwf, c_int(1), c_int(8), rgbRX, c_int(len(rgbRX))) # read array of 8 bit (byte) length elements
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Digital_Spi_Dual.py b/tests/py/Digital_Spi_Dual.py
new file mode 100644
index 0000000000000000000000000000000000000000..2fb6ac71fd400854c032a76486fee3acb785d3fe
--- /dev/null
+++ b/tests/py/Digital_Spi_Dual.py
@@ -0,0 +1,60 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+
+dwf.FDwfParamSet(c_int(4), c_int(2)) # DwfParamOnClose run, keep device running on close, kee the SPI lines driven after close
+
+print("Opening first device")
+#dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+# device configuration of index 3 (4th) for Analog Discovery has 16kS digital-in/out buffer
+dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf)) 
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring SPI...")
+dwf.FDwfDigitalSpiFrequencySet(hdwf, c_double(1e4))
+dwf.FDwfDigitalSpiClockSet(hdwf, c_int(1))
+dwf.FDwfDigitalSpiDataSet(hdwf, c_int(0), c_int(2)) # 0 DQ0_MOSI_SISO = DIO-2
+dwf.FDwfDigitalSpiDataSet(hdwf, c_int(1), c_int(3)) # 1 DQ1_MISO = DIO-3
+dwf.FDwfDigitalSpiModeSet(hdwf, c_int(0)) # SPI mode 
+dwf.FDwfDigitalSpiOrderSet(hdwf, c_int(1)) # 1 MSB first
+dwf.FDwfDigitalSpiSelectSet(hdwf, c_int(0), c_int(1)) # CS DIO-0, idle high
+# cDQ 0 SISO, 1 MOSI/MISO, 2 dual, 4 quad
+#                                cDQ dual  bits 0    data 0
+dwf.FDwfDigitalSpiWriteOne(hdwf, c_int(2), c_int(0), c_int(0)) # start driving the channels, clock and data
+time.sleep(1)
+
+fsCmd = c_uint16(0xABCB)
+rgbTX = (c_ubyte*16)(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
+rgwRX = (c_uint16*8)()
+
+# 12bit command, 0x12D command, 0 dummy bits, 2 dual mode, 8bit words, word array, number of words
+dwf.FDwfDigitalSpiCmdWrite(hdwf, c_int(12), c_int(0x12D), c_int(0), c_int(2), c_int(8), rgbTX, c_int(len(rgbTX))) 
+
+# 16bit command, command, 0 dummy bits, 2 dual mode, 12bit words, read buffer, number of words
+dwf.FDwfDigitalSpiCmdRead16(hdwf, c_int(16), fsCmd, c_int(0), c_int(2), c_int(12), rgwRX, c_int(len(rgwRX)))
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Digital_Spi_Quad.py b/tests/py/Digital_Spi_Quad.py
new file mode 100644
index 0000000000000000000000000000000000000000..99afde4f2957a9147f8ba9a0d458d52450f2f9c6
--- /dev/null
+++ b/tests/py/Digital_Spi_Quad.py
@@ -0,0 +1,64 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+
+print("Opening first device")
+#dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+# device configuration of index 3 (4th) for Analog Discovery has 16kS digital-in/out buffer
+dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf)) 
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring SPI...")
+dwf.FDwfDigitalSpiFrequencySet(hdwf, c_double(1e3))
+dwf.FDwfDigitalSpiClockSet(hdwf, c_int(1))
+dwf.FDwfDigitalSpiDataSet(hdwf, c_int(0), c_int(2)) # 0 DQ0_MOSI_SISO = DIO-2
+dwf.FDwfDigitalSpiDataSet(hdwf, c_int(1), c_int(3)) # 1 DQ1_MISO = DIO-3
+dwf.FDwfDigitalSpiDataSet(hdwf, c_int(2), c_int(4)) # 2 DQ2 = DIO-4
+dwf.FDwfDigitalSpiDataSet(hdwf, c_int(3), c_int(5)) # 3 DQ3 = DIO-5
+dwf.FDwfDigitalSpiModeSet(hdwf, c_int(0)) # SPI mode 
+dwf.FDwfDigitalSpiOrderSet(hdwf, c_int(1)) # 1 MSB first
+#                              DIO       value: 0 low, 1 high, -1 high impedance
+dwf.FDwfDigitalSpiSelectSet(hdwf, c_int(0), c_int(1)) # CS: DIO-0, idle high
+# cDQ 0 SISO, 1 MOSI/MISO, 2 dual, 4 quad, // 1-32 bits / word
+#                                cDQ       bits     data
+dwf.FDwfDigitalSpiWriteOne(hdwf, c_int(4), c_int(0), c_int(0)) # start driving the channels
+time.sleep(1)
+
+rgbCmd = (c_ubyte*2)(0xAB,0xCB)
+rgdwTX = (c_uint32*16)(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
+rgbRX = (c_ubyte*8)()
+
+# 8bit command, 0x1D command, 0 dummy bits, 4 quad mode, 24but words, word array, number of words
+dwf.FDwfDigitalSpiWrite32(hdwf, c_int(8), c_int(0x1D), c_int(0), c_int(4), c_int(24), rgdwTX, c_int(len(rgdwTX))) 
+
+dwf.FDwfDigitalSpiSelect(hdwf, c_int(0), c_int(0)) # software control of select
+dwf.FDwfDigitalSpiWrite(hdwf, c_int(1), c_int(8), rgbCmd, c_int(len(rgbCmd))) # write 2 bytes to MOSI
+dwf.FDwfDigitalSpiRead(hdwf, c_int(4), c_int(8), rgbRX, c_int(len(rgbRX)))  # read to array of 8bit(byte) elements in dual mode 8bit data lengths
+dwf.FDwfDigitalSpiSelect(hdwf, c_int(0), c_int(1)) # CS DIO-0 high
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Digital_Spi_Siso.py b/tests/py/Digital_Spi_Siso.py
new file mode 100644
index 0000000000000000000000000000000000000000..541befa0580c82ef83b51ea69ebcde7ab10a4de5
--- /dev/null
+++ b/tests/py/Digital_Spi_Siso.py
@@ -0,0 +1,66 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+
+print("Opening first device")
+#dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+# device configuration of index 3 (4th) for Analog Discovery has 16kS digital-in/out buffer
+dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf)) 
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring SPI...")
+dwf.FDwfDigitalSpiFrequencySet(hdwf, c_double(1e3))
+dwf.FDwfDigitalSpiClockSet(hdwf, c_int(1))
+dwf.FDwfDigitalSpiDataSet(hdwf, c_int(0), c_int(2)) # 0 DQ0_MOSI_SISO = DIO-2
+dwf.FDwfDigitalSpiModeSet(hdwf, c_int(0)) # SPI mode 
+dwf.FDwfDigitalSpiOrderSet(hdwf, c_int(1)) # 1 MSB first
+dwf.FDwfDigitalSpiSelectSet(hdwf, c_int(0), c_int(1)) # CS DIO-0, idle high
+
+# cDQ 0 SISO, 1 MOSI/MISO, 2 dual, 4 quad
+#                                cDQ       bits 0    data 0
+dwf.FDwfDigitalSpiWriteOne(hdwf, c_int(0), c_int(0), c_int(0)) # start driving the channels
+time.sleep(1)
+
+rgwRX1 = (c_uint16*10)()
+rgwRX2 = (c_uint16*20)()
+dw = c_uint32()
+
+# 0 SISO mode, 16bit words, word
+dwf.FDwfDigitalSpiWriteOne(hdwf, c_int(0), c_int(16), c_uint(0x1234))
+
+# 16bit command, 0x1234 command, 0 dummy bits, 0 SISO mode, 24bit word, pointer to read variable
+dwf.FDwfDigitalSpiCmdReadOne(hdwf, c_int(16), c_uint(0x1234), c_int(0), c_int(0), c_int(24), byref(dw))
+
+dwf.FDwfDigitalSpiSelect(hdwf, c_int(0), c_int(0)) # Select software control DIO-0 = 0
+dwf.FDwfDigitalSpiWriteOne(hdwf, c_int(0), c_int(16), c_uint(0x1234))) # write 16 bits
+# 0 SISO mode, 12bit words, read buffer, number of words
+dwf.FDwfDigitalSpiRead16(hdwf, c_int(0), c_int(12), rgwRX1, c_int(len(rgwRX1)))
+dwf.FDwfDigitalSpiRead16(hdwf, c_int(0), c_int(12), rgwRX2, c_int(len(rgwRX2)))
+dwf.FDwfDigitalSpiSelect(hdwf, c_int(0), c_int(1)) # Select software control DIO-0 = 1
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Digital_Spi_Spy.py b/tests/py/Digital_Spi_Spy.py
new file mode 100644
index 0000000000000000000000000000000000000000..f492743211a398527dcae25a4f4ad35e1e948644
--- /dev/null
+++ b/tests/py/Digital_Spi_Spy.py
@@ -0,0 +1,130 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2023-02-03
+
+   Requires:                       
+       Python 2.7, 3
+   Description:
+   Intended to be used with Digital Discovery.
+   Decodes SPI communication.
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import sys
+import ctypes
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring Digital In...")
+
+nSamples = 100000
+rgbSamples = (c_uint8*nSamples)()
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+
+idxCS = 0 # DIO-0
+idxClk = 1 # DIO-1
+idxMosi = 2 # DIO-2
+idxMiso = 3 # DIO-3
+nBits = 8
+
+print("Configuring SPI spy...")
+# record mode
+dwf.FDwfDigitalInAcquisitionModeSet(hdwf, acqmodeRecord)
+# for sync mode set divider to -1 
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(-1))
+# 8bit per sample format DIO 0:7
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(8))
+# continuous sampling 
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(-1))
+# in sync mode the trigger is used for sampling condition
+# trigger detector mask:          low &     high    & ( rising                     | falling )
+dwf.FDwfDigitalInTriggerSet(hdwf, c_int(0), c_int(0), c_int((1<<idxClk)|(1<<idxCS)), c_int(0))
+# sample on clock rising edge for sampling bits, or CS rising edge to detect frames
+
+dwf.FDwfDigitalInConfigure(hdwf, c_int(0), c_int(1))
+
+try:
+    fsMosi = 0
+    fsMiso = 0
+    cBit = 0
+    rgMosi = []
+    rgMiso = []
+    while True:
+    
+        dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+        dwf.FDwfDigitalInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+
+        if cLost.value :
+            print("Samples were lost!")
+        if cCorrupted.value :
+            print("Samples could be corrupted!")
+        if cAvailable.value > nSamples :
+            cAvailable = c_int(nSamples)
+
+        dwf.FDwfDigitalInStatusData(hdwf, rgbSamples, c_int(cAvailable.value)) # 8bit data
+        
+        for i in range(cAvailable.value):
+            v = rgbSamples[i]
+            if (v>>idxCS)&1: # CS high, inactive, print data
+                if len(rgMosi) != 0 :
+                    print("MOSI:", end=" ")
+                    for j in range(len(rgMosi)) :
+                        print("h%02X," % rgMosi[j], end=" ")
+                    print("")
+                if len(rgMiso) != 0 :
+                    print("MISO:", end=" ")
+                    for j in range(len(rgMiso)) :
+                        print("h%02X," % rgMiso[j], end=" ")
+                    print("")
+                if cBit != 0: # log leftover bits, frame not multiple of nBits
+                    print("leftover bits %d : h%02X | h%02X" % (cBit, fsMosi, fsMiso))
+                cBit = 0
+                fsMosi = 0
+                fsMiso = 0
+                rgMosi.clear()
+                rgMiso.clear()
+            else:
+                cBit+=1
+                fsMosi <<= 1 # MSB first
+                fsMiso <<= 1 # MSB first
+                if (v>>idxMosi)&1 :
+                    fsMosi |= 1
+                if (v>>idxMiso)&1 :
+                    fsMiso |= 1
+                if cBit >= nBits: # got nBits of bits
+                    rgMosi.append(fsMosi)
+                    rgMiso.append(fsMiso)
+                    cBit = 0
+                    fsMosi = 0
+                    fsMiso = 0
+except KeyboardInterrupt:
+    pass
+
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/Digital_Spi_Spy_DD.py b/tests/py/Digital_Spi_Spy_DD.py
new file mode 100644
index 0000000000000000000000000000000000000000..8ea7cee3f17a520a0d4fe369b9cf037fe12aa869
--- /dev/null
+++ b/tests/py/Digital_Spi_Spy_DD.py
@@ -0,0 +1,136 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2023-02-03
+
+   Requires:                       
+       Python 2.7, 3
+   Description:
+   Intended to be used with Digital Discovery.
+   Decodes SPI communication.
+"""
+
+from ctypes import *
+from dwfconstants import *
+import math
+import sys
+import ctypes
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+sts = c_byte()
+
+version = create_string_buffer(16)
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring Digital In...")
+
+nSamples = 100000
+rgdwSamples = (c_uint32*nSamples)()
+cAvailable = c_int()
+cLost = c_int()
+cCorrupted = c_int()
+
+# 0 represents DIO-24 with order 1
+idxCS = 0 # DIO-24
+idxClk = 1 # DIO-25
+idxMosi = 2 # DIO-26
+idxMiso = 3 # DIO-27
+nBits = 8
+
+print("Configuring SPI spy...")
+# record mode
+dwf.FDwfDigitalInAcquisitionModeSet(hdwf, acqmodeRecord)
+# for sync mode set divider to -1 
+dwf.FDwfDigitalInDividerSet(hdwf, c_int(-1))
+# 32bit per sample format
+dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(32))
+# noise samples
+dwf.FDwfDigitalInSampleModeSet(hdwf, c_int(1)) 
+# continuous sampling 
+dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(-1))
+# in sync mode the trigger is used for sampling condition
+# trigger detector mask:          low &     high    & ( rising                     | falling )
+dwf.FDwfDigitalInTriggerSet(hdwf, c_int(0), c_int(0), c_int((1<<idxClk)|(1<<idxCS)), c_int(0))
+# sample on clock rising edge for sampling bits, or CS rising edge to detect frames
+
+# for Digital Discovery bit order: DIO24:39; with 32 bit sampling [DIO24:39 + DIN0:15]
+dwf.FDwfDigitalInInputOrderSet(hdwf, c_int(1))
+
+dwf.FDwfDigitalInConfigure(hdwf, c_int(0), c_int(1))
+
+try:
+    fsMosi = 0
+    fsMiso = 0
+    cBit = 0
+    rgMosi = []
+    rgMiso = []
+    while True:
+        
+        dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
+        dwf.FDwfDigitalInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
+
+        if cLost.value :
+            print("Samples were lost!")
+        if cCorrupted.value :
+            print("Samples could be corrupted!")
+        if cAvailable.value > nSamples :
+            cAvailable = c_int(nSamples)
+        
+        dwf.FDwfDigitalInStatusData(hdwf, rgdwSamples, c_int(cAvailable.value*4)) # 32bit data
+        
+        for i in range(cAvailable.value):
+            v = rgdwSamples[i]
+            if (v>>idxCS)&1: # CS high, inactive, print data
+                if len(rgMosi) != 0 :
+                    print("MOSI:", end=" ")
+                    for j in range(len(rgMosi)) :
+                        print("h%02X," % rgMosi[j], end=" ")
+                    print("")
+                if len(rgMiso) != 0 :
+                    print("MISO:", end=" ")
+                    for j in range(len(rgMiso)) :
+                        print("h%02X," % rgMiso[j], end=" ")
+                    print("")
+                if cBit != 0: # log leftover bits, frame not multiple of nBits
+                    print("leftover bits %d : h%02X | h%02X" % (cBit, fsMosi, fsMiso))
+                cBit = 0
+                fsMosi = 0
+                fsMiso = 0
+                rgMosi.clear()
+                rgMiso.clear()
+            else:
+                cBit+=1
+                fsMosi <<= 1 # MSB first
+                fsMiso <<= 1 # MSB first
+                if (v>>idxMosi)&1 :
+                    fsMosi |= 1
+                if (v>>idxMiso)&1 :
+                    fsMiso |= 1
+                if cBit >= nBits: # got nBits of bits
+                    rgMosi.append(fsMosi)
+                    rgMiso.append(fsMiso)
+                    cBit = 0
+                    fsMosi = 0
+                    fsMiso = 0
+except KeyboardInterrupt:
+    pass
+
+dwf.FDwfDeviceClose(hdwf)
diff --git a/tests/py/Digital_Uart.py b/tests/py/Digital_Uart.py
new file mode 100644
index 0000000000000000000000000000000000000000..bd9e21cfee6805fdd829ab50889425b300e160e6
--- /dev/null
+++ b/tests/py/Digital_Uart.py
@@ -0,0 +1,70 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-23
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+# device configuration of index 3 (4th) for Analog Discovery has 16kS digital-in/out buffer
+#dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf)) 
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring UART...")
+
+cRX = c_int(0)
+fParity = c_int(0)
+
+# configure the I2C/TWI, default settings
+dwf.FDwfDigitalUartRateSet(hdwf, c_double(9600)) # 9.6kHz
+dwf.FDwfDigitalUartTxSet(hdwf, c_int(0)) # TX = DIO-0
+dwf.FDwfDigitalUartRxSet(hdwf, c_int(1)) # RX = DIO-1
+dwf.FDwfDigitalUartBitsSet(hdwf, c_int(8)) # 8 bits
+dwf.FDwfDigitalUartParitySet(hdwf, c_int(0)) # 0 no parity, 1 even, 2 odd, 3 mark (high), 4 space (low)
+dwf.FDwfDigitalUartStopSet(hdwf, c_double(1)) # 1 bit stop length
+
+dwf.FDwfDigitalUartTx(hdwf, None, c_int(0))# initialize TX, drive with idle level
+dwf.FDwfDigitalUartRx(hdwf, None, c_int(0), byref(cRX), byref(fParity))# initialize RX reception
+time.sleep(1)
+
+rgTX = create_string_buffer(b'Hello\r\n')
+rgRX = create_string_buffer(8193)
+
+print("Sending on TX for 10 seconds...")
+dwf.FDwfDigitalUartTx(hdwf, rgTX, c_int(sizeof(rgTX)-1)) # send text, trim zero ending
+
+tsec = time.perf_counter()  + 10 # receive for 10 seconds
+print("Receiving on RX...")
+while time.perf_counter() < tsec:
+    time.sleep(0.01)
+    dwf.FDwfDigitalUartRx(hdwf, rgRX, c_int(sizeof(rgRX)-1), byref(cRX), byref(fParity)) # read up to 8k chars at once
+    if cRX.value > 0:
+        rgRX[cRX.value] = 0 # add zero ending
+        print(rgRX.value.decode(), end = '', flush=True)
+    if fParity.value != 0:
+        print("Parity error {}".format(fParity.value))
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Digital_Uart_RX.py b/tests/py/Digital_Uart_RX.py
new file mode 100644
index 0000000000000000000000000000000000000000..51287d91c638232b931aea7b697dbcc3d1bf1f3e
--- /dev/null
+++ b/tests/py/Digital_Uart_RX.py
@@ -0,0 +1,71 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2018-07-29
+
+   Requires:                       
+       Python 2.7, 3
+"""
+
+from ctypes import *
+import math
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.LoadLibrary("dwf.dll")
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+
+hdwf = c_int()
+
+print("Opening first device")
+dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
+# device configuration of index 3 (4th) for Analog Discovery has 16kS digital-in/out buffer
+#dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf)) 
+
+if hdwf.value == 0:
+    print("failed to open device")
+    szerr = create_string_buffer(512)
+    dwf.FDwfGetLastErrorMsg(szerr)
+    print(str(szerr.value))
+    quit()
+
+print("Configuring UART...")
+
+cRX = c_int(0)
+fParity = c_int(0)
+
+dwf.FDwfDigitalUartRateSet(hdwf, c_double(9600)) # 9.6kHz 
+dwf.FDwfDigitalUartRxSet(hdwf, c_int(0)) # RX = DIO-0
+dwf.FDwfDigitalUartBitsSet(hdwf, c_int(8)) # 8 bits
+dwf.FDwfDigitalUartParitySet(hdwf, c_int(0)) # 0 no parity, 1 even, 2 odd, 3 mark (high), 4 space (low)
+dwf.FDwfDigitalUartStopSet(hdwf, c_double(1)) # 1 bit stop length
+
+dwf.FDwfDigitalUartRx(hdwf, None, c_int(0), byref(cRX), byref(fParity))# initialize RX reception
+
+rgRX = create_string_buffer(8193)
+
+print("Receiving on RX, press Ctrl+C to stop...")
+try:
+    while True:
+        time.sleep(0.001)
+        if dwf.FDwfDigitalUartRx(hdwf, rgRX, c_int(sizeof(rgRX)-1), byref(cRX), byref(fParity)) != 1: # read up to 8k chars at once
+            szerr = create_string_buffer(512)
+            dwf.FDwfGetLastErrorMsg(szerr)
+            print("Error:\n"+str(szerr.value))
+            break
+        if cRX.value > 0:
+            rgRX[cRX.value] = 0 # add zero ending
+            sz = rgRX.value.decode(encoding='ascii',errors='replace')
+            #sz = sz.replace('\r', '\n') # replace CarriageReturn or other custom line ending to LineFeed, in case it is needed
+            print(sz, end = '', flush=True) # works with CR+LF or LF
+        if fParity.value != 0:
+            print("Parity error {}".format(fParity.value))
+        
+except KeyboardInterrupt: # Ctrl+C
+    pass
+
+dwf.FDwfDeviceCloseAll()
diff --git a/tests/py/Enumerate.py b/tests/py/Enumerate.py
new file mode 100644
index 0000000000000000000000000000000000000000..08721dce289f2ba27e2647add2dd9e3294e5ba57
--- /dev/null
+++ b/tests/py/Enumerate.py
@@ -0,0 +1,119 @@
+"""
+   DWF Python Example
+   Author:  Digilent, Inc.
+   Revision:  2019-07-24
+
+   Requires:                       
+       Python 2.7, 3
+   Description:
+   Device detection troubleshooting.
+"""
+
+from ctypes import *
+import sys
+import time
+
+if sys.platform.startswith("win"):
+    dwf = cdll.dwf
+    dmgr = cdll.dmgr
+    ftd = windll.ftd2xx
+elif sys.platform.startswith("darwin"):
+    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
+    dmgr = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/Frameworks/libdmgr.dylib")
+    ftd = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/Frameworks/libftd2xx.dylib")
+    dftd = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/Frameworks/libdftd2xx.dylib")
+else:
+    dwf = cdll.LoadLibrary("libdwf.so")
+    dmgr = cdll.LoadLibrary("libdmgr.so")
+    ftd = cdll.LoadLibrary("libftd2xx.so")
+
+version = create_string_buffer(32)
+cDev = c_int();
+dvc = (c_char*1024)()
+pdid = c_int()
+flags = c_int()
+locid = c_int()
+type = c_int()
+
+name = create_string_buffer(64)
+sn = create_string_buffer(64)
+
+if sys.platform.startswith("darwin"):
+    print("")
+    if dftd.DFT_Init() == 0 :
+        print("DFT_INIT failed")
+        quit()
+
+    print("Digilent FTDI Enumeration library loaded")
+    
+    if dftd.DFT_CreateDeviceInfoList(byref(cDev)) != 0 :
+        print("DFT_CreateDeviceInfoList failed")
+        dftd.DFT_Term()
+        quit()
+
+    print("Devices: "+str(cDev.value))
+
+    for i in range(0, cDev.value):
+        if dftd.DFT_GetDeviceInfoDetail(c_int(i), byref(flags), byref(type), byref(pdid), byref(locid), sn, name, None) != 0 :
+            print("Failed DFT_GetDeviceInfoDetail")
+            dftd.DFT_Term()
+            quit()
+        print(" "+str(i+1)+". SN:"+str(sn.value)+" '"+str(name.value)+"'"+" flags: "+hex(flags.value)+" type: "+hex(type.value)+" id: "+hex(pdid.value)+" locid: "+hex(locid.value))
+
+
+print("")
+ftd.FT_GetLibraryVersion(byref(pdid))
+print("FTDI Version: "+hex(pdid.value))
+
+if ftd.FT_CreateDeviceInfoList(byref(cDev)) != 0 :
+    print("FT_CreateDeviceInfoList failed")
+    quit()
+
+print("Devices: "+str(cDev.value))
+
+for i in range(cDev.value):
+    if ftd.FT_GetDeviceInfoDetail(c_int(i), byref(flags), byref(type), byref(pdid), byref(locid), sn, name, None) != 0 :
+        print("Failed FT_GetDeviceInfoDetail")
+    print(" "+str(i+1)+". SN:"+str(sn.value)+" "+str(name.value)+""+" flags: "+hex(flags.value)+" type: "+hex(type.value)+" id: "+hex(pdid.value)+" locid: "+hex(locid.value))
+
+
+print("")
+dmgr.DmgrGetVersion(version)
+print("DMGR Version: "+str(version.value))
+
+if dmgr.DmgrEnumDevices(byref(cDev)) == 0 :
+    print("DmgrEnumDevices failed")
+    quit()
+
+print("Devices: "+str(cDev.value))
+
+for i in range(cDev.value):
+    dmgr.DmgrGetDvc(c_int(i), dvc);
+
+    if dmgr.DmgrGetInfo(dvc, 3, name) == 0 : #dinfoProdName
+        print("Failed DmgrGetInfo dinfoProdName")
+    if dmgr.DmgrGetInfo(dvc, 4, byref(pdid)) == 0 : #dinfoPDID
+        print("Failed DmgrGetInfo dinfoPDID")
+    if dmgr.DmgrGetInfo(dvc, 5, sn) == 0 : #dinfoSN
+        print("Failed DmgrGetInfo dinfoSN")
+    print(" "+str(i+1)+". "+str(sn.value)+" "+str(name.value)+""+" PDID: "+hex(pdid.value))
+
+
+print("")
+dwf.FDwfGetVersion(version)
+print("DWF Version: "+str(version.value))
+
+if dwf.FDwfEnum(c_int(0), byref(cDev)) == 0 :
+    print("DmgrEnumDevices failed")
+    quit()
+
+print("Devices: "+str(cDev.value))
+
+for i in range(cDev.value):
+    dwf.FDwfEnumDeviceName(c_int(i), name)
+    dwf.FDwfEnumSN(c_int(i), sn)
+    print(" "+str(i+1)+". "+str(sn.value)+" "+str(name.value)+"")
+
+dmgr.DmgrFreeDvcEnum()
+if sys.platform.startswith("darwin"):
+    dftd.DFT_Term()
\ No newline at end of file
diff --git a/tests/py/dwfconstants.py b/tests/py/dwfconstants.py
new file mode 100644
index 0000000000000000000000000000000000000000..5ac974fcb10b48f4788974a4ed5c824e19045f75
--- /dev/null
+++ b/tests/py/dwfconstants.py
@@ -0,0 +1,284 @@
+"""
+   DWFConstants (definitions file for DWF library)
+   Author:  Digilent, Inc.
+   Revision:  2021-12-09
+
+   Must install:                       
+       Python 2.7 or 3
+"""
+
+
+from ctypes import *
+
+# device handle
+#HDWF
+hdwfNone = c_int(0)
+
+# device enumeration filters
+enumfilterAll        = c_int(0)
+
+enumfilterType     = c_int(0x8000000)
+enumfilterUSB      = c_int(0x0000001)
+enumfilterNetwork  = c_int(0x0000002)
+enumfilterAXI      = c_int(0x0000004)
+enumfilterRemote   = c_int(0x1000000)
+enumfilterAudio    = c_int(0x2000000)
+enumfilterDemo     = c_int(0x4000000)
+
+# device ID
+devidEExplorer   = c_int(1)
+devidDiscovery   = c_int(2)
+devidDiscovery2  = c_int(3)
+devidDDiscovery  = c_int(4)
+devidADP3X50     = c_int(6)
+devidADP5250     = c_int(8)
+devidDPS3340     = c_int(9)
+
+# device version
+devverEExplorerC   = c_int(2)
+devverEExplorerE   = c_int(4)
+devverEExplorerF   = c_int(5)
+devverDiscoveryA   = c_int(1)
+devverDiscoveryB   = c_int(2)
+devverDiscoveryC   = c_int(3)
+
+# trigger source
+trigsrcNone                 = c_ubyte(0)
+trigsrcPC                   = c_ubyte(1)
+trigsrcDetectorAnalogIn     = c_ubyte(2)
+trigsrcDetectorDigitalIn    = c_ubyte(3)
+trigsrcAnalogIn             = c_ubyte(4)
+trigsrcDigitalIn            = c_ubyte(5)
+trigsrcDigitalOut           = c_ubyte(6)
+trigsrcAnalogOut1           = c_ubyte(7)
+trigsrcAnalogOut2           = c_ubyte(8)
+trigsrcAnalogOut3           = c_ubyte(9)
+trigsrcAnalogOut4           = c_ubyte(10)
+trigsrcExternal1            = c_ubyte(11)
+trigsrcExternal2            = c_ubyte(12)
+trigsrcExternal3            = c_ubyte(13)
+trigsrcExternal4            = c_ubyte(14)
+trigsrcHigh                 = c_ubyte(15)
+trigsrcLow                  = c_ubyte(16)
+trigsrcClock                = c_ubyte(17)
+
+# instrument states
+DwfStateReady        = c_ubyte(0)
+DwfStateConfig       = c_ubyte(4)
+DwfStatePrefill      = c_ubyte(5)
+DwfStateArmed        = c_ubyte(1)
+DwfStateWait         = c_ubyte(7)
+DwfStateTriggered    = c_ubyte(3)
+DwfStateRunning      = c_ubyte(3)
+DwfStateDone         = c_ubyte(2)
+
+# DwfEnumConfigInfo
+DECIAnalogInChannelCount = c_int(1)
+DECIAnalogOutChannelCount = c_int(2)
+DECIAnalogIOChannelCount = c_int(3)
+DECIDigitalInChannelCount = c_int(4)
+DECIDigitalOutChannelCount = c_int(5)
+DECIDigitalIOChannelCount = c_int(6)
+DECIAnalogInBufferSize = c_int(7)
+DECIAnalogOutBufferSize = c_int(8)
+DECIDigitalInBufferSize = c_int(9)
+DECIDigitalOutBufferSize = c_int(10)
+
+# acquisition modes:
+acqmodeSingle       = c_int(0)
+acqmodeScanShift    = c_int(1)
+acqmodeScanScreen   = c_int(2)
+acqmodeRecord       = c_int(3)
+acqmodeOvers        = c_int(4)
+acqmodeSingle1      = c_int(5)
+
+# analog acquisition filter:
+filterDecimate = c_int(0)
+filterAverage  = c_int(1)
+filterMinMax   = c_int(2)
+
+# analog in trigger mode:
+trigtypeEdge         = c_int(0)
+trigtypePulse        = c_int(1)
+trigtypeTransition   = c_int(2)
+trigtypeWindow       = c_int(3)
+
+# trigger slope:
+DwfTriggerSlopeRise   = c_int(0)
+DwfTriggerSlopeFall   = c_int(1)
+DwfTriggerSlopeEither = c_int(2)
+
+# trigger length condition
+triglenLess       = c_int(0)
+triglenTimeout    = c_int(1)
+triglenMore       = c_int(2)
+
+# error codes for the functions:                         
+dwfercNoErc                  = c_int(0)		#  No error occurred
+dwfercUnknownError           = c_int(1)		#  API waiting on pending API timed out
+dwfercApiLockTimeout         = c_int(2)		#  API waiting on pending API timed out
+dwfercAlreadyOpened          = c_int(3)		#  Device already opened
+dwfercNotSupported           = c_int(4)		#  Device not supported
+dwfercInvalidParameter0      = c_int(16)	#  Invalid parameter sent in API call
+dwfercInvalidParameter1      = c_int(17)	#  Invalid parameter sent in API call
+dwfercInvalidParameter2      = c_int(18)	#  Invalid parameter sent in API call
+dwfercInvalidParameter3      = c_int(19)	#  Invalid parameter sent in API call
+dwfercInvalidParameter4      = c_int(20)	#  Invalid parameter sent in API call
+
+# analog out signal types
+funcDC       = c_ubyte(0)
+funcSine     = c_ubyte(1)
+funcSquare   = c_ubyte(2)
+funcTriangle = c_ubyte(3)
+funcRampUp   = c_ubyte(4)
+funcRampDown = c_ubyte(5)
+funcNoise    = c_ubyte(6)
+funcPulse    = c_ubyte(7)
+funcTrapezium= c_ubyte(8)
+funcSinePower= c_ubyte(9)
+funcCustomPattern   = c_ubyte(28)
+funcPlayPattern     = c_ubyte(29)
+funcCustom   = c_ubyte(30)
+funcPlay     = c_ubyte(31)
+
+# analog io channel node types
+analogioEnable      = c_ubyte(1)
+analogioVoltage     = c_ubyte(2)
+analogioCurrent     = c_ubyte(3)
+analogioPower       = c_ubyte(4)
+analogioTemperature	= c_ubyte(5)
+analogioDmm	        = c_ubyte(6)
+analogioRange	    = c_ubyte(7)
+analogioMeasure	    = c_ubyte(8)
+analogioTime	    = c_ubyte(9)
+analogioFrequency	= c_ubyte(10)
+analogioResistance	= c_ubyte(11)
+
+DwfDmmResistance     = c_double(1)
+DwfDmmContinuity     = c_double(2)
+DwfDmmDiode          = c_double(3)
+DwfDmmDCVoltage      = c_double(4)
+DwfDmmACVoltage      = c_double(5)
+DwfDmmDCCurrent      = c_double(6)
+DwfDmmACCurrent      = c_double(7)
+DwfDmmDCLowCurrent   = c_double(8)
+DwfDmmACLowCurrent   = c_double(9)
+DwfDmmTemperature    = c_double(10)
+
+AnalogOutNodeCarrier  = c_int(0)
+AnalogOutNodeFM       = c_int(1)
+AnalogOutNodeAM       = c_int(2)
+
+DwfAnalogOutIdleDisable  = c_int(0)
+DwfAnalogOutIdleOffset   = c_int(1)
+DwfAnalogOutIdleInitial  = c_int(2)
+
+DwfDigitalInClockSourceInternal = c_int(0)
+DwfDigitalInClockSourceExternal = c_int(1)
+
+DwfDigitalInSampleModeSimple   = c_int(0)
+# alternate samples: noise|sample|noise|sample|...  
+# where noise is more than 1 transition between 2 samples
+DwfDigitalInSampleModeNoise    = c_int(1)
+
+DwfDigitalOutOutputPushPull   = c_int(0)
+DwfDigitalOutOutputOpenDrain  = c_int(1)
+DwfDigitalOutOutputOpenSource = c_int(2)
+DwfDigitalOutOutputThreeState = c_int(3) 
+
+DwfDigitalOutTypePulse      = c_int(0)
+DwfDigitalOutTypeCustom     = c_int(1)
+DwfDigitalOutTypeRandom     = c_int(2)
+DwfDigitalOutTypeROM        = c_int(3)
+DwfDigitalOutTypeState      = c_int(4)
+DwfDigitalOutTypePlay       = c_int(5)
+
+DwfDigitalOutIdleInit     = c_int(0)
+DwfDigitalOutIdleLow      = c_int(1)
+DwfDigitalOutIdleHigh     = c_int(2)
+DwfDigitalOutIdleZet      = c_int(3)
+
+DwfAnalogImpedanceImpedance         = c_int(0)
+DwfAnalogImpedanceImpedancePhase    = c_int(1)
+DwfAnalogImpedanceResistance        = c_int(2)
+DwfAnalogImpedanceReactance         = c_int(3)
+DwfAnalogImpedanceAdmittance        = c_int(4)
+DwfAnalogImpedanceAdmittancePhase   = c_int(5)
+DwfAnalogImpedanceConductance       = c_int(6)
+DwfAnalogImpedanceSusceptance       = c_int(7)
+DwfAnalogImpedanceSeriesCapacitance = c_int(8)
+DwfAnalogImpedanceParallelCapacitance = c_int(9)
+DwfAnalogImpedanceSeriesInductance  = c_int(10)
+DwfAnalogImpedanceParallelInductance = c_int(11)
+DwfAnalogImpedanceDissipation       = c_int(12)
+DwfAnalogImpedanceQuality           = c_int(13)
+DwfAnalogImpedanceVrms              = c_int(14)
+DwfAnalogImpedanceVreal             = c_int(15)
+DwfAnalogImpedanceVimag             = c_int(16)
+DwfAnalogImpedanceIrms              = c_int(17)
+DwfAnalogImpedanceIreal             = c_int(18)
+DwfAnalogImpedanceIimag             = c_int(19)
+
+DwfParamUsbPower        = c_int(2) # 1 keep the USB power enabled even when AUX is connected, Analog Discovery 2
+DwfParamLedBrightness   = c_int(3) # LED brightness 0 ... 100%, Digital Discovery
+DwfParamOnClose         = c_int(4) # 0 continue, 1 stop, 2 shutdown
+DwfParamAudioOut        = c_int(5) # 0 disable / 1 enable audio output, Analog Discovery 1, 2
+DwfParamUsbLimit        = c_int(6) # 0..1000 mA USB power limit, -1 no limit, Analog Discovery 1, 2
+DwfParamAnalogOut       = c_int(7) # 0 disable / 1 enable
+DwfParamFrequency       = c_int(8) # Hz
+DwfParamExtFreq         = c_int(9) # Hz
+DwfParamClockMode       = c_int(10) # 0 internal, 1 output, 2 input, 3 IO
+
+DwfWindowRectangular    = c_int(0)
+DwfWindowTriangular     = c_int(1)
+DwfWindowHamming        = c_int(2)
+DwfWindowHann           = c_int(3)
+DwfWindowCosine         = c_int(4)
+DwfWindowBlackmanHarris = c_int(5)
+DwfWindowFlatTop        = c_int(6)
+DwfWindowKaiser         = c_int(7)
+DwfWindowBlackman       = c_int(8)
+
+DwfAnalogCouplingDC     = c_int(0)
+DwfAnalogCouplingAC     = c_int(1)
+
+DwfFiirWindow         = c_int(0)
+DwfFiirFir            = c_int(1)
+DwfFiirIirButterworth = c_int(2)
+DwfFiirIirChebyshev   = c_int(3)
+
+DwfFiirLowPass    = c_int(0)
+DwfFiirHighPass   = c_int(1)
+DwfFiirBandPass   = c_int(2)
+DwfFiirBandStop   = c_int(3)
+
+DwfFiirRaw      = c_int(0)
+DwfFiirDecimate = c_int(1)
+DwfFiirAverage  = c_int(2)
+
+
+# obsolate
+#STS
+stsRdy		= c_ubyte(0)
+stsArm		= c_ubyte(1)
+stsDone		= c_ubyte(2)
+stsTrig		= c_ubyte(3)
+stsCfg		= c_ubyte(4)
+stsPrefill	= c_ubyte(5)
+stsNotDone	= c_ubyte(6)
+stsTrigDly	= c_ubyte(7)
+stsError	= c_ubyte(8)
+stsBusy		= c_ubyte(9)
+stsStop		= c_ubyte(10)
+
+#TRIGCOND
+trigcondRisingPositive   = c_int(0)
+trigcondFallingNegative  = c_int(1)
+
+#use deiceid
+enumfilterEExplorer  = c_int(1)
+enumfilterDiscovery  = c_int(2)
+enumfilterDiscovery2 = c_int(3)
+enumfilterDDiscovery = c_int(4)
+
+