Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
test-and-measurement:guides:waveforms-sdk-getting-started [2021/12/08 09:39] – [Getting Started with the WaveForms SDK] Álmos Veres-Vitályostest-and-measurement:guides:waveforms-sdk-getting-started [2024/03/25 22:09] (current) – [Getting Started with WaveForms SDK] Arthur Brown
Line 1: Line 1:
-====== Getting Started with the WaveForms SDK ======+====== Getting Started with WaveForms SDK ======
 <WRAP group> <WRAP group>
 WaveForms SDK is a set of tools provided within the WaveForms installation that are used to develop custom software solutions that use Digilent Test and Measurement devices. The WaveForms SDK API is available in several programming languages, making it easy to use across many different platforms. WaveForms SDK is a set of tools provided within the WaveForms installation that are used to develop custom software solutions that use Digilent Test and Measurement devices. The WaveForms SDK API is available in several programming languages, making it easy to use across many different platforms.
Line 6: Line 6:
  
 This guide demonstrates the usage of some basic instruments and presents some patterns to help develop your own application. It is written with Python in mind, but users of other languages will still find it useful to illustrate the principles of working with the SDK. This guide demonstrates the usage of some basic instruments and presents some patterns to help develop your own application. It is written with Python in mind, but users of other languages will still find it useful to illustrate the principles of working with the SDK.
 +
 +For an up-to-date version of the scripts, check the [[https://github.com/Digilent/WaveForms-SDK-Getting-Started-PY|GitHub repository, Python]].
 +
 +<WRAP round important>
 +The GitHub material used by this guide has not been been updated since 2022. Newer hardware, such as the Analog Discovery 3, and additional software features that have been added since that time are not directly supported in Python modules and test examples provided by the GitHub material.
 +
 +Alternate, fully supported examples for each supported programming language, maintained by the WaveForms development team, are provided with the WaveForms SDK download and may be found at the following locations:
 +  * Windows 32-bit: **C:\Program Files\Digilent\WaveFormsSDK\samples**
 +  * Windows 64-bit: **C:\Program Files (x86)\Digilent\WaveFormsSDK\samples**
 +  * Linux: **/usr/share/digilent/waveforms/samples**
 +  * macOS: **/Applications/WaveForms.app/Contents/Resources/SDK/samples**
 +
 +The Python examples included with the WaveForms SDK download do not use any wrapper modules. However, an overview of how some of the underlying ctypes functions might be used to create modules is provided in the four numbered __[[waveforms-sdk-getting-started#workflow|Workflow]]__ sections further down in this document.
 +</WRAP>
 </WRAP> </WRAP>
 ---- ----
Line 12: Line 26:
 <WRAP group> <WRAP group>
   * A Digilent Test & Measurement Device   * A Digilent Test & Measurement Device
 +    * [[test-and-measurement:analog-discovery-3:start|Analog Discovery 3]]
 +    * [[test-and-measurement:discovery-power-supply-3340:start|Discovery Power Supply (DPS3340)]]
     * [[test-and-measurement:analog-discovery-pro-5250:start|]]     * [[test-and-measurement:analog-discovery-pro-5250:start|]]
     * [[test-and-measurement:analog-discovery-pro-3x50:start|]]     * [[test-and-measurement:analog-discovery-pro-3x50:start|]]
 +    * [[test-and-measurement:analog-discovery-pro-2230:start|Analog Discovery Pro (ADP2230)]]
     * [[test-and-measurement:analog-discovery-studio:start|]]     * [[test-and-measurement:analog-discovery-studio:start|]]
     * [[test-and-measurement:analog-discovery-2:start|]]     * [[test-and-measurement:analog-discovery-2:start|]]
Line 29: Line 46:
 Another important file is the one that contains the definition of all constants. If you want to use the SDK from Python, this file is a Python module, while for C/C++ applications, the constants are defined in a header file. Another important file is the one that contains the definition of all constants. If you want to use the SDK from Python, this file is a Python module, while for C/C++ applications, the constants are defined in a header file.
  
-Working code examples for each supported programming language are provided with the SDK and may be found at the following locations: 
-  * Windows 32-bit: **C:\Program Files\Digilent\WaveFormsSDK\samples** 
-  * Windows 64-bit: **C:\Program Files (x86)\Digilent\WaveFormsSDK\samples** 
-  * Linux: **/usr/share/digilent/waveforms/samples** 
-  * macOS: **/Applications/WaveForms.app/Contents/Resources/SDK/samples** 
  
-For other examples, check: [[test-and-measurement:guides:waveforms-using-waveforms-sdk|]].+
 </WRAP> </WRAP>
 ---- ----
Line 45: Line 57:
  
 As the first step of your project import the **dwfconstants.py** file to your project directory (it is located among the sample codes, in the **py** folder), then load the necessary modules and the dynamic library. As the first step of your project import the **dwfconstants.py** file to your project directory (it is located among the sample codes, in the **py** folder), then load the necessary modules and the dynamic library.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fdevice.py%23L23-L44&style=github&showCopy=on"></script> +import ctypes                     # import the C compatible data types 
-</html></WRAP></WRAP>+from sys import platform, path    # this is needed to check the OS type and get the PATH 
 +from os import sep                # OS specific file path separators
  
---> Optional: Importing the Constants from the Project Directory # +load the dynamic libraryget constants path (the path is OS specific) 
-<WRAP group><WRAP half column> +if platform.startswith("win"): 
-Alternatively, you can import the dwfconstants.py file from the project directorysimplifying this way the code. Copy the file into your project, then import it like any other module, but include the directory name in the import path. +    # on Windows 
-</WRAP><WRAP half column> +    dwf = ctypes.cdll.dwf 
-<html> +    constants_path = "C:" + sep + "Program Files (x86)" + sep + "Digilent" + sep + "WaveFormsSDK" + sep + "samples" + sep + "py" 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fdevice.py%23L4-L17&style=github&showCopy=on"></script> +elif platform.startswith("darwin"): 
-</html> +    # on macOS 
-</WRAP></WRAP> +    lib_path = sep + "Library" + sep + "Frameworks" + sep + "dwf.framework" + sep + "dwf" 
-<--+    dwf ctypes.cdll.LoadLibrary(lib_path) 
 +    constants_path = sep + "Applications" + sep + "WaveForms.app" + sep + "Contents" + sep + "Resources" + sep + "SDK" + sep + "samples" + sep + "py
 +else: 
 +    # on Linux 
 +    dwf ctypes.cdll.LoadLibrary("libdwf.so"
 +    constants_path sep + "usr" + sep + "share" + sep + "digilent" + sep + "waveforms" + sep + "samples" + sep + "py" 
 + 
 +# import constants 
 +path.append(constants_path) 
 +import dwfconstants as constants 
 +</code></WRAP></WRAP>
 ---- ----
  
Line 63: Line 86:
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 The next step is to "open" your device. If you have only one Test & Measurement device connected, the simplest method is to ask the WaveForms SDK to connect to the first available device. The next step is to "open" your device. If you have only one Test & Measurement device connected, the simplest method is to ask the WaveForms SDK to connect to the first available device.
-</WRAP><WRAP half column><html> 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fdevice.py%23L49-L58&style=github&showCopy=on"></script> 
-</html></WRAP></WRAP> 
  
---> Optional: Connecting to Specific Device # +Opening specific device and retrieving the name of the connected device is also possible (for more informationcheck the WaveForms SDK examples, or the GitHub repository)
-<WRAP group><WRAP half column> +</WRAP><WRAP half column><code python
-If you have multiple Test & Measurement devices connected, opening the first available device might not be the best option. If you want to open a specific type of device, use the function presented to the right+class data: 
-</WRAP><WRAP half column><html+    """ 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fdevice.py%23L63-L117&style=github&showCopy=on"></script> +        stores the device handle and the device name 
-</html></WRAP></WRAP> +    """ 
-<--+    handle ctypes.c_int(0) 
 +    name = ""
  
---> OptionalError Checking # +def open()
-<WRAP group><WRAP half column> +    """ 
-You can check for errors, to know whether your device was connected to or not+        open the first available device 
-</WRAP><WRAP half column><html> +    """ 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fdevice.py%23L121-L139&style=github&showCopy=on"></script> +    # this is the device handle - it will be used by all functions to "address" the connected device 
-</html></WRAP></WRAP> +    device_handle = ctypes.c_int() 
-<--+    # connect to the first available device 
 +    dwf.FDwfDeviceOpen(ctypes.c_int(-1), ctypes.byref(device_handle)) 
 +    data.handle device_handle 
 +    return data 
 +</code></WRAP></WRAP>
 ---- ----
  
 ==== 3. Using Instruments ==== ==== 3. Using Instruments ====
---> Oscilloscope # 
 <WRAP group> <WRAP group>
-=== 3.1 Initialize the Scope ===+The code snippets in this section present basic functionality of some instruments for some devices. For more possibilities (advanced features and more instruments) check the documentation of the WaveForms SDK, the available sample scripts and the GitHub repository. 
 +</WRAP> 
 + 
 +--> 3.1 Oscilloscope # 
 +<WRAP group> 
 +=== 3.1.1 Initialize the Scope ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Before measuring with the oscilloscope, it must be set up. Change the values to fit your needs. Before measuring with the oscilloscope, it must be set up. Change the values to fit your needs.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fscope.py%23L37-L64&style=github&showCopy=on"></script> +class data: 
-</html></WRAP></WRAP>+    """ stores the sampling frequency and the buffer size """ 
 +    sampling_frequency 20e06 
 +    buffer_size 8192
  
-=== 3.2 Measure a Voltage ===+def open(device_data, sampling_frequency=20e06, buffer_size=8192, offset=0, amplitude_range=5): 
 +    """ 
 +        initialize the oscilloscope 
 +        parameters: - device data 
 +                    - sampling frequency in Hz, default is 20MHz 
 +                    - buffer size, default is 8192 
 +                    - offset voltage in Volts, default is 0V 
 +                    - amplitude range in Volts, default is ±5V 
 +    """ 
 +    # enable all channels 
 +    dwf.FDwfAnalogInChannelEnableSet(device_data.handle, ctypes.c_int(0), ctypes.c_bool(True)) 
 +     
 +    # set offset voltage (in Volts) 
 +    dwf.FDwfAnalogInChannelOffsetSet(device_data.handle, ctypes.c_int(0), ctypes.c_double(offset)) 
 +     
 +    # set range (maximum signal amplitude in Volts) 
 +    dwf.FDwfAnalogInChannelRangeSet(device_data.handle, ctypes.c_int(0), ctypes.c_double(amplitude_range)) 
 +     
 +    # set the buffer size (data point in a recording) 
 +    dwf.FDwfAnalogInBufferSizeSet(device_data.handle, ctypes.c_int(buffer_size)) 
 +     
 +    # set the acquisition frequency (in Hz) 
 +    dwf.FDwfAnalogInFrequencySet(device_data.handle, ctypes.c_double(sampling_frequency)) 
 +     
 +    # disable averaging (for more info check the documentation) 
 +    dwf.FDwfAnalogInChannelFilterSet(device_data.handle, ctypes.c_int(-1), constants.filterDecimate) 
 +    data.sampling_frequency = sampling_frequency 
 +    data.buffer_size = buffer_size 
 +    return 
 +</code></WRAP></WRAP> 
 + 
 +=== 3.1.2 Measure a Voltage ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 You can measure voltages, like with the Voltmeter instrument in WaveForms. You can measure voltages, like with the Voltmeter instrument in WaveForms.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fscope.py%23L68-L89&style=github&showCopy=on"></script> +def measure(device_data, channel): 
-</html></WRAP></WRAP>+    """ 
 +        measure a voltage 
 +        parameters- device data 
 +                    - the selected oscilloscope channel (1-2, or 1-4) 
 +         
 +        returns:    - the measured voltage in Volts 
 +    """ 
 +    # set up the instrument 
 +    dwf.FDwfAnalogInConfigure(device_data.handle, ctypes.c_bool(False), ctypes.c_bool(False)) 
 +     
 +    # read data to an internal buffer 
 +    dwf.FDwfAnalogInStatus(device_data.handle, ctypes.c_bool(False), ctypes.c_int(0)) 
 +     
 +    # extract data from that buffer 
 +    voltage ctypes.c_double()   # variable to store the measured voltage 
 +    dwf.FDwfAnalogInStatusSample(device_data.handle, ctypes.c_int(channel 1), ctypes.byref(voltage)) 
 +     
 +    # store the result as float 
 +    voltage voltage.value 
 +    return voltage 
 +</code></WRAP></WRAP>
  
-=== 3.3 Record a Signal ===+=== 3.1.3 Record a Signal ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 The most important feature of the oscilloscope is, that it can record signals. The recorded voltages can be stored in a list. The most important feature of the oscilloscope is, that it can record signals. The recorded voltages can be stored in a list.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fscope.py%23L137-L172&style=github&showCopy=on"></script> +def record(device_data, channel): 
-</html></WRAP></WRAP>+    """ 
 +        record an analog signal 
 +        parameters- device data 
 +                    - the selected oscilloscope channel (1-2, or 1-4) 
 +        returns:    - buffer - a list with the recorded voltages 
 +                    - time - a list with the time moments for each voltage in seconds (with the same index as "buffer"
 +    """ 
 +    # set up the instrument 
 +    dwf.FDwfAnalogInConfigure(device_data.handle, ctypes.c_bool(False), ctypes.c_bool(True)) 
 +     
 +    # read data to an internal buffer 
 +    while True: 
 +        status ctypes.c_byte()    # variable to store buffer status 
 +        dwf.FDwfAnalogInStatus(device_data.handle, ctypes.c_bool(True), ctypes.byref(status)) 
 +     
 +        # check internal buffer status 
 +        if status.value == constants.DwfStateDone.value: 
 +                # exit loop when ready 
 +                break 
 +     
 +    # copy buffer 
 +    buffer = (ctypes.c_double * data.buffer_size)()   # create an empty buffer 
 +    dwf.FDwfAnalogInStatusData(device_data.handle, ctypes.c_int(channel 1), buffer, ctypes.c_int(data.buffer_size)) 
 +     
 +    # calculate aquisition time 
 +    time range(0, data.buffer_size) 
 +    time [moment data.sampling_frequency for moment in time] 
 +     
 +    # convert into list 
 +    buffer = [float(element) for element in buffer] 
 +    return buffer, time 
 +</code></WRAP></WRAP>
  
-=== 3.4 Reset the Scope ===+=== 3.1.4 Reset the Scope ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 After usage, reset the oscilloscope to the default settings. After usage, reset the oscilloscope to the default settings.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fscope.py%23L176-L181&style=github&showCopy=on"></script> +def close(device_data): 
-</html></WRAP></WRAP> +    """ 
- +        reset the scope 
---> Optional: Triggering # +    """ 
-<WRAP group><WRAP half column> +    dwf.FDwfAnalogInReset(device_data.handle) 
-Before recording a signal, you might want to set up triggering. Set the trigger parameters to fit your needs. +    return 
- +</code></WRAP></WRAP>
-<WRAP center round tip 80%> +
-You can define custom trigger source names, to make the usage of the function easier. +
-</WRAP> +
- +
-<html> +
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fscope.py%23L28-L33&style=github&showCopy=on"></script> +
-</html> +
-</WRAP><WRAP half column><html> +
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fscope.py%23L93-L133&style=github&showCopy=on"></script> +
-</html></WRAP></WRAP> +
-<-- +
-----+
 </WRAP> </WRAP>
 <-- <--
  
---> Waveform Generator #+--> 3.2 Waveform Generator #
 <WRAP group> <WRAP group>
-=== 3.1 Generate a Signal ===+=== 3.2.1 Generate a Signal ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Use the waveform generator to generate different signals. Use the waveform generator to generate different signals.
Line 144: Line 245:
 </WRAP> </WRAP>
  
-<html+<code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fwavegen.py%23L28-L40&style=github&showCopy=on"></script> +class function: 
-</html+    """ function names """ 
-</WRAP><WRAP half column><html+    custom = constants.funcCustom 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fwavegen.py%23L44-L98&style=github&showCopy=on"></script> +    sine = constants.funcSine 
-</html></WRAP></WRAP>+    square constants.funcSquare 
 +    triangle = constants.funcTriangle 
 +    noise constants.funcNoise 
 +    dc constants.funcDC 
 +    pulse = constants.funcPulse 
 +    trapezium = constants.funcTrapezium 
 +    sine_power = constants.funcSinePower 
 +    ramp_up = constants.funcRampUp 
 +    ramp_down = constants.funcRampDown 
 +</code
 +</WRAP><WRAP half column><code python
 +def generate(device_data, channel, function, offset, frequency=1e03, amplitude=1, symmetry=50, wait=0, run_time=0, repeat=0, data=[]): 
 +    """ 
 +        generate an analog signal 
 +        parameters: - device data 
 +                    the selected wavegen channel (1-2) 
 +                    - function - possible: custom, sine, square, triangle, noise, ds, pulse, trapezium, sine_power, ramp_up, ramp_down 
 +                    - offset voltage in Volts 
 +                    - frequency in Hz, default is 1KHz 
 +                    - amplitude in Volts, default is 1V 
 +                    - signal symmetry in percentage, default is 50% 
 +                    - wait time in seconds, default is 0s 
 +                    - run time in seconds, default is infinite (0) 
 +                    - repeat count, default is infinite (0) 
 +                    - data - list of voltages, used only if function=custom, default is empty 
 +    """ 
 +    # enable channel 
 +    channel = ctypes.c_int(channel 1) 
 +    dwf.FDwfAnalogOutNodeEnableSet(device_data.handle, channel, constants.AnalogOutNodeCarrier, ctypes.c_bool(True)) 
 +     
 +    # set function type 
 +    dwf.FDwfAnalogOutNodeFunctionSet(device_data.handle, channel, constants.AnalogOutNodeCarrier, function) 
 +     
 +    # load data if the function type is custom 
 +    if function == constants.funcCustom: 
 +        data_length = len(data) 
 +        buffer = (ctypes.c_double * data_length)() 
 +        for index in range(0, len(buffer)): 
 +            buffer[index] = ctypes.c_double(data[index]) 
 +        dwf.FDwfAnalogOutNodeDataSet(device_data.handle, channel, constants.AnalogOutNodeCarrier, buffer, ctypes.c_int(data_length)) 
 +     
 +    # set frequency 
 +    dwf.FDwfAnalogOutNodeFrequencySet(device_data.handle, channel, constants.AnalogOutNodeCarrier, ctypes.c_double(frequency)) 
 +     
 +    # set amplitude or DC voltage 
 +    dwf.FDwfAnalogOutNodeAmplitudeSet(device_data.handle, channel, constants.AnalogOutNodeCarrier, ctypes.c_double(amplitude)) 
 +     
 +    # set offset 
 +    dwf.FDwfAnalogOutNodeOffsetSet(device_data.handle, channel, constants.AnalogOutNodeCarrier, ctypes.c_double(offset)) 
 +     
 +    # set symmetry 
 +    dwf.FDwfAnalogOutNodeSymmetrySet(device_data.handle, channel, constants.AnalogOutNodeCarrier, ctypes.c_double(symmetry)) 
 +     
 +    # set running time limit 
 +    dwf.FDwfAnalogOutRunSet(device_data.handle, channel, ctypes.c_double(run_time)) 
 +     
 +    # set wait time before start 
 +    dwf.FDwfAnalogOutWaitSet(device_data.handle, channel, ctypes.c_double(wait)) 
 +     
 +    # set number of repeating cycles 
 +    dwf.FDwfAnalogOutRepeatSet(device_data.handle, channel, ctypes.c_int(repeat)) 
 +     
 +    # start 
 +    dwf.FDwfAnalogOutConfigure(device_data.handle, channel, ctypes.c_bool(True)) 
 +    return 
 +</code></WRAP></WRAP>
  
-=== 3.2 Reset the Wavegen ===+=== 3.2.2 Reset the Wavegen ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 After usage, reset the wavegen to the default settings. After usage, reset the wavegen to the default settings.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fwavegen.py%23L102-L107&style=github&showCopy=on"></script> +def close(device_data, channel=0): 
-</html></WRAP></WRAP> +    """ 
-----+        reset a wavegen channel, or all channels (channel=0) 
 +    """ 
 +    channel = ctypes.c_int(channel 1) 
 +    dwf.FDwfAnalogOutReset(device_data.handle, channel) 
 +    return 
 +</code></WRAP></WRAP>
 </WRAP> </WRAP>
 <-- <--
  
---> Power Supplies #+--> 3.3 Power Supplies #
 <WRAP group> <WRAP group>
---> 3.1 Analog Discovery Supplies #+--> 3.3.1 Analog Discovery Supplies #
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
-The Analog Discovery has only fixed supplies, so just a limited number of functions are available+The Analog Discovery has variable positive and negative supplies to set voltage levels
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fsupplies.py%23L28-L45&style=github&showCopy=on"></script> +def _switch_variable_(device_data, master_state, positive_state, negative_state, positive_voltage, negative_voltage): 
-</html></WRAP></WRAP>+    """ 
 +        turn the power supplies on/off 
 +        parameters: device data 
 +                    master switch True = on, False = off 
 +                    positive supply switch - True on, False = off 
 +                    - negative supply switch - True = on, False = off 
 +                    - positive supply voltage in Volts 
 +                    - negative supply voltage in Volts 
 +    """ 
 +    # set positive voltage 
 +    positive_voltage = max(0, min(5, positive_voltage)) 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(0), ctypes.c_int(1), ctypes.c_double(positive_voltage)) 
 +     
 +    # set negative voltage 
 +    negative_voltage = max(-5, min(0, negative_voltage)) 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(1), ctypes.c_int(1), ctypes.c_double(negative_voltage)) 
 + 
 +    # enable/disable the positive supply 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(0), ctypes.c_int(0), ctypes.c_int(positive_state)) 
 +     
 +    # enable the negative supply 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(1), ctypes.c_int(0), ctypes.c_int(negative_state)) 
 +     
 +    # start/stop the supplies - master switch 
 +    dwf.FDwfAnalogIOEnableSet(device_data.handle, ctypes.c_int(master_state)) 
 +    return 
 +</code></WRAP></WRAP>
 <-- <--
  
---> 3.Analog Discovery 2 and Analog Discovery Studio Supplies #+--> 3.3.2 Analog Discovery 2 and Analog Discovery Studio Supplies #
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 These devices have variable positive and negative supplies, so a voltage level can also be set. These devices have variable positive and negative supplies, so a voltage level can also be set.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fsupplies.py%23L49-L76&style=github&showCopy=on"></script> +def _switch_variable_(device_data, master_state, positive_state, negative_state, positive_voltage, negative_voltage): 
-</html></WRAP></WRAP>+    """ 
 +        turn the power supplies on/off 
 +        parameters: - device data 
 +                    - master switch - True = on, False = off 
 +                    - positive supply switch - True = on, False = off 
 +                    - negative supply switch - True = on, False = off 
 +                    - positive supply voltage in Volts 
 +                    - negative supply voltage in Volts 
 +    """ 
 +    # set positive voltage 
 +    positive_voltage = max(0, min(5, positive_voltage)) 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(0), ctypes.c_int(1), ctypes.c_double(positive_voltage)) 
 +     
 +    # set negative voltage 
 +    negative_voltage = max(-5, min(0, negative_voltage)) 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(1), ctypes.c_int(1), ctypes.c_double(negative_voltage)) 
 + 
 +    # enable/disable the positive supply 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(0), ctypes.c_int(0), ctypes.c_int(positive_state)) 
 +     
 +    # enable the negative supply 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(1), ctypes.c_int(0), ctypes.c_int(negative_state)) 
 +     
 +    # start/stop the supplies - master switch 
 +    dwf.FDwfAnalogIOEnableSet(device_data.handle, ctypes.c_int(master_state)) 
 +    return 
 +</code></WRAP></WRAP> 
 +<-- 
 + 
 +--> 3.3.3 Analog Discovery (Legacy) Supplies # 
 +<WRAP group><WRAP half column> 
 +The Analog Discovery has only fixed supplies, so just a limited number of functions are available. 
 +</WRAP><WRAP half column><code python> 
 +def _switch_fixed_(device_data, master_state, positive_state, negative_state): 
 +    """ 
 +        turn the power supplies on/off 
 +        parameters: device data 
 +                    - master switch - True on, False = off 
 +                    - positive supply switch - True = on, False = off 
 +                    - negative supply switch - True = on, False = off 
 +    """ 
 +    # enable/disable the positive supply 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(0), ctypes.c_int(0), ctypes.c_int(positive_state)) 
 +     
 +    # enable the negative supply 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(1), ctypes.c_int(0), ctypes.c_int(negative_state)) 
 +     
 +    # start/stop the supplies - master switch 
 +    dwf.FDwfAnalogIOEnableSet(device_data.handle, ctypes.c_int(master_state)) 
 +    return 
 +</code></WRAP></WRAP>
 <-- <--
  
---> 3.Analog Discovery Pro 3X50 and Digital Discovery Supplies #+--> 3.3.4 Analog Discovery Pro 3X50 and Digital Discovery Supplies #
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Devices with digital supplies have only positive voltage supplies with a variable voltage level between 1.2 and 3.3 Volts. Devices with digital supplies have only positive voltage supplies with a variable voltage level between 1.2 and 3.3 Volts.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fsupplies.py%23L80-L94&style=github&showCopy=on"></script> +def _switch_digital_(device_data, master_state, voltage): 
-</html></WRAP></WRAP>+    """ 
 +        turn the power supplies on/off 
 +        parameters: device data 
 +                    master switch True = on, False = off 
 +                    - supply voltage in Volts 
 +    """ 
 +    # set supply voltage 
 +    voltage = max(1.2, min(3.3, voltage)) 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(0), ctypes.c_int(0), ctypes.c_double(voltage)) 
 +     
 +    # start/stop the supplies - master switch 
 +    dwf.FDwfAnalogIOEnableSet(device_data.handle, ctypes.c_int(master_state)) 
 +    return 
 +</code></WRAP></WRAP>
 <-- <--
  
---> 3.Analog Discovery Pro 5250 6V Power Supply #+--> 3.3.5 Analog Discovery Pro 5250 6V Power Supply #
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 You can set not only the voltage for the 6V power supply on the Analog Discovery 5250, but also the current limit, up to 1A. You can set not only the voltage for the 6V power supply on the Analog Discovery 5250, but also the current limit, up to 1A.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fsupplies.py%23L98-L117&style=github&showCopy=on"></script> +def _switch_6V_(device_data, master_state, voltage, current=1): 
-</html></WRAP></WRAP>+    """ 
 +        turn the 6V supply on the ADP5250 on/off 
 +        parameters: - master switch - True on, False = off 
 +                    voltage in volts between 0-
 +                    current in amperes between 0-
 +    """ 
 +    # set the voltage 
 +    voltage max(0, min(6, voltage)) 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(0), ctypes.c_int(1), ctypes.c_double(voltage)) 
 +     
 +    # set the current 
 +    current max(0, min(1, current)) 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(0), ctypes.c_int(2), ctypes.c_double(current)) 
 +     
 +    # start/stop the supply - master switch 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(0), ctypes.c_int(0), ctypes.c_double(float(master_state))) 
 +    dwf.FDwfAnalogIOEnableSet(device_data.handle, ctypes.c_int(master_state)) 
 +    return 
 +</code></WRAP></WRAP>
 <-- <--
  
---> 3.Analog Discovery Pro 5250 25V Power Supplies #+--> 3.3.6 Analog Discovery Pro 5250 25V Power Supplies #
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 The positive and negative isolated 25V power supplies are similar to the 6V one, but with a maximum current limit of 500mA. The positive and negative isolated 25V power supplies are similar to the 6V one, but with a maximum current limit of 500mA.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fsupplies.py%23L121-L154&style=github&showCopy=on"></script> +def _switch_25V_(device_data, positive_state, negative_state, positive_voltage, negative_voltage, positive_current=0.5, negative_current=-0.5): 
-</html></WRAP></WRAP>+    """ 
 +        turn the 25V power supplies on/off on the ADP5250 
 +        parameters: positive supply switch True = on, False = off 
 +                    negative supply switch True = on, False = off 
 +                    - positive supply voltage in Volts 
 +                    - negative supply voltage in Volts 
 +                    - positive supply current limit 
 +                    - negative supply current limit 
 +    """ 
 +    # set positive voltage 
 +    positive_voltage = max(0, min(25, positive_voltage)) 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(1), ctypes.c_int(1), ctypes.c_double(positive_voltage)) 
 +     
 +    # set negative voltage 
 +    negative_voltage *= -1 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(2), ctypes.c_int(1), ctypes.c_double(negative_voltage)) 
 + 
 +    # set positive current limit 
 +    positive_current = max(0, min(0.5, positive_current)) 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(1), ctypes.c_int(2), ctypes.c_double(positive_current)) 
 +     
 +    # set negative current limit 
 +    negative_current *= -1 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(2), ctypes.c_int(2), ctypes.c_double(negative_current)) 
 + 
 +    # enable/disable the supplies 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(1), ctypes.c_int(0), ctypes.c_double(float(positive_state))) 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(2), ctypes.c_int(0), ctypes.c_double(float(negative_state))) 
 +     
 +    # master switch 
 +    dwf.FDwfAnalogIOEnableSet(device_data.handle, ctypes.c_int(positive_state or negative_state)) 
 +    return 
 +</code></WRAP></WRAP>
 <-- <--
  
---> Optional: Power Supplies Wrapper Function #+=== 3.3.7 Wrapper Function  ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
-To make the usage of the above functions easier, you can create a wrapper function, which is able to call the function you need. +To make the usage of the above functions easier, you can create a wrapper function, which is able to call the function you need (if the device name is set)
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fsupplies.py%23L158-L257&style=github&showCopy=on"></script> +class data: 
-</html></WRAP></WRAP> +    """ power supply parameters """ 
-<--+    master_state = False    # master switch 
 +    state False           # digital/6V/positive supply state 
 +    positive_state False  # positive supply switch 
 +    negative_state False  # negative supply switch 
 +    positive_voltage 0    # positive supply voltage 
 +    negative_voltage = 0    # negative supply voltage 
 +    voltage = 0             # digital/positive supply voltage 
 +    positive_current = 0    # positive supply current 
 +    negative_current = 0    # negative supply current 
 +    current = 0             # digital/6V supply current
  
-=== 3.2 Reset the Supplies ===+def switch(device_data, supplies_data): 
 +    """ 
 +        turn the power supplies on/off 
 +        parameters: - device data 
 +                    - class containing supplies data: 
 +                        - master_state 
 +                        - state and/or positive_state and negative_state 
 +                        - voltage and/or positive_voltage and negative_voltage 
 +                        - current and/or positive_current and negative_current 
 +    """ 
 +    if device_data.name == "Analog Discovery": 
 +        # switch fixed supplies on AD 
 +        supply_state supplies_data.state or supplies_data.positive_state 
 +        _switch_fixed_(device_data, supplies_data.master_state, supply_state, supplies_data.negative_state) 
 + 
 +    elif device_data.name == "Analog Discovery 2" or device_data.name == "Analog Discovery Studio": 
 +        # switch variable supplies on AD2 
 +        supply_state = supplies_data.state or supplies_data.positive_state 
 +        supply_voltage = supplies_data.voltage + supplies_data.positive_voltage 
 +        _switch_variable_(device_data, supplies_data.master_state, supply_state, supplies_data.negative_state, supply_voltage, supplies_data.negative_voltage) 
 + 
 +    elif device_data.name == "Digital Discovery" or device_data.name == "Analog Discovery Pro 3X50": 
 +        # switch the digital supply on DD, or ADP3x50 
 +        supply_state = supplies_data.master_state and (supplies_data.state or supplies_data.positive_state) 
 +        supply_voltage = supplies_data.voltage + supplies_data.positive_voltage 
 +        _switch_digital_(device_data, supply_state, supply_voltage) 
 + 
 +    elif device_data.name == "Analog Discovery Pro 5250": 
 +        # switch the 6V supply on ADP5250 
 +        supply_state = supplies_data.master_state and supplies_data.state 
 +        _switch_6V_(device_data, supply_state, supplies_data.voltage, supplies_data.current) 
 +        # switch the 25V supplies on ADP5250 
 +        supply_positive_state = supplies_data.master_state and supplies_data.positive_state 
 +        supply_negative_state = supplies_data.master_state and supplies_data.negative_state 
 +        _switch_25V_(device_data, supply_positive_state, supply_negative_state, supplies_data.positive_voltage, supplies_data.negative_voltage, supplies_data.positive_current, supplies_data.negative_current) 
 +    return 
 +</code></WRAP></WRAP> 
 + 
 +=== 3.3.8 Reset the Supplies ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 After usage, reset the supplies to the default settings. After usage, reset the supplies to the default settings.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fsupplies.py%23L261-L266&style=github&showCopy=on"></script> +def close(device_data): 
-</html></WRAP></WRAP> +    ""
-----+        reset the supplies 
 +    """ 
 +    dwf.FDwfAnalogIOReset(device_data.handle) 
 +    return 
 +</code></WRAP></WRAP>
 </WRAP> </WRAP>
 <-- <--
  
---> Digital Multimeter - Only on ADP5250 #+--> 3.4 Digital Multimeter - Only on ADP5250 #
 <WRAP group> <WRAP group>
-=== 3.1 Initialize the DMM ===+=== 3.4.1 Initialize the DMM ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Before measuring with the digital multimeter, it must be enabled. Before measuring with the digital multimeter, it must be enabled.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fdmm.py%23L28-L34&style=github&showCopy=on"></script> +def open(device_data): 
-</html></WRAP></WRAP>+    """ 
 +        initialize the digital multimeter 
 +    """ 
 +    # enable the DMM 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(0), ctypes.c_double(1.0)) 
 +    return 
 +</code></WRAP></WRAP>
  
-=== 3.2 Measure With the DMM ===+=== 3.4.2 Measure With the DMM ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
-<WRAP center round important 60%> 
-This function was not tested. 
-</WRAP> 
- 
 You can use the digital multimeter to measure AC, or DC voltages (in Volts), with an input impedance of 10MΩ, or 10GΩ, low (<100mA), or high AC, or DC currents (up to 10A), resistance, conductance, temperature and more, with automatic, or fixed range. You can use the digital multimeter to measure AC, or DC voltages (in Volts), with an input impedance of 10MΩ, or 10GΩ, low (<100mA), or high AC, or DC currents (up to 10A), resistance, conductance, temperature and more, with automatic, or fixed range.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fdmm.py%23L38-L108&style=github&showCopy=on"></script> +def measure(device_data, mode, ac=False, range=0, high_impedance=False): 
-</html></WRAP></WRAP>+    """ 
 +        measure a voltage/current/resistance/continuity/temperature 
 +        parameters: device data 
 +                    mode: "voltage", "low current", "high current", "resistance", "continuity", "diode", "temperature" 
 +                    ac: True means AC value, False means DC value, default is DC 
 +                    range: voltage/current/resistance/temperature range, 0 means auto, default is auto 
 +                    - high_impedance: input impedance for DC voltage measurement, False means 10MΩ, True means 10GΩ, default is 10MΩ 
 +         
 +        returns:    - the measured value in V/A/Ω/°C, or None on error 
 +    """ 
 +    # set voltage mode 
 +    if mode == "voltage": 
 +        # set coupling 
 +        if ac: 
 +            dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(1), constants.DwfDmmACVoltage) 
 +        else: 
 +            dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(1), constants.DwfDmmDCVoltage)
  
-=== 3.3 Reset the DMM ===+        # set input impedance 
 +        if high_impedance: 
 +            dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(5), ctypes.c_double(1)) 
 +        else: 
 +            dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(5), ctypes.c_double(0)) 
 + 
 +    # set high current mode 
 +    elif mode == "high current": 
 +        # set coupling 
 +        if ac: 
 +            dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(1), constants.DwfDmmACCurrent) 
 +        else: 
 +            dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(1), constants.DwfDmmDCCurrent) 
 + 
 +    # set low current mode 
 +    elif mode == "low current": 
 +        # set coupling 
 +        if ac: 
 +            dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(1), constants.DwfDmmACLowCurrent) 
 +        else: 
 +            dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(1), constants.DwfDmmDCLowCurrent) 
 +             
 +    # set resistance mode 
 +    elif mode == "resistance": 
 +        dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(1), constants.DwfDmmResistance) 
 + 
 +    # set continuity mode 
 +    elif mode == "continuity": 
 +        dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(1), constants.DwfDmmContinuity) 
 + 
 +    # set diode mode 
 +    elif mode == "diode": 
 +        dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(1), constants.DwfDmmDiode) 
 + 
 +    # set temperature mode 
 +    elif mode == "temperature": 
 +        dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(1), constants.DwfDmmTemperature) 
 +         
 +    # set range 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(2), ctypes.c_double(range)) 
 + 
 +    # fetch analog I/O status 
 +    if dwf.FDwfAnalogIOStatus(device_data.handle) == 0: 
 +        # signal error 
 +        return None 
 + 
 +    # get reading 
 +    measurement = ctypes.c_double() 
 +    dwf.FDwfAnalogIOChannelNodeStatus(device_data.handle, ctypes.c_int(3), ctypes.c_int(3), ctypes.byref(measurement)) 
 + 
 +    return measurement.value 
 +</code></WRAP></WRAP> 
 + 
 +=== 3.4.3 Reset the DMM ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 After usage, reset the instrument to the default settings. After usage, reset the instrument to the default settings.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fdmm.py%23L112-L120&style=github&showCopy=on"></script> +def close(device_data): 
-</html></WRAP></WRAP> +    """ 
-----+        reset the instrument 
 +    """ 
 +    # disable the DMM 
 +    dwf.FDwfAnalogIOChannelNodeSet(device_data.handle, ctypes.c_int(3), ctypes.c_int(0), ctypes.c_double(0)) 
 +    # reset the instrument 
 +    dwf.FDwfAnalogIOReset(device_data.handle) 
 +    return 
 +</code></WRAP></WRAP>
 </WRAP> </WRAP>
 <-- <--
  
---> Logic Analyzer #+--> 3.5 Logic Analyzer #
 <WRAP group> <WRAP group>
-=== 3.1 Initialize the Logic Analyzer ===+=== 3.5.1 Initialize the Logic Analyzer ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Before measuring with the logic analyzer, it must be set up. Change the values to fit your needs. Before measuring with the logic analyzer, it must be set up. Change the values to fit your needs.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Flogic.py%23L28-L48&style=github&showCopy=on"></script> +class data: 
-</html></WRAP></WRAP>+    """ stores the sampling frequency and the buffer size """ 
 +    sampling_frequency 100e06 
 +    buffer_size 4096
  
-=== 3.2 Record Logic Signals ===+def open(device_data, sampling_frequency=100e06, buffer_size=4096): 
 +    """ 
 +        initialize the logic analyzer 
 +        parameters: - device data 
 +                    - sampling frequency in Hz, default is 100MHz 
 +                    - buffer size, default is 4096 
 +    """ 
 +    # get internal clock frequency 
 +    internal_frequency = ctypes.c_double() 
 +    dwf.FDwfDigitalInInternalClockInfo(device_data.handle, ctypes.byref(internal_frequency)) 
 +     
 +    # set clock frequency divider (needed for lower frequency input signals) 
 +    dwf.FDwfDigitalInDividerSet(device_data.handle, ctypes.c_int(int(internal_frequency.value / sampling_frequency))) 
 +     
 +    # set 16-bit sample format 
 +    dwf.FDwfDigitalInSampleFormatSet(device_data.handle, ctypes.c_int(16)) 
 +     
 +    # set buffer size 
 +    dwf.FDwfDigitalInBufferSizeSet(device_data.handle, ctypes.c_int(buffer_size)) 
 +    data.sampling_frequency = sampling_frequency 
 +    data.buffer_size = buffer_size 
 +    return 
 +</code></WRAP></WRAP> 
 + 
 +=== 3.5.2 Record Logic Signals ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Record logic signals in a list of lists, then select the one specific for the required DIO line. Record logic signals in a list of lists, then select the one specific for the required DIO line.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Flogic.py%23L99-L140&style=github&showCopy=on"></script> +def record(device_data, channel): 
-</html></WRAP></WRAP>+    """ 
 +        initialize the logic analyzer 
 +        parameters- device data 
 +                    - channel - the selected DIO line number 
 +        returns:    - buffer - a list with the recorded logic values 
 +                    - time - a list with the time moments for each value in seconds (with the same index as "buffer"
 +    """ 
 +    # set up the instrument 
 +    dwf.FDwfDigitalInConfigure(device_data.handle, ctypes.c_bool(False), ctypes.c_bool(True)) 
 +     
 +    # read data to an internal buffer 
 +    while True: 
 +        status ctypes.c_byte()    # variable to store buffer status 
 +        dwf.FDwfDigitalInStatus(device_data.handle, ctypes.c_bool(True), ctypes.byref(status)) 
 +     
 +        if status.value == constants.stsDone.value: 
 +            # exit loop when finished 
 +            break 
 +     
 +    # get samples 
 +    buffer = (ctypes.c_uint16 * data.buffer_size)() 
 +    dwf.FDwfDigitalInStatusData(device_data.handle, buffer, ctypes.c_int(2 * data.buffer_size)) 
 +     
 +    # convert buffer to list of lists of integers 
 +    buffer = [int(element) for element in buffer] 
 +    result = [[] for _ in range(16)] 
 +    for point in buffer: 
 +        for index in range(16): 
 +            result[index].append(point & (1 << index)) 
 +     
 +    # calculate acquisition time 
 +    time = range(0, data.buffer_size) 
 +    time = [moment data.sampling_frequency for moment in time] 
 +     
 +    # get channel specific data 
 +    buffer = result[channel] 
 +    return buffer, time 
 +</code></WRAP></WRAP>
  
-=== 3.3 Reset the Logic Analyzer ===+=== 3.5.3 Reset the Logic Analyzer ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 After usage, reset the logic analyzer to the default settings. After usage, reset the logic analyzer to the default settings.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Flogic.py%23L144-L149&style=github&showCopy=on"></script> +def close(device_data): 
-</html></WRAP></WRAP> +    """ 
- +        reset the instrument 
---> Optional: Triggering # +    """ 
-<WRAP group><WRAP half column> +    dwf.FDwfDigitalInReset(device_data.handle) 
-Before recording a signal, you might want to set up triggeringSet the trigger parameters to fit your needs+    return 
-</WRAP><WRAP half column><html> +</code></WRAP></WRAP>
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Flogic.py%23L52-L95&style=github&showCopy=on"></script> +
-</html></WRAP></WRAP> +
-<-- +
-----+
 </WRAP> </WRAP>
 <-- <--
  
---> Pattern Generator #+--> 3.6 Pattern Generator #
 <WRAP group> <WRAP group>
-=== 3.1 Generate Logic Signals ===+=== 3.6.1 Generate Logic Signals ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Configure the pattern generator to generate logic signals. Configure the pattern generator to generate logic signals.
Line 296: Line 794:
  
 <WRAP center round tip 80%> <WRAP center round tip 80%>
-You can define custom function and trigger source names, to make the usage of the function easier.+You can define custom functiontrigger source and idle state names, to make the usage of the function easier.
 </WRAP> </WRAP>
  
-<html+<code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fpattern.py%23L28-L32&style=github&showCopy=on"></script> +class function: 
-</html>+    """ function names """ 
 +    pulse constants.DwfDigitalOutTypePulse 
 +    custom constants.DwfDigitalOutTypeCustom 
 +    random = constants.DwfDigitalOutTypeRandom
  
-<html> +class trigger_source: 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fpattern.py%23L36-L41&style=github&showCopy=on"></script> +    """ trigger source names """ 
-</html> +    none constants.trigsrcNone 
-</WRAP><WRAP half column><html> +    analog = constants.trigsrcDetectorAnalogIn 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fpattern.py%23L45-L126&style=github&showCopy=on"></script> +    digital constants.trigsrcDetectorDigitalIn 
-</html></WRAP></WRAP>+    external [None, constants.trigsrcExternal1, constants.trigsrcExternal2, constants.trigsrcExternal3, constants.trigsrcExternal4]
  
-=== 3.2 Reset the Pattern Generator ===+class idle_state: 
 +    """ channel idle states """ 
 +    initial = constants.DwfDigitalOutIdleInit 
 +    high = constants.DwfDigitalOutIdleHigh 
 +    low = constants.DwfDigitalOutIdleLow 
 +    high_impedance = constants.DwfDigitalOutIdleZet 
 +</code> 
 + 
 +</WRAP><WRAP half column><code python> 
 +def generate(device_data, channel, function, frequency, duty_cycle=50, data=[], wait=0, repeat=0, run_time=0, idle=idle_state.initial, trigger_enabled=False, trigger_source=trigger_source.none, trigger_edge_rising=True): 
 +    """ 
 +        generate a logic signal 
 +         
 +        parameters: - channel - the selected DIO line number 
 +                    - function - possible: pulse, custom, random 
 +                    - frequency in Hz 
 +                    - duty cycle in percentage, used only if function = pulse, default is 50% 
 +                    - data list, used only if function = custom, default is empty 
 +                    - wait time in seconds, default is 0 seconds 
 +                    - repeat count, default is infinite (0) 
 +                    - run_time: in seconds, 0=infinite, "auto"=auto 
 +                    - idle - possible: initial, high, low, high_impedance, default = initial 
 +                    - trigger_enabled - include/exclude trigger from repeat cycle 
 +                    - trigger_source - possible: none, analog, digital, external[1-4] 
 +                    - trigger_edge_rising - True means rising, False means falling, None means either, default is rising 
 +    """ 
 +    # get internal clock frequency 
 +    internal_frequency = ctypes.c_double() 
 +    dwf.FDwfDigitalOutInternalClockInfo(device_data.handle, ctypes.byref(internal_frequency)) 
 +     
 +    # get counter value range 
 +    counter_limit = ctypes.c_uint() 
 +    dwf.FDwfDigitalOutCounterInfo(device_data.handle, ctypes.c_int(channel), ctypes.c_int(0), ctypes.byref(counter_limit)) 
 +     
 +    # calculate the divider for the given signal frequency 
 +    if function == constants.DwfDigitalOutTypePulse: 
 +        divider = int(-(-(internal_frequency.value / frequency) // counter_limit.value)) 
 +    else: 
 +        divider = int(internal_frequency.value / frequency) 
 +     
 +    # enable the respective channel 
 +    dwf.FDwfDigitalOutEnableSet(device_data.handle, ctypes.c_int(channel), ctypes.c_int(1)) 
 +     
 +    # set output type 
 +    dwf.FDwfDigitalOutTypeSet(device_data.handle, ctypes.c_int(channel), function) 
 +     
 +    # set frequency 
 +    dwf.FDwfDigitalOutDividerSet(device_data.handle, ctypes.c_int(channel), ctypes.c_int(divider)) 
 + 
 +    # set idle state 
 +    dwf.FDwfDigitalOutIdleSet(device_data.handle, ctypes.c_int(channel), idle) 
 + 
 +    # set PWM signal duty cycle 
 +    if function == constants.DwfDigitalOutTypePulse: 
 +        # calculate counter steps to get the required frequency 
 +        steps = int(round(internal_frequency.value / frequency / divider)) 
 +        # calculate steps for low and high parts of the period 
 +        high_steps = int(steps * duty_cycle / 100) 
 +        low_steps = int(steps - high_steps) 
 +        dwf.FDwfDigitalOutCounterSet(device_data.handle, ctypes.c_int(channel), ctypes.c_int(low_steps), ctypes.c_int(high_steps)) 
 +     
 +    # load custom signal data 
 +    elif function == constants.DwfDigitalOutTypeCustom: 
 +        # format data 
 +        buffer = (ctypes.c_ubyte * ((len(data) + 7) >> 3))(0) 
 +        for index in range(len(data)): 
 +            if data[index] != 0: 
 +                buffer[index >> 3] |= 1 << (index & 7) 
 +     
 +        # load data 
 +        dwf.FDwfDigitalOutDataSet(device_data.handle, ctypes.c_int(channel), ctypes.byref(buffer), ctypes.c_int(len(data))) 
 +     
 +    # calculate run length 
 +    if run_time == "auto": 
 +        run_time = len(data) / frequency 
 +     
 +    # set wait time 
 +    dwf.FDwfDigitalOutWaitSet(device_data.handle, ctypes.c_double(wait)) 
 +     
 +    # set repeat count 
 +    dwf.FDwfDigitalOutRepeatSet(device_data.handle, ctypes.c_int(repeat)) 
 +     
 +    # set run length 
 +    dwf.FDwfDigitalOutRunSet(device_data.handle, ctypes.c_double(run_time)) 
 + 
 +    # enable triggering 
 +    dwf.FDwfDigitalOutRepeatTriggerSet(device_data.handle, ctypes.c_int(trigger_enabled)) 
 +     
 +    if trigger_enabled: 
 +        # set trigger source 
 +        dwf.FDwfDigitalOutTriggerSourceSet(device_data.handle, trigger_source) 
 +     
 +        # set trigger slope 
 +        if trigger_edge_rising == True: 
 +            # rising edge 
 +            dwf.FDwfDigitalOutTriggerSlopeSet(device_data.handle, constants.DwfTriggerSlopeRise) 
 +        elif trigger_edge_rising == False: 
 +            # falling edge 
 +            dwf.FDwfDigitalOutTriggerSlopeSet(device_data.handle, constants.DwfTriggerSlopeFall) 
 +        elif trigger_edge_rising == None: 
 +            # either edge 
 +            dwf.FDwfDigitalOutTriggerSlopeSet(device_data.handle, constants.DwfTriggerSlopeEither) 
 + 
 +    # start generating the signal 
 +    dwf.FDwfDigitalOutConfigure(device_data.handle, ctypes.c_int(True)) 
 +    return 
 +</code></WRAP></WRAP> 
 + 
 +=== 3.6.2 Reset the Pattern Generator ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 After usage, reset the pattern generator to the default settings. After usage, reset the pattern generator to the default settings.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fpattern.py%23L130-L135&style=github&showCopy=on"></script> +def close(device_data): 
-</html></WRAP></WRAP> +    ""
-----+        reset the instrument 
 +    """ 
 +    dwf.FDwfDigitalOutReset(device_data.handle) 
 +    return 
 +</code></WRAP></WRAP>
 </WRAP> </WRAP>
 <-- <--
  
---> Static I/O #+--> 3.7 Static I/O #
 <WRAP group> <WRAP group>
-=== 3.1 Set Pins As Input Or As Output ===+=== 3.7.1 Set Pins As Input Or As Output ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Each digital pin of the Test & Measurement device can be used only as input, or as output at a time. The default settings for each line are input states. Each digital pin of the Test & Measurement device can be used only as input, or as output at a time. The default settings for each line are input states.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fstatic.py%23L28-L55&style=github&showCopy=on"></script> +def set_mode(device_data, channel, output): 
-</html></WRAP></WRAP>+    """ 
 +        set a DIO line as input, or as output 
 +        parameters- device data 
 +                    - selected DIO channel number 
 +                    - True means output, False means input 
 +    """ 
 +    # load current state of the output enable buffer 
 +    mask = ctypes.c_uint16() 
 +    dwf.FDwfDigitalIOOutputEnableGet(device_data.handle, ctypes.byref(mask)) 
 +     
 +    # convert mask to list 
 +    mask list(bin(mask.value)[2:].zfill(16)) 
 +     
 +    # set bit in mask 
 +    if output: 
 +        mask[15 channel] "1" 
 +    else: 
 +        mask[15 - channel] = "0" 
 +     
 +    # convert mask to number 
 +    mask = "".join(element for element in mask) 
 +    mask = int(mask, 2) 
 +     
 +    # set the pin to output 
 +    dwf.FDwfDigitalIOOutputEnableSet(device_data.handle, ctypes.c_int(mask)) 
 +    return 
 +</code></WRAP></WRAP>
  
-=== 3.2 Get Pin State ===+=== 3.7.2 Get Pin State ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Read the state of a DIO line with the following code snippet: Read the state of a DIO line with the following code snippet:
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fstatic.py%23L59-L83&style=github&showCopy=on"></script> +def get_state(device_data, channel): 
-</html></WRAP></WRAP>+    """ 
 +        get the state of a DIO line 
 +        parameters- device data 
 +                    - selected DIO channel number 
 +        returns:    - True if the channel is HIGH, or False, if the channel is LOW 
 +    """ 
 +    # load internal buffer with current state of the pins 
 +    dwf.FDwfDigitalIOStatus(device_data.handle) 
 +     
 +    # get the current state of the pins 
 +    data ctypes.c_uint32()  # variable for this current state 
 +    dwf.FDwfDigitalIOInputStatus(device_data.handle, ctypes.byref(data)) 
 +     
 +    # convert the state to a 16 character binary string 
 +    data list(bin(data.value)[2:].zfill(16)) 
 +     
 +    # check the required bit 
 +    if data[15 - channel] != "0": 
 +        value = True 
 +    else: 
 +        value = False 
 +    return value 
 +</code></WRAP></WRAP>
  
-=== 3.3 Set Pin State ===+=== 3.7.3 Set Pin State ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 To set the state of a DIO line, it must be set as output! To set the state of a DIO line, it must be set as output!
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fstatic.py%23L87-L114&style=github&showCopy=on"></script> +def set_state(device_data, channel, value): 
-</html></WRAP></WRAP>+    """ 
 +        set a DIO line as input, or as output 
 +        parameters- device data 
 +                    - selected DIO channel number 
 +                    - True means HIGH, False means LOW 
 +    """ 
 +    # load current state of the output state buffer 
 +    mask = ctypes.c_uint16() 
 +    dwf.FDwfDigitalIOOutputGet(device_data.handle, ctypes.byref(mask)) 
 +     
 +    # convert mask to list 
 +    mask list(bin(mask.value)[2:].zfill(16)) 
 +     
 +    # set bit in mask 
 +    if value: 
 +        mask[15 channel] "1" 
 +    else: 
 +        mask[15 - channel] = "0" 
 +     
 +    # convert mask to number 
 +    mask = "".join(element for element in mask) 
 +    mask = int(mask, 2) 
 +     
 +    # set the pin state 
 +    dwf.FDwfDigitalIOOutputSet(device_data.handle, ctypes.c_int(mask)) 
 +    return 
 +</code></WRAP></WRAP>
  
-=== 3.4 Reset the Static I/O ===+=== 3.7.4 Reset the Static I/O ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 After usage, reset the instrument to the default settings. After usage, reset the instrument to the default settings.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fstatic.py%23L210-L215&style=github&showCopy=on"></script> +def close(device_data): 
-</html></WRAP></WRAP> +    """ 
- +        reset the instrument 
---> Optional: Limiting DIO Channel Current # +    """ 
-<WRAP group><WRAP half column> +    dwf.FDwfDigitalIOReset(device_data.handle) 
-Test & Measurement devices with digital supplies (the Digital Discovery and the Analog Discovery Pro 3X50) also have options to limit the output current of a DIO channel. +    return 
- +</code></WRAP></WRAP>
-<WRAP center round important 60%> +
-This function was not tested.+
 </WRAP> </WRAP>
-</WRAP><WRAP half column><html> 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fstatic.py%23L118-L143&style=github&showCopy=on"></script> 
-</html></WRAP></WRAP> 
 <-- <--
  
---> Optional: DIO Channel Pull Up/Down # +--> 3.Protocol: UART #
-<WRAP group><WRAP half column> +
-Test & Measurement devices with digital supplies (the Digital Discovery and the Analog Discovery Pro 3X50) also have options to pull a DIO channel up, or down. +
- +
-<WRAP center round important 60%> +
-This function was not tested. +
-</WRAP> +
-</WRAP><WRAP half column><html> +
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fstatic.py%23L147-L206&style=github&showCopy=on"></script> +
-</html></WRAP></WRAP> +
-<-- +
----- +
-</WRAP> +
-<-- +
- +
---> Protocol: UART #+
 <WRAP group> <WRAP group>
-=== 3.1 Initialize the Interface ===+=== 3.8.1 Initialize the Interface ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Before using a communication interface, it must be initialized by setting the communication parameters to the desired values. Before using a communication interface, it must be initialized by setting the communication parameters to the desired values.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fuart.py%23L28-L73&style=github&showCopy=on"></script> +def open(device_data, rx, tx, baud_rate=9600, parity=None, data_bits=8, stop_bits=1): 
-</html></WRAP></WRAP>+    """ 
 +        initializes UART communication 
 +         
 +        parameters- device data 
 +                    - rx (DIO line used to receive data) 
 +                    - tx (DIO line used to send data) 
 +                    - baud_rate (communication speed, default is 9600 bits/s) 
 +                    - parity possible: None (default), True means even, False means odd 
 +                    - data_bits (default is 8) 
 +                    - stop_bits (default is 1) 
 +    """ 
 +    # set baud rate 
 +    dwf.FDwfDigitalUartRateSet(device_data.handle, ctypes.c_double(baud_rate)) 
 + 
 +    # set communication channels 
 +    dwf.FDwfDigitalUartTxSet(device_data.handle, ctypes.c_int(tx)) 
 +    dwf.FDwfDigitalUartRxSet(device_data.handle, ctypes.c_int(rx)) 
 + 
 +    # set data bit count 
 +    dwf.FDwfDigitalUartBitsSet(device_data.handle, ctypes.c_int(data_bits)) 
 + 
 +    # set parity bit requirements 
 +    if parity == True: 
 +        parity = 2 
 +    elif parity == False: 
 +        parity = 1 
 +    else: 
 +        parity = 0 
 +    dwf.FDwfDigitalUartParitySet(device_data.handle, ctypes.c_int(parity)) 
 + 
 +    # set stop bit count 
 +    dwf.FDwfDigitalUartStopSet(device_data.handle, ctypes.c_double(stop_bits)) 
 + 
 +    # initialize channels with idle levels 
 + 
 +    # dummy read 
 +    dummy_buffer ctypes.create_string_buffer(0) 
 +    dummy_buffer ctypes.c_int(0) 
 +    dummy_parity_flag = ctypes.c_int(0) 
 +    dwf.FDwfDigitalUartRx(device_data.handle, dummy_buffer, ctypes.c_int(0), ctypes.byref(dummy_buffer), ctypes.byref(dummy_parity_flag)) 
 + 
 +    # dummy write 
 +    dwf.FDwfDigitalUartTx(device_data.handle, dummy_buffer, ctypes.c_int(0)) 
 +    return 
 +</code></WRAP></WRAP>
  
-=== 3.2 Receive Data ===+=== 3.8.2 Receive Data ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Use the function to the right to read data on an initialized UART interface. Use the function to the right to read data on an initialized UART interface.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fuart.py%23L77-L130&style=github&showCopy=on"></script> +def read(device_data): 
-</html></WRAP></WRAP>+    """ 
 +        receives data from UART 
 +         
 +        parameters: - device data 
 +        return:     integer list containing the received bytes 
 +                    error message or empty string 
 +    """ 
 +    # variable to store results 
 +    error = "" 
 +    rx_data = []
  
-=== 3.3 Send Data ===+    # create empty string buffer 
 +    data = (ctypes.c_ubyte * 8193)() 
 + 
 +    # character counter 
 +    count = ctypes.c_int(0) 
 + 
 +    # parity flag 
 +    parity_flag= ctypes.c_int(0) 
 + 
 +    # read up to 8k characters 
 +    dwf.FDwfDigitalUartRx(device_data.handle, data, ctypes.c_int(ctypes.sizeof(data)-1), ctypes.byref(count), ctypes.byref(parity_flag)) 
 + 
 +    # append current data chunks 
 +    for index in range(0, count.value): 
 +        rx_data.append(int(data[index])) 
 + 
 +    # ensure data integrity 
 +    while count.value > 0: 
 +        # create empty string buffer 
 +        data = (ctypes.c_ubyte * 8193)() 
 + 
 +        # character counter 
 +        count = ctypes.c_int(0) 
 + 
 +        # parity flag 
 +        parity_flag= ctypes.c_int(0) 
 + 
 +        # read up to 8k characters 
 +        dwf.FDwfDigitalUartRx(device_data.handle, data, ctypes.c_int(ctypes.sizeof(data)-1), ctypes.byref(count), ctypes.byref(parity_flag)) 
 +        # append current data chunks 
 +        for index in range(0, count.value): 
 +            rx_data.append(int(data[index])) 
 + 
 +        # check for not acknowledged 
 +        if error == "": 
 +            if parity_flag.value < 0: 
 +                error = "Buffer overflow" 
 +            elif parity_flag.value > 0: 
 +                error = "Parity error: index {}".format(parity_flag.value) 
 +    return rx_data,  
 +</code></WRAP></WRAP> 
 + 
 +=== 3.8.3 Send Data ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Use the function to the right to send data on an initialized UART interface to another device. Use the function to the right to send data on an initialized UART interface to another device.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fuart.py%23L134-L152&style=github&showCopy=on"></script> +def write(device_data, data): 
-</html></WRAP></WRAP>+    """ 
 +        send data through UART 
 +         
 +        parameters- data of type string, int, or list of characters/integers 
 +    """ 
 +    # cast data 
 +    if type(data) == int: 
 +        data = "".join(chr (data)) 
 +    elif type(data) == list: 
 +        data = "".join(chr (element) for element in data)
  
-=== 3.4 Reset the Interface ===+    # encode the string into a string buffer 
 +    data = ctypes.create_string_buffer(data.encode("UTF-8")) 
 + 
 +    # send text, trim zero ending 
 +    dwf.FDwfDigitalUartTx(device_data.handle, data, ctypes.c_int(ctypes.sizeof(data)-1)) 
 +    return 
 +</code></WRAP></WRAP> 
 + 
 +=== 3.8.4 Reset the Interface ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 After usage, reset the instrument to the default settings. After usage, reset the instrument to the default settings.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fuart.py%23L156-L161&style=github&showCopy=on"></script> +def close(device_data): 
-</html></WRAP></WRAP> +    ""
-----+        reset the uart interface 
 +    """ 
 +    dwf.FDwfDigitalUartReset(device_data.handle) 
 +    return 
 +</code></WRAP></WRAP>
 </WRAP> </WRAP>
 <-- <--
  
---> Protocol: SPI #+--> 3.9 Protocol: SPI #
 <WRAP group> <WRAP group>
-=== 3.1 Initialize the Interface ===+=== 3.9.1 Initialize the Interface ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Before using a communication interface, it must be initialized by setting the communication parameters to the desired values. Before using a communication interface, it must be initialized by setting the communication parameters to the desired values.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fspi.py%23L28-L78&style=github&showCopy=on"></script> +def open(device_data, cs, sck, miso=None, mosi=None, clk_frequency=1e06, mode=0, order=True): 
-</html></WRAP></WRAP>+    """ 
 +        initializes SPI communication 
 +        parameters: - device data 
 +                    cs (DIO line used for chip select) 
 +                    sck (DIO line used for serial clock) 
 +                    miso (DIO line used for master in - slave out, optional) 
 +                    - mosi (DIO line used for master out - slave in, optional) 
 +                    - frequency (communication frequency in Hz, default is 1MHz) 
 +                    - mode (SPI mode: 0: CPOL=0, CPHA=0; 1: CPOL-0, CPHA=1; 2: CPOL=1, CPHA=0; 3: CPOL=1, CPHA=1) 
 +                    - order (endianness, True means MSB first - default, False means LSB first) 
 +    ""
 +    # set the clock frequency 
 +    dwf.FDwfDigitalSpiFrequencySet(device_data.handle, ctypes.c_double(clk_frequency))
  
-=== 3.2 Receive Data ===+    # set the clock pin 
 +    dwf.FDwfDigitalSpiClockSet(device_data.handle, ctypes.c_int(sck)) 
 + 
 +    if mosi != None: 
 +        # set the mosi pin 
 +        dwf.FDwfDigitalSpiDataSet(device_data.handle, ctypes.c_int(0), ctypes.c_int(mosi)) 
 + 
 +        # set the initial state 
 +        dwf.FDwfDigitalSpiIdleSet(device_data.handle, ctypes.c_int(0), constants.DwfDigitalOutIdleZet) 
 + 
 +    if miso != None: 
 +        # set the miso pin 
 +        dwf.FDwfDigitalSpiDataSet(device_data.handle, ctypes.c_int(1), ctypes.c_int(miso)) 
 + 
 +        # set the initial state 
 +        dwf.FDwfDigitalSpiIdleSet(device_data.handle, ctypes.c_int(1), constants.DwfDigitalOutIdleZet) 
 + 
 +    # set the SPI mode 
 +    dwf.FDwfDigitalSpiModeSet(device_data.handle, ctypes.c_int(mode)) 
 + 
 +    # set endianness 
 +    if order: 
 +        # MSB first 
 +        dwf.FDwfDigitalSpiOrderSet(device_data.handle, ctypes.c_int(1)) 
 +    else: 
 +        # LSB first 
 +        dwf.FDwfDigitalSpiOrderSet(device_data.handle, ctypes.c_int(0)) 
 + 
 +    # set the cs pin HIGH 
 +    dwf.FDwfDigitalSpiSelect(device_data.handle, ctypes.c_int(cs), ctypes.c_int(1)) 
 + 
 +    # dummy write 
 +    dwf.FDwfDigitalSpiWriteOne(device_data.handle, ctypes.c_int(1), ctypes.c_int(0), ctypes.c_int(0)) 
 +    return 
 +</code></WRAP></WRAP> 
 + 
 +=== 3.9.2 Receive Data ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Use the function to the right to read data on an initialized SPI interface. Use the function to the right to read data on an initialized SPI interface.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fspi.py%23L82-L107&style=github&showCopy=on"></script> +def read(device_data, count, cs): 
-</html></WRAP></WRAP>+    """ 
 +        receives data from SPI 
 +        parameters: - device data 
 +                    count (number of bytes to receive) 
 +                    chip select line number 
 +        return:     integer list containing the received bytes 
 +    ""
 +    # enable the chip select line 
 +    dwf.FDwfDigitalSpiSelect(device_data.handle, ctypes.c_int(cs), ctypes.c_int(0))
  
-=== 3.3 Send Data ===+    # create buffer to store data 
 +    buffer = (ctypes.c_ubyte*count)() 
 + 
 +    # read array of 8 bit elements 
 +    dwf.FDwfDigitalSpiRead(device_data.handle, ctypes.c_int(1), ctypes.c_int(8), buffer, ctypes.c_int(len(buffer))) 
 + 
 +    # disable the chip select line 
 +    dwf.FDwfDigitalSpiSelect(device_data.handle, ctypes.c_int(cs), ctypes.c_int(1)) 
 + 
 +    # decode data 
 +    data = [int(element) for element in buffer] 
 +    return data 
 +</code></WRAP></WRAP> 
 + 
 +=== 3.9.3 Send Data ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Use the function to the right to send data on an initialized SPI interface to another device. Use the function to the right to send data on an initialized SPI interface to another device.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fspi.py%23L111-L140&style=github&showCopy=on"></script> +def write(device_data, data, cs): 
-</html></WRAP></WRAP>+    """ 
 +        send data through SPI 
 +        parameters: - device data 
 +                    data of type string, int, or list of characters/integers 
 +                    chip select line number 
 +    """ 
 +    # cast data 
 +    if type(data) == int: 
 +        data = "".join(chr (data)) 
 +    elif type(data) == list: 
 +        data = "".join(chr (element) for element in data)
  
-=== 3.4 Exchange Data === +    # enable the chip select line 
-<WRAP group><WRAP half column> +    dwf.FDwfDigitalSpiSelect(device_data.handle, ctypes.c_int(cs), ctypes.c_int(0))
-You might want to receive data from a slave device while you are sending commands to it. In this case the data exchanging function can be used. +
-</WRAP><WRAP half column><html> +
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fspi.py%23L144-L182&style=github&showCopy=on"></script> +
-</html></WRAP></WRAP>+
  
-=== 3.5 Spy on SPI communication === +    # create buffer to write 
-<WRAP group><WRAP half column> +    data bytes(data, "utf-8"
-If two other devices, a master and a slaveare communicating using the initialized communication interface, the Test & Measurement device can be used to spy on this communication (record both incoming and outgoing data).+    buffer (ctypes.c_ubyte * len(data))() 
 +    for index in range(0len(buffer)): 
 +        buffer[index] = ctypes.c_ubyte(data[index])
  
-<WRAP center round important 60%> +    # write array of 8 bit elements 
-This function was not tested+    dwf.FDwfDigitalSpiWrite(device_data.handle, ctypes.c_int(1), ctypes.c_int(8), buffer, ctypes.c_int(len(buffer))) 
-</WRAP> + 
-</WRAP><WRAP half column><html> +    # disable the chip select line 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fspi.py%23L186-L292&style=github&showCopy=on"></script> +    dwf.FDwfDigitalSpiSelect(device_data.handle, ctypes.c_int(cs), ctypes.c_int(1)) 
-</html></WRAP></WRAP>+    return 
 +</code></WRAP></WRAP>
  
-=== 3.Reset the Interface ===+=== 3.9.4 Reset the Interface ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 After usage, reset the instrument to the default settings. After usage, reset the instrument to the default settings.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fspi.py%23L296-L301&style=github&showCopy=on"></script> +def close(device_data): 
-</html></WRAP></WRAP> +    ""
-----+        reset the spi interface 
 +    """ 
 +    dwf.FDwfDigitalSpiReset(device_data.handle) 
 +    return 
 +</code></WRAP></WRAP>
 </WRAP> </WRAP>
 <-- <--
  
---> Protocol: I2C #+--> 3.10 Protocol: I2C #
 <WRAP group> <WRAP group>
-=== 3.1 Initialize the Interface ===+=== 3.10.1 Initialize the Interface ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Before using a communication interface, it must be initialized by setting the communication parameters to the desired values. Before using a communication interface, it must be initialized by setting the communication parameters to the desired values.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fi2c.py%23L28-L68&style=github&showCopy=on"></script> +def open(device_data, sda, scl, clk_rate=100e03, stretching=True): 
-</html></WRAP></WRAP>+    """ 
 +        initializes I2C communication 
 +        parameters: - device data 
 +                    sda (DIO line used for data) 
 +                    scl (DIO line used for clock) 
 +                    rate (clock frequency in Hz, default is 100KHz) 
 +                    - stretching (enables/disables clock stretching) 
 +        returns:    - error message or empty string 
 +    """ 
 +    # reset the interface 
 +    dwf.FDwfDigitalI2cReset(device_data.handle)
  
-=== 3.2 Receive Data ===+    # clock stretching 
 +    if stretching: 
 +        dwf.FDwfDigitalI2cStretchSet(device_data.handle, ctypes.c_int(1)) 
 +    else: 
 +        dwf.FDwfDigitalI2cStretchSet(device_data.handle, ctypes.c_int(0)) 
 + 
 +    # set clock frequency 
 +    dwf.FDwfDigitalI2cRateSet(device_data.handle, ctypes.c_double(clk_rate)) 
 + 
 +    #  set communication lines 
 +    dwf.FDwfDigitalI2cSclSet(device_data.handle, ctypes.c_int(scl)) 
 +    dwf.FDwfDigitalI2cSdaSet(device_data.handle, ctypes.c_int(sda)) 
 + 
 +    # check bus 
 +    nak = ctypes.c_int() 
 +    dwf.FDwfDigitalI2cClear(device_data.handle, ctypes.byref(nak)) 
 +    if nak.value == 0: 
 +        return "Error: I2C bus lockup" 
 + 
 +    # write 0 bytes 
 +    dwf.FDwfDigitalI2cWrite(device_data.handle, ctypes.c_int(0), ctypes.c_int(0), ctypes.c_int(0), ctypes.byref(nak)) 
 +    if nak.value != 0: 
 +        return "NAK: index " + str(nak.value) 
 +    return "" 
 +</code></WRAP></WRAP> 
 + 
 +=== 3.10.2 Receive Data ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Use the function to the right to read data on an initialized I2C interface. Use the function to the right to read data on an initialized I2C interface.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fi2c.py%23L106-L131&style=github&showCopy=on"></script> +def read(device_data, count, address): 
-</html></WRAP></WRAP>+    """ 
 +        receives data from I2C 
 +         
 +        parameters: - device data 
 +                    count (number of bytes to receive) 
 +                    address (8-bit address of the slave device) 
 +         
 +        return:     - integer list containing the received bytes 
 +                    - error message or empty string 
 +    """ 
 +    # create buffer to store data 
 +    buffer (ctypes.c_ubyte * count)() 
 + 
 +    # receive 
 +    nak ctypes.c_int() 
 +    dwf.FDwfDigitalI2cRead(device_data.handle, ctypes.c_int(address << 1), buffer, ctypes.c_int(count), ctypes.byref(nak)) 
 + 
 +    # decode data 
 +    data = [int(element) for element in buffer]
  
-=== 3.3 Send Data ===+    # check for not acknowledged 
 +    if nak.value != 0: 
 +        return data, "NAK: index " + str(nak.value) 
 +    return data, "" 
 +</code></WRAP></WRAP> 
 + 
 +=== 3.10.3 Send Data ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 Use the function to the right to send data on an initialized I2C interface to another device. Use the function to the right to send data on an initialized I2C interface to another device.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fi2c.py%23L72-L102&style=github&showCopy=on"></script> +def write(device_data, data, address): 
-</html></WRAP></WRAP>+    """ 
 +        send data through I2C 
 +         
 +        parameters: - device data 
 +                    data of type string, int, or list of characters/integers 
 +                    address (8-bit address of the slave device) 
 +                     
 +        returns:    - error message or empty string 
 +    """ 
 +    # cast data 
 +    if type(data) == int: 
 +        data = "".join(chr (data)) 
 +    elif type(data) == list: 
 +        data = "".join(chr (element) for element in data)
  
-=== 3.4 Exchange Data === +    # encode the string into a string buffer 
-<WRAP group><WRAP half column> +    data bytes(data, "utf-8"
-You might want to receive data from a slave device while you are sending commands to it. In this case the data exchanging function can be used. +    buffer (ctypes.c_ubyte * len(data))() 
-</WRAP><WRAP half column><html> +    for index in range(0, len(buffer)): 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fi2c.py%23L135-L173&style=github&showCopy=on"></script> +        buffer[index] ctypes.c_ubyte(data[index])
-</html></WRAP></WRAP>+
  
-=== 3.5 Spy on I2C communication === +    # send 
-<WRAP group><WRAP half column> +    nak ctypes.c_int() 
-If two other devicesa master and a slaveare communicating using the initialized communication interface, the Test & Measurement device can be used to spy on this communication (record both incoming and outgoing data).+    dwf.FDwfDigitalI2cWrite(device_data.handle, ctypes.c_int(address << 1)bufferctypes.c_int(ctypes.sizeof(buffer)), ctypes.byref(nak))
  
-<WRAP center round important 60%> +    # check for not acknowledged 
-This function was not tested+    if nak.value != 0: 
-</WRAP> +        return "NAKindex " + str(nak.value) 
-</WRAP><WRAP half column><html> +    return "
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fi2c.py%23L177-L238&style=github&showCopy=on"></script> +</code></WRAP></WRAP>
-</html></WRAP></WRAP>+
  
-=== 3.Reset the Interface ===+=== 3.10.4 Reset the Interface ===
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 After usage, reset the instrument to the default settings. After usage, reset the instrument to the default settings.
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fi2c.py%23L242-L247&style=github&showCopy=on"></script> +def close(device_data): 
-</html></WRAP></WRAP> +    ""
-----+        reset the i2c interface 
 +    """ 
 +    dwf.FDwfDigitalI2cReset(device_data.handle) 
 +    return 
 +</code></WRAP></WRAP>
 </WRAP> </WRAP>
 <-- <--
- 
-<WRAP group> 
-The code snippets above present basic functionality of some instruments. For more possibilities (advanced features and more instruments) check the documentation of the WaveForms SDK and the available sample scripts. 
-</WRAP> 
 ---- ----
 ==== 4. Disconnecting the Device ==== ==== 4. Disconnecting the Device ====
 <WRAP group><WRAP half column> <WRAP group><WRAP half column>
 When your script is exiting, it is very important to close the opened connections, to make the device available for other software (like the WaveForms application). When your script is exiting, it is very important to close the opened connections, to make the device available for other software (like the WaveForms application).
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fdevice.py%23L143-L148&style=github&showCopy=on"></script> +def close(device_data): 
-</html></WRAP></WRAP>+    ""
 +        close a specific device 
 +    """ 
 +    dwf.FDwfDeviceClose(device_data.handle) 
 +    return 
 +</code></WRAP></WRAP>
 ---- ----
 ===== Creating Modules ===== ===== Creating Modules =====
Line 527: Line 1469:
 To avoid copying several hundred lines of code into every project, you can create Python modules from the functions controlling the instruments. These modules then can be imported in your project. To avoid copying several hundred lines of code into every project, you can create Python modules from the functions controlling the instruments. These modules then can be imported in your project.
  
-To create a module, create a new file with the desired name and the extension ***.py**, then copy the respective functions into that file. Don't forget to also import the dwfconstants file into every module.+To create a module, create a new file with the desired name and the extension ***.py**, then copy the respective functions into that file. Don't forget to also import the dwfconstants file into every module. Place your modules in a separate folder, name this folder (for example WF_SDK is a good name as it is suggestive).
  
-Place your modules in a separate folder, name this folder (for example WF_SDK is a good name as it is suggestive), then copy the **dwfconstants.py** file into the same folder. +You can download the archive containing the module and some test files [[https://github.com/Digilent/WaveForms-SDK-Getting-Started-PY/archive/refs/heads/master.zip|here]].
- +
-<WRAP center round important 60%> +
-Don't forget to correct the import path of the **dwfconstants.py** file, if you import it from the project directory. The name of the parent directory (WF_SDK), followed by a dot must be added before the file name. +
- +
-If you import the file from the installation folder, no changes have to be made.+
 </WRAP> </WRAP>
  
-You can download the archive containing the module and some test files [[https://github.com/Digilent/WaveForms-SDK-Getting-Started/archive/refs/heads/master.zip|here]].+<WRAP group> 
 +As the created function set will be used as a module, an initializer is needed, to let the editors recognize the module. This file contains only the description of the module and imports every file in the module, to make the functions accessibleThe created file has to be named <html><b>__init__.py</b></html> and must be put in the module directoryAfter the file is created, your module will be recognized: the module name in the text editor will be colored (this depends on the editor) and if you hover the mouse on the module name, the module description appears.
  
-Open the drop-downs below to see the content of the created modules. +<code python> 
-</WRAP>+""" 
 +This module realizes communication with Digilent Test & Measurement devices 
 +"""
  
---> Device Control - device.py # +from WF_SDK import device 
-<WRAP group><html> +from WF_SDK import scope 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fdevice.py&style=github&showCopy=on"></script> +from WF_SDK import wavegen 
-</html></WRAP> +from WF_SDK import supplies 
-<--+from WF_SDK import dmm 
 +from WF_SDK import logic 
 +from WF_SDK import pattern 
 +from WF_SDK import static 
 +from WF_SDK import protocol 
 +</code>
  
---> Oscilloscope Control - scope.py # +Remember, that any submodule (the protocol folder in this case) also needs initialization:
-<WRAP group><html> +
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fscope.py&style=github&showCopy=on"></script> +
-</html></WRAP> +
-<--+
  
---> Waveform Generator Control - wavegen.py # +<code python
-<WRAP group><html+""" 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fwavegen.py&style=github&showCopy=on"></script> +This module controls the protocol instrument 
-</html></WRAP> +"""
-<--+
  
---> Power Supplies Control - supplies.py # +from WF_SDK.protocol import i2c 
-<WRAP group><html> +from WF_SDK.protocol import spi 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fsupplies.py&style=github&showCopy=on"></script> +from WF_SDK.protocol import uart 
-</html></WRAP> +</code></WRAP> 
-<--+----
  
---> Digital Multimeter Control - supplies.py #+==== Testing ====
 <WRAP group> <WRAP group>
-<WRAP center round important 60%> +Copy your module folder (WF_SDK in this case) into the project directory, then create a new Python script. Import the necessary modules, then use your functions to control the Test & Measurement device. 
-This module contains untested functions.+ 
 +In the drop-downs below, several examples and a project template will be presented. 
 + 
 +**Note: ** //The example using the oscilloscope and the waveform generator won't work on devices without analog I/O capability (Digital Discovery).// 
 + 
 +**Note: ** //Name your test scripts "test_testname.py"This will be important if you want to install the module as a package.//
 </WRAP> </WRAP>
  
-<html+--Empty Project Template # 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fdmm.py&style=github&showCopy=on"></script+<WRAP group><WRAP half column> 
-</html></WRAP> +Fill in this template. Be creative, use any instrument in any configuration. 
-<--+</WRAP><WRAP half column><code python
 +from WF_SDK import device       # import instruments
  
---> Logic Analyzer Control logic.py # +"""-----------------------------------------------------------------------"""
-<WRAP group><html> +
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Flogic.py&style=github&showCopy=on"></script> +
-</html></WRAP> +
-<--+
  
---> Pattern Generator Control - pattern.py +connect to the device 
-<WRAP group><html> +device_data device.open()
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fpattern.py&style=github&showCopy=on"></script> +
-</html></WRAP> +
-<--+
  
---> Static I/O Control static.py # +"""-----------------------------------"""
-<WRAP group> +
-<WRAP center round important 60%> +
-This module contains untested functions. +
-</WRAP>+
  
-<html> +# use instruments here
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fstatic.py&style=github&showCopy=on"></script> +
-</html></WRAP> +
-<--+
  
---> Protocol: UART Interface - protocol/uart.py # 
-<WRAP group> 
-<html> 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fuart.py&style=github&showCopy=on"></script> 
-</html></WRAP> 
-<-- 
  
---> Protocol: SPI Interface protocol/spi.py # +"""-----------------------------------"""
-<WRAP group> +
-<WRAP center round important 60%> +
-This module contains untested functions. +
-</WRAP>+
  
-<html> +# close the connection 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fspi.py&style=github&showCopy=on"></script> +device.close(device_data) 
-</html></WRAP>+</code></WRAP></WRAP>
 <-- <--
  
---> Protocol: I2C Interface - protocol/i2c.py +--> Using the Oscilloscope and the Waveform Generator 
-<WRAP group> +<WRAP group><WRAP half column
-<WRAP center round important 60%+This example generates a sinusoidal signal on a wavegen channel, then records it on a scope channelConnect the respective channels together on your device!
-This module contains untested functions. +
-</WRAP>+
  
-<html> +{{ :test-and-measurement:analog-discovery-3:ad3-scope-wavegen-bb.png?400 |}}
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2Fprotocol%2Fi2c.py&style=github&showCopy=on"></script> +
-</html></WRAP> +
-<--+
  
-<WRAP group> +{{ :test-and-measurement:guides:scope-wavegen.png?600 |}} 
-As the created function set will be used as a module, an initializer is needed, to let the text editors recognize the module. This file contains only the description of the module and imports every file in the module, to make the functions accessibleThe created file has to be named <html><b>__init__.py</b></html> and must be put in the module directory.+</WRAP><WRAP half column><code python> 
 +from WF_SDK import device, scope, wavegen   # import instruments
  
-After the file is created, your module will be recognized: the module name in the text editor will be colored (this depends on the editor) and if you hover the mouse on the module name, the module description appears.+import matplotlib.pyplot as plt   # needed for plotting
  
-<html> +"""-----------------------------------------------------------------------"""
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2FWF_SDK%2F__init__.py&style=github&showCopy=on"></script></html> +
-</WRAP> +
-----+
  
-===== Testing ===== +# connect to the device 
-<WRAP group> +device_data = device.open()
-Copy your module folder (WF_SDK in this case) into the project directory, then create a new Python script. Import the necessary modules, then use your functions to control the Test & Measurement device.+
  
-In the drop-downs below, several examples and a project template will be presented.+"""-----------------------------------"""
  
-**Note: ** //The example using the oscilloscope and the waveform generator won't work on devices without analog I/O capability (Digital Discovery).// +# initialize the scope with default settings 
-</WRAP>+scope.open(device_data)
  
---> Empty Project Template +generate a 10KHz sine signal with 2V amplitude on channel 1 
-<WRAP group><WRAP half column> +wavegen.generate(device_datachannel=1, function=wavegen.function.sine, offset=0, frequency=10e03, amplitude=2)
-Fill in this templateBe creativeuse any instrument in any configuration. +
-</WRAP><WRAP half column><html> +
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2Ftest_template.py&style=github&showCopy=on"></script> +
-</html></WRAP></WRAP> +
-<--+
  
---> Using the Oscilloscope and the Waveform Generator # +# record data with the scopeon channel 1 
-<WRAP group><WRAP half column> +buffertime = scope.record(device_data, channel=1)
-This example generates a sinusoidal signal on a wavegen channelthen records it on a scope channel. Connect the respective channels together on your device!+
  
-{{ :test-and-measurement:guides:scope-wavegen_bb.png?400 |}}+# plot 
 +time = [moment * 1e03 for moment in time]   # convert time to ms 
 +plt.plot(time, buffer) 
 +plt.xlabel("time [ms]"
 +plt.ylabel("voltage [V]"
 +plt.show()
  
-{{ :test-and-measurement:guides:scope-wavegen.png?600 |}} +# reset the scope 
-</WRAP><WRAP half column><html> +scope.close(device_data) 
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2Ftest_scope-wavegen.py&style=github&showCopy=on"></script> + 
-</html></WRAP></WRAP>+# reset the wavegen 
 +wavegen.close(device_data) 
 + 
 +"""-----------------------------------""" 
 + 
 +# close the connection 
 +device.close(device_data) 
 +</code></WRAP></WRAP>
 <-- <--
  
Line 673: Line 1593:
  
 {{ :test-and-measurement:guides:logic-pattern.png?600 |}} {{ :test-and-measurement:guides:logic-pattern.png?600 |}}
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2Ftest_logic-pattern.py&style=github&showCopy=on"></script> +from WF_SDK import device, logic, pattern   # import instruments 
-</html></WRAP></WRAP>+ 
 +import matplotlib.pyplot as plt   # needed for plotting 
 + 
 +"""-----------------------------------------------------------------------""" 
 + 
 +# connect to the device 
 +device_data device.open() 
 + 
 +"""-----------------------------------""" 
 + 
 +# initialize the logic analyzer with default settings 
 +logic.open(device_data) 
 + 
 +# generate a 100KHz PWM signal with 30% duty cycle on DIO0 
 +pattern.generate(device_data, channel=0, function=pattern.function.pulse, frequency=100e03, duty_cycle=30) 
 + 
 +# record a logic signal on DIO0 
 +buffer, time = logic.record(device_data, channel=0) 
 + 
 +# plot 
 +time = [moment * 1e06 for moment in time]   # convert time to μs 
 +plt.plot(time, buffer) 
 +plt.xlabel("time [μs]"
 +plt.ylabel("logic value"
 +plt.yticks([0, 1]) 
 +plt.show() 
 + 
 +# reset the logic analyzer 
 +logic.close(device_data) 
 + 
 +# reset the pattern generator 
 +pattern.close(device_data) 
 + 
 +"""-----------------------------------""" 
 + 
 +# close the connection 
 +device.close(device_data) 
 +</code></WRAP></WRAP>
 <-- <--
  
Line 682: Line 1639:
 Connect LEDs and series resistors to each DIO channel of your device. Use the positive, or the digital power supply to provide current to the LEDs, then use the Static I/O instrument to sink the currents (turn the LEDs on/off). Connect LEDs and series resistors to each DIO channel of your device. Use the positive, or the digital power supply to provide current to the LEDs, then use the Static I/O instrument to sink the currents (turn the LEDs on/off).
  
-{{ :test-and-measurement:guides:static-supplies_bb.png?600 |}} +{{ :test-and-measurement:analog-discovery-3:ad3-static-io-supplies-bb.png?600 |}} 
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2Ftest_static-supplies.py&style=github&showCopy=on"></script+from WF_SDK import device, static, supplies       # import instruments 
-</html></WRAP></WRAP>+ 
 +from time import sleep                            # needed for delays 
 + 
 +device_name = "Analog Discovery 3" 
 + 
 +"""-----------------------------------------------------------------------""" 
 + 
 +# connect to the device 
 +device_data = device.open() 
 +device_data.name device_name 
 + 
 +"""-----------------------------------""" 
 + 
 +# start the positive supply 
 +supplies_data = supplies.data() 
 +supplies_data.master_state True 
 +supplies_data.state = True 
 +supplies_data.voltage = 3.3 
 +supplies.switch(device_data, supplies_data) 
 + 
 +# set all pins as output 
 +for index in range(16): 
 +    static.set_mode(device_data, index, True) 
 + 
 +try: 
 +    while True: 
 +        # repeat 
 +        mask = 1 
 +        while mask < 0x10000: 
 +            # go through possible states 
 +            for index in range(16): 
 +                # set the state of every DIO channel 
 +                static.set_state(device_data, index, not(mask pow(2, index))) 
 +            sleep(0.1)  # delay 
 +            mask <<1  # switch mask 
 + 
 +        while mask 1: 
 +            # go through possible states backward 
 +            mask >>= 1  # switch mask 
 +            for index in range(16): 
 +                # set the state of every DIO channel 
 +                static.set_state(device_data, index, not(mask & pow(2, index))) 
 +            sleep(0.1)  # delay 
 + 
 +except KeyboardInterrupt: 
 +    # stop if Ctrl+C is pressed 
 +    pass 
 + 
 +finally: 
 +    # stop the static I/O 
 +    static.close(device_data) 
 + 
 +    # stop and reset the power supplies 
 +    supplies_data.master_state = False 
 +    supplies.switch(device_data, supplies_data) 
 +    supplies.close(device_data) 
 + 
 +    """-----------------------------------""" 
 + 
 +    # close the connection 
 +    device.close(device_data) 
 +</code></WRAP></WRAP>
 <-- <--
  
Line 692: Line 1710:
 Connect the UART interface of both Pmods to your Test & Measurement device as presented below. Pay special attention to the jumpers on the Pmod CLS. Use the positive, or the digital power supply to provide current to the Pmods, then receive and send data with the protocol instrument. Connect the UART interface of both Pmods to your Test & Measurement device as presented below. Pay special attention to the jumpers on the Pmod CLS. Use the positive, or the digital power supply to provide current to the Pmods, then receive and send data with the protocol instrument.
  
-{{ :test-and-measurement:guides:cls-maxsonar-uart_bb.png?600 |}} +{{ :test-and-measurement:analog-discovery-3:ad3-pmodcls-maxsonar.png?600 |}} 
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2Ftest_UART_CLS-MAXSonar.py&style=github&showCopy=on"></script> +from WF_SDK import device, supplies, static     # import instruments 
-</html></WRAP></WRAP>+from WF_SDK.protocol import uart                # import protocol instrument 
 + 
 +from time import sleep          # needed for delays 
 + 
 +device_name = "Analog Discovery 3" 
 + 
 +"""-----------------------------------------------------------------------""" 
 + 
 +# connect to the device 
 +device_data = device.open() 
 +device_data.name device_name 
 + 
 +"""-----------------------------------""" 
 + 
 +# define MAXSonar reset line 
 +reset = 2 
 + 
 +# define timeout iteration count 
 +timeout = 1000 
 + 
 +# start the power supplies 
 +supplies_data = supplies.data() 
 +supplies_data.master_state True 
 +supplies_data.state True 
 +supplies_data.voltage = 3.3 
 +supplies.switch(device_data, supplies_data) 
 +sleep(0.1)    # delay 
 + 
 +# initialize the reset line 
 +static.set_mode(device_data, reset, output=True) 
 +static.set_state(device_data, reset, False) 
 + 
 +# initialize the uart interface on DIO0 and DIO1 
 +uart.open(device_data, tx=0, rx=1, baud_rate=9600) 
 + 
 +try: 
 +    # repeat 
 +    while True: 
 +        # clear the screen and home cursor 
 +        uart.write(device_data, "\x1b[j"
 + 
 +        # display a message 
 +        uart.write(device_data, "Dist: ") 
 + 
 +        # read raw data 
 +        static.set_state(device_data, reset, True)    # enable the device 
 +        message = "" 
 +        for _ in range(timeout): 
 +            # wait for data 
 +            message, error = uart.read(device_data) 
 +            if message != "": 
 +                # exit when data is received 
 +                break 
 +        static.set_state(device_data, reset, False)    # disable the device 
 + 
 +        # convert raw data into distance 
 +        try: 
 +            if message[0] == 234: 
 +                message.pop(0)    # remove first byte 
 +                value = 0 
 +                for element in message: 
 +                    if element 47 and element 58: 
 +                        # concatenate valid bytes 
 +                        value = value * 10 + (element - 48) 
 +                value *= 2.54   # convert to cm 
 +        except: 
 +            # error in message 
 +            value = -1 
 + 
 +        # display the distance 
 +        uart.write(device_data, str(round(value, 2))) 
 + 
 +        # display a message 
 +        uart.write(device_data, "cm"
 + 
 +        # delay 1s 
 +        sleep(1) 
 + 
 +except KeyboardInterrupt: 
 +    # exit on Ctrl+C 
 +    pass 
 + 
 +# reset the interface 
 +uart.close(device_data) 
 + 
 +# reset the static I/
 +static.set_mode(device_data, reset, output=False) 
 +static.set_state(device_data, reset, True) 
 +static.close(device_data) 
 + 
 +# stop and reset the power supplies 
 +supplies_data.master_state = False 
 +supplies.switch(device_data, supplies_data) 
 +supplies.close(device_data) 
 + 
 +"""-----------------------------------""" 
 + 
 +# close the connection 
 +device.close(device_data) 
 +</code></WRAP></WRAP>
 <-- <--
  
Line 702: Line 1819:
 Connect the SPI interface of both Pmods to your Test & Measurement device as presented below. Pay special attention to the jumpers on the Pmod CLS. Use the positive, or the digital power supply to provide current to the Pmods, then receive and send data with the protocol instrument. Connect the SPI interface of both Pmods to your Test & Measurement device as presented below. Pay special attention to the jumpers on the Pmod CLS. Use the positive, or the digital power supply to provide current to the Pmods, then receive and send data with the protocol instrument.
  
-{{ :test-and-measurement:guides:cls-als-spi_bb.png?600 |}} +{{ :test-and-measurement:analog-discovery-3:ad3-pmodcls-pmodals.png?600 |}} 
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2Ftest_SPI_CLS-ALS.py&style=github&showCopy=on"></script+from WF_SDK import device, supplies     # import instruments 
-</html></WRAP></WRAP>+from WF_SDK.protocol import spi         # import protocol instrument 
 + 
 +from time import sleep          # needed for delays 
 + 
 +device_name = "Analog Discovery 3" 
 + 
 +"""-----------------------------------------------------------------------""" 
 + 
 +# connect to the device 
 +device_data = device.open() 
 +device_data.name device_name 
 + 
 +"""-----------------------------------""" 
 + 
 +# define chip select lines 
 +CLS_cs = 0 
 +ALS_cs = 1 
 + 
 +# start the power supplies 
 +supplies_data = supplies.data() 
 +supplies_data.master_state True 
 +supplies_data.state True 
 +supplies_data.voltage = 3.3 
 +supplies.switch(device_data, supplies_data) 
 + 
 +# initialize the spi interface on DIO0, DIO1, DIO2, DIO3 and DIO4 
 +spi.open(device_data, CLS_cs, sck=2, miso=3, mosi=4) 
 +spi.open(device_data, ALS_cs, sck=2, miso=3, mosi=4) 
 + 
 +try: 
 +    # repeat 
 +    while True: 
 +        # clear the screen and home cursor 
 +        spi.write(device_data, "\x1b[j", CLS_cs) 
 + 
 +        # display a message 
 +        spi.write(device_data, "Lum: ", CLS_cs) 
 + 
 +        # read the temperature 
 +        message = spi.read(device_data, 2, ALS_cs) 
 +        value = ((int(message[0]) << 3) | (int(message[1]) >> 4)) / 1.27 
 + 
 +        # display the temperature 
 +        spi.write(device_data, str(round(value, 2)), CLS_cs) 
 + 
 +        # display a message 
 +        spi.write(device_data, "%", CLS_cs) 
 + 
 +        # delay 1s 
 +        sleep(1) 
 + 
 +except KeyboardInterrupt: 
 +    # exit on Ctrl+C 
 +    pass 
 + 
 +# reset the interface 
 +spi.close(device_data) 
 + 
 +# stop and reset the power supplies 
 +supplies_data.master_state = False 
 +supplies.switch(device_data, supplies_data) 
 +supplies.close(device_data) 
 + 
 +"""-----------------------------------""" 
 + 
 +# close the connection 
 +device.close(device_data) 
 +</code></WRAP></WRAP>
 <-- <--
  
Line 712: Line 1896:
 Connect the I2C interface of both Pmods to your Test & Measurement device as presented below. Pay special attention to the jumpers on the Pmod CLS. Use the positive, or the digital power supply to provide current to the Pmods, then receive and send data with the protocol instrument. Connect the I2C interface of both Pmods to your Test & Measurement device as presented below. Pay special attention to the jumpers on the Pmod CLS. Use the positive, or the digital power supply to provide current to the Pmods, then receive and send data with the protocol instrument.
  
-{{ :test-and-measurement:guides:cls-tmp2-i2c_bb.png?600 |}} +{{ :test-and-measurement:analog-discovery-3:ad3-pmodcls-pmodtmp2.png?600 |}} 
-</WRAP><WRAP half column><html+</WRAP><WRAP half column><code python
-<script src="https://emgithub.com/embed.js?target=https%3A%2F%2Fgithub.com%2FDigilent%2FWaveForms-SDK-Getting-Started%2Fblob%2Fmaster%2Ftest_I2C_CLS-TMP2.py&style=github&showCopy=on"></script+from WF_SDK import device, supplies     # import instruments 
-</html></WRAP></WRAP>+from WF_SDK.protocol import i2c         # import protocol instrument 
 + 
 +from time import sleep          # needed for delays 
 + 
 +device_name = "Analog Discovery 3" 
 + 
 +"""-----------------------------------------------------------------------""" 
 + 
 +# connect to the device 
 +device_data = device.open() 
 +device_data.name device_name 
 + 
 +"""-----------------------------------""" 
 + 
 +# define i2c addresses 
 +CLS_address = 0x48 
 +TMP2_address = 0x4B 
 + 
 +# start the power supplies 
 +supplies_data = supplies.data() 
 +supplies_data.master_state True 
 +supplies_data.state True 
 +supplies_data.voltage = 3.3 
 +supplies.switch(device_data, supplies_data) 
 +sleep(0.1)    # delay 
 + 
 +# initialize the i2c interface on DIO0 and DIO1 
 +i2c.open(device_data, sda=0, scl=1) 
 + 
 +# initialize the PMOD TMP2 (set output size to 16-bit) 
 +i2c.write(device_data, [0x03, 0x80], TMP2_address) 
 + 
 +# save custom character 
 +i2c.write(device_data, "\x1b[7;5;7;0;0;0;0;0;0d", CLS_address)   # define character 
 +i2c.write(device_data, "\x1b[3p", CLS_address) # load character table 
 + 
 +try: 
 +    # repeat 
 +    while True: 
 +        # clear the screen and home cursor 
 +        i2c.write(device_data, [0x1B, 0x5B, 0x6A], CLS_address) 
 + 
 +        # display a message 
 +        i2c.write(device_data, "Temp: ", CLS_address) 
 + 
 +        # read the temperature 
 +        message, error = i2c.read(device_data, 2, TMP2_address)   # read 2 bytes 
 +        value = (int(message[0]) << 8) | int(message[1])    # create integer from received bytes 
 +        if ((value >> 15) & 1) == 0: 
 +            value /= 128    # decode positive numbers 
 +        else: 
 +            value = (value - 65535) / 128   # decode negative numbers 
 + 
 +        # display the temperature 
 +        i2c.write(device_data, str(round(value, 2)), CLS_address) 
 + 
 +        # display a message 
 +        i2c.write(device_data, 0, CLS_address) 
 +        i2c.write(device_data, "C", CLS_address) 
 + 
 +        # delay 1s 
 +        sleep(1) 
 + 
 +except KeyboardInterrupt: 
 +    # exit on Ctrl+C 
 +    pass 
 + 
 +# reset the interface 
 +i2c.close(device_data) 
 + 
 +# stop and reset the power supplies 
 +supplies_data.master_state = False 
 +supplies.switch(device_data, supplies_data) 
 +supplies.close(device_data) 
 + 
 +"""-----------------------------------""" 
 + 
 +# close the connection 
 +device.close(device_data) 
 +</code></WRAP></WRAP>
 <-- <--
 ---- ----
  
 +==== Installing the Package ====
 +<WRAP group>
 +Once you completed the package, you might want to install it, like other Python packages and use it on new projects as well. To do so, you must create some additional files in the project folder.
 +
 +First, exclude the test scripts from the final package. Create a file named **MANIFEST.in**, with the content:
 +<code>global-exclude test_*</code>
 +
 +The installer needs the list of dependencies to install your package. Specify this list on a file called **requirements.txt**:
 +<code>
 +setuptools==58.1.0
 +wheel==0.37.1</code>
 +
 +Finally, create a **README.md** file with the description of your package, then create the installer. The installer is the file named **setup.py**, with the following content:
 +<code python>
 +from setuptools import setup
 +
 +with open("README.md", "r") as f:
 +    long_description = f.read()
 +
 +setup(
 +   name = "WF_SDK",
 +   version = "1.0",
 +   description = "This module realizes communication with Digilent Test & Measurement devices",
 +   license = "MIT",
 +   long_description = long_description,
 +   author = "author_name",
 +   author_email = "author_email_address",
 +   url = "https://digilent.com/reference/test-and-measurement/guides/waveforms-sdk-getting-started",
 +   packages = ["WF_SDK", "WF_SDK.protocol"],
 +)
 +</code>
 +</WRAP>
 +
 +<WRAP group>
 +Once the necessary files are created, open a terminal, go to the project folder and install your package with the following command:
 +<code>pip3 install .</code>
 +
 +Alternatively, you can install the package from the GitHub repository, with the command:
 +<code>pip3 install git+https://github.com/Digilent/WaveForms-SDK-Getting-Started-PY#egg=WF_SDK</code>
 +
 +If you already installed the package, you can update it with the command:
 +<code>pip3 install --force-reinstall git+https://github.com/Digilent/WaveForms-SDK-Getting-Started-PY#egg=WF_SDK</code>
 +
 +**Note:** //Use "pip" instead of "pip3", if you are using Python 2.//
 +</WRAP>
 +----
 +
 +===== Other Programming Languages =====
 +<WRAP group>
 +Realizing the same package in other programming languages is also possible. To check the C++ version of the package and some test programs, follow this [[https://github.com/Digilent/WaveForms-SDK-Getting-Started-Cpp|GitHub repository, C++]] link.
 +</WRAP>
 +----
 ===== Next Steps ===== ===== Next Steps =====
 <WRAP group> <WRAP group>
Line 727: Line 2042:
 For more information on WaveForms visit the [[software:waveforms:waveforms-3:reference-manual|]].  For more information on WaveForms visit the [[software:waveforms:waveforms-3:reference-manual|]]. 
  
-For technical support, please visit the [[https://forum.digilentinc.com/forum/8-test-and-measurement/|Test and Measurement]] section of the Digilent Forums.+For technical support, please visit the [[https://forum.digilent.com/forum/8-test-and-measurement/|Test and Measurement]] section of the Digilent Forums.
 </WRAP> </WRAP>