diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/ALIGN_PHASES_AFG31000.py b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/ALIGN_PHASES_AFG31000.py
new file mode 100644
index 00000000..d675037d
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/ALIGN_PHASES_AFG31000.py
@@ -0,0 +1,32 @@
+from flojoy import flojoy, DataContainer, String, VisaConnection
+from typing import Optional, Literal
+
+
+@flojoy(inject_connection=True)
+def ALIGN_PHASES_AFG31000(
+ connection: VisaConnection,
+ channel: Literal["1", "2"] = "1",
+ input: Optional[DataContainer] = None,
+) -> String:
+ """Run this block to align the phases for ch1 and ch2.
+
+ This block should also work with compatible Tektronix AFG31XXX instruments.
+
+ Parameters
+ ----------
+ connection: VisaConnection
+ The VISA address (requires the CONNECTION_AFG31000 block).
+ channel: select, default=ch1
+ Which channel is the reference?
+
+ Returns
+ -------
+ String
+ Aligned channel phases
+ """
+
+ afg = connection.get_handle()
+
+ afg.write(f"SOURCE{channel}:PHASE:INIT")
+
+ return String(s="Aligned channel phases")
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/app.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/app.json
new file mode 100644
index 00000000..cfe2cd71
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/app.json
@@ -0,0 +1,633 @@
+{
+ "rfInstance": {
+ "nodes": [
+ {
+ "width": 192,
+ "height": 192,
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "type": "HARDWARE",
+ "data": {
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "label": "CONNECT AFG31000",
+ "func": "CONNECT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "device": {
+ "type": "VisaDevice",
+ "default": null,
+ "desc": "The VISA address to connect to.",
+ "overload": null,
+ "functionName": "CONNECT_AFG31000",
+ "param": "device",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "The IP or VISA address of the VISA device."
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py"
+ },
+ "position": {
+ "x": -356.99744674030666,
+ "y": -192.33911380820962
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -356.99744674030666,
+ "y": -192.33911380820962
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "type": "HARDWARE",
+ "data": {
+ "id": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "label": "ALIGN PHASES AFG31000",
+ "func": "ALIGN_PHASES_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "ALIGN_PHASES_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "channel": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": "Which channel is the reference?",
+ "overload": null,
+ "functionName": "ALIGN_PHASES_AFG31000",
+ "param": "channel",
+ "value": "1"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/ALIGN_PHASES_AFG31000.py"
+ },
+ "position": {
+ "x": 439.9476681838445,
+ "y": -194.69759194078154
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 439.9476681838445,
+ "y": -194.69759194078154
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "type": "HARDWARE",
+ "data": {
+ "id": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "label": "OUTPUT AFG31000",
+ "func": "OUTPUT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "ch1": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 1 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1",
+ "value": "on"
+ },
+ "ch2": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 2 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2",
+ "value": "on"
+ },
+ "ch1_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 1 impedance.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1_impedance",
+ "value": "50"
+ },
+ "ch2_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 2 impedance",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2_impedance",
+ "value": "50"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py"
+ },
+ "position": {
+ "x": 193.0241524368904,
+ "y": -193.99838203480326
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 193.0241524368904,
+ "y": -193.99838203480326
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "type": "HARDWARE",
+ "data": {
+ "id": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "label": "SAVE STATE AFG31000",
+ "func": "SAVE_STATE_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "save_recall": {
+ "type": "select",
+ "options": [
+ "save",
+ "recall"
+ ],
+ "default": "save",
+ "desc": "Save or recall the save state.",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "save_recall",
+ "value": "save"
+ },
+ "option": {
+ "type": "select",
+ "options": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5"
+ ],
+ "default": "1",
+ "desc": "Choose from the 5 save states.",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "option",
+ "value": "2"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Save state"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/SAVE_STATE_AFG31000.py"
+ },
+ "position": {
+ "x": 680.0566763496477,
+ "y": -192.15162100388233
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 680.0566763496477,
+ "y": -192.15162100388233
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "type": "HARDWARE",
+ "data": {
+ "id": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "label": "FUNCTION AFG31000",
+ "func": "FUNCTION_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "source",
+ "value": "1"
+ },
+ "functions": {
+ "type": "select",
+ "options": [
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine"
+ ],
+ "default": "sinusoid",
+ "desc": "Choose the function to output",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "functions",
+ "value": "sinusoid"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "frequency",
+ "value": 2000000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "amplitude",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "offset",
+ "value": 0
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "phase",
+ "value": 0
+ },
+ "pulse_width": {
+ "type": "float",
+ "default": 0.000001,
+ "desc": "The pulse width in nanoseconds if the PULS waveform is used.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "pulse_width",
+ "value": 0.000001
+ },
+ "ramp_symmetry": {
+ "type": "float",
+ "default": 50,
+ "desc": "The ramp symmetry if the RAMP waveform is used, in percent.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "ramp_symmetry",
+ "value": 50
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py"
+ },
+ "position": {
+ "x": -67.77699444442803,
+ "y": -334.69885402865026
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -67.77699444442803,
+ "y": -334.69885402865026
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "type": "HARDWARE",
+ "data": {
+ "id": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "label": "FUNCTION AFG31000 1",
+ "func": "FUNCTION_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "source",
+ "value": "2"
+ },
+ "functions": {
+ "type": "select",
+ "options": [
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine"
+ ],
+ "default": "sinusoid",
+ "desc": "Choose the function to output",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "functions",
+ "value": "gaussian"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "frequency",
+ "value": 5000000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "amplitude",
+ "value": 2
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "offset",
+ "value": -0.5
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "phase",
+ "value": 45
+ },
+ "pulse_width": {
+ "type": "float",
+ "default": 0.000001,
+ "desc": "The pulse width in nanoseconds if the PULS waveform is used.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "pulse_width",
+ "value": 0.000001
+ },
+ "ramp_symmetry": {
+ "type": "float",
+ "default": 50,
+ "desc": "The ramp symmetry if the RAMP waveform is used, in percent.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "ramp_symmetry",
+ "value": 50
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py"
+ },
+ "position": {
+ "x": -62.333665463218566,
+ "y": -90.14297151518164
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -62.333665463218566,
+ "y": -90.14297151518164
+ },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "sourceHandle": "default",
+ "target": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "targetHandle": "input",
+ "id": "reactflow__edge-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1default-ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749input"
+ },
+ {
+ "source": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "targetHandle": "input",
+ "id": "reactflow__edge-FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527default-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1input"
+ },
+ {
+ "source": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "targetHandle": "input",
+ "id": "reactflow__edge-FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2adefault-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1input"
+ },
+ {
+ "source": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "sourceHandle": "default",
+ "target": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "targetHandle": "input",
+ "id": "reactflow__edge-ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749default-SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dcinput"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527input"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2ainput"
+ }
+ ],
+ "viewport": {
+ "x": 998.0979704909867,
+ "y": 583.9050842369531,
+ "zoom": 0.9793470432493011
+ }
+ },
+ "textNodes": []
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/block_data.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/block_data.json
new file mode 100644
index 00000000..88bdbe69
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/block_data.json
@@ -0,0 +1,25 @@
+{
+ "docstring": {
+ "long_description": "This block should also work with compatible Tektronix AFG31XXX instruments.",
+ "short_description": "Run this block to align the phases for ch1 and ch2.",
+ "parameters": [
+ {
+ "name": "connection",
+ "type": "VisaConnection",
+ "description": "The VISA address (requires the CONNECTION_AFG31000 block)."
+ },
+ {
+ "name": "channel",
+ "type": "select, default=ch1",
+ "description": "Which channel is the reference?"
+ }
+ ],
+ "returns": [
+ {
+ "name": null,
+ "type": "String",
+ "description": "Aligned channel phases"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/example.md b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/example.md
new file mode 100644
index 00000000..4c1183ad
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/example.md
@@ -0,0 +1,18 @@
+In this example, an Tektronix AFG31000 is used to generate two waveforms.
+
+First the necessary blocks were added:
+
+- `CONNECT_AFG31000`
+- `RESET_AFG31000`
+- 2x `FUNCTION_AFG31000`
+- `ALIGN_PHASES_AFG31000`
+- `OUTPUT_AFG31000`
+- `SAVE_STATE_AFG31000`
+
+The instrument address was set for each `AFG31000` block. Ensure the `OUTPUT_AFG31000` block has both channels turn on.
+
+The blocks were connected as shown and the app was run. The `SAVE_STATE_AFG31000` block can be used to save and recall the current state of the AFG. However, you must use a `OUTPUT_AFG31000` block to turn the outputs back on.
+
+An oscilloscope was connected to the AFG31000 resulting in waveform:
+
+![image](https://res.cloudinary.com/dhopxs1y3/image/upload/v1701277906/flojoy-docs/afg31000/afg31000_basic.png)
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/ARBITRARY_AFG31000.py b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/ARBITRARY_AFG31000.py
new file mode 100644
index 00000000..230d47cd
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/ARBITRARY_AFG31000.py
@@ -0,0 +1,68 @@
+from flojoy import flojoy, OrderedPair, String, VisaConnection, Vector
+from typing import Literal
+from numpy import max, min
+
+
+@flojoy(inject_connection=True)
+def ARBITRARY_AFG31000(
+ input: OrderedPair | Vector,
+ connection: VisaConnection,
+ memory_state: Literal["EMEM1", "EMEM2"] = "EMEM1",
+ source: Literal["1", "2"] = "1",
+ frequency: float = 1e6,
+ amplitude: float = 1,
+ offset: float = 0,
+ phase: float = 0,
+) -> String:
+ """Take the input waveform and use it as the arbitrary wavefunction.
+
+ This block should also work with compatible Tektronix AFG31XXX instruments.
+
+ Parameters
+ ----------
+ connection: VisaConnection
+ The VISA address (requires the CONNECTION_AFG31000 block).
+ memory_state: select, default=EMEM1
+ Save the function in "Edit Memory" 1 or 2.
+ channel: select, default=1
+ Choose the channel to use with the waveform.
+ frequency: float, default=1e6
+ The voltage of the waveform to set, in Hz.
+ amplitude: float, default=1
+ The voltage of the waveform to set.
+ offset: float, default=0
+ The voltage offset to set the waveform to, in volts.
+ phase: float, default=0
+ The phase to set the waveform to, in degrees.
+
+ Returns
+ -------
+ String
+ Set FG parameters
+ """
+
+ assert -180.0 <= phase <= 180.0, "The phase must be between -180 and 180 degrees."
+
+ afg = connection.get_handle()
+
+ match input:
+ case OrderedPair():
+ y = input.y
+ case Vector():
+ y = input.v
+
+ y -= min(y)
+ y /= max(y)
+ y *= 16383
+
+ afg.write_binary_values(
+ f"DATA:DATA {memory_state}, ", y, is_big_endian=True, datatype="h"
+ )
+ afg.write(f"SOURCE{source}:FUNCTION {memory_state}")
+
+ afg.write(f"SOURCE{source}:FREQUENCY {frequency}")
+ afg.write(f"SOURCE{source}:VOLTAGE:AMPLITUDE {amplitude}")
+ afg.write(f"SOURCE{source}:VOLTAGE:OFFSET {offset}")
+ afg.write(f"SOURCE{source}:PHASE:ADJUST {phase}DEG")
+
+ return String(s="Set FG parameters")
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/app.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/app.json
new file mode 100644
index 00000000..7e448660
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/app.json
@@ -0,0 +1,796 @@
+{
+ "rfInstance": {
+ "nodes": [
+ {
+ "width": 192,
+ "height": 192,
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "type": "HARDWARE",
+ "data": {
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "label": "CONNECT AFG31000",
+ "func": "CONNECT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "device": {
+ "type": "VisaDevice",
+ "default": null,
+ "desc": "The VISA address to connect to.",
+ "overload": null,
+ "functionName": "CONNECT_AFG31000",
+ "param": "device",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "The IP or VISA address of the VISA device."
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py"
+ },
+ "position": {
+ "x": -174.2226058564158,
+ "y": -353.6710962643813
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -174.2226058564158,
+ "y": -353.6710962643813
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2ac",
+ "type": "HARDWARE",
+ "data": {
+ "id": "ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2ac",
+ "label": "ARBITRARY AFG31000",
+ "func": "ARBITRARY_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "memory_state": {
+ "type": "select",
+ "options": [
+ "EMEM1",
+ "EMEM2"
+ ],
+ "default": "EMEM1",
+ "desc": "Save the function in \"Edit Memory\" 1 or 2.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "memory_state",
+ "value": "EMEM1"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "source",
+ "value": "1"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "frequency",
+ "value": 100000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "amplitude",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "offset",
+ "value": 0
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "phase",
+ "value": 0
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "OrderedPair|Vector",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/ARBITRARY_AFG31000.py"
+ },
+ "position": {
+ "x": 145.66871932962246,
+ "y": -43.37213414482457
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 145.66871932962246,
+ "y": -43.37213414482457
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781",
+ "type": "HARDWARE",
+ "data": {
+ "id": "COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781",
+ "label": "PLACEHOLDER",
+ "func": "COPY_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "COPY_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "channel": {
+ "type": "select",
+ "options": [
+ "ch1",
+ "ch2"
+ ],
+ "default": "ch1",
+ "desc": "Which channel to copy to the other channel.",
+ "overload": null,
+ "functionName": "COPY_AFG31000",
+ "param": "channel",
+ "value": "ch1"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/COPY_AFG31000.py"
+ },
+ "position": {
+ "x": 144.4620281465655,
+ "y": -351.58208891808863
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 144.4620281465655,
+ "y": -351.58208891808863
+ },
+ "dragging": true
+ },
+ {
+ "width": 210,
+ "height": 96,
+ "id": "BASIC_OSCILLATOR-5ea02552-dcaf-43d9-b296-075501fa958a",
+ "type": "DATA",
+ "data": {
+ "id": "BASIC_OSCILLATOR-5ea02552-dcaf-43d9-b296-075501fa958a",
+ "label": "BASIC OSCILLATOR",
+ "func": "BASIC_OSCILLATOR",
+ "type": "DATA",
+ "ctrls": {
+ "sample_rate": {
+ "type": "int",
+ "default": 100,
+ "desc": "The number of samples that are taken in a second.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "sample_rate",
+ "value": 1000
+ },
+ "time": {
+ "type": "int",
+ "default": 10,
+ "desc": "The total amount of time of the signal.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "time",
+ "value": 2
+ },
+ "waveform": {
+ "type": "select",
+ "options": [
+ "sine",
+ "square",
+ "triangle",
+ "sawtooth"
+ ],
+ "default": "sine",
+ "desc": "The waveform type of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "waveform",
+ "value": "sine"
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The amplitude of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "amplitude",
+ "value": 1
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1,
+ "desc": "The wave frequency in radians/2pi.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "frequency",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The y axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "offset",
+ "value": 0
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The x axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "phase",
+ "value": 0
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair",
+ "desc": "x: time domain\ny: generated signal"
+ }
+ ],
+ "path": "DATA/GENERATION/SIMULATIONS/BASIC_OSCILLATOR/BASIC_OSCILLATOR.py"
+ },
+ "position": {
+ "x": -362.1075027285308,
+ "y": 31.080632360951938
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -362.1075027285308,
+ "y": 31.080632360951938
+ },
+ "dragging": true
+ },
+ {
+ "width": 210,
+ "height": 96,
+ "id": "BASIC_OSCILLATOR-7ce8d7e2-ec85-4e06-a3c3-c04359d10b94",
+ "type": "DATA",
+ "data": {
+ "id": "BASIC_OSCILLATOR-7ce8d7e2-ec85-4e06-a3c3-c04359d10b94",
+ "label": "BASIC OSCILLATOR 1",
+ "func": "BASIC_OSCILLATOR",
+ "type": "DATA",
+ "ctrls": {
+ "sample_rate": {
+ "type": "int",
+ "default": 100,
+ "desc": "The number of samples that are taken in a second.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "sample_rate",
+ "value": 2000
+ },
+ "time": {
+ "type": "int",
+ "default": 10,
+ "desc": "The total amount of time of the signal.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "time",
+ "value": 1
+ },
+ "waveform": {
+ "type": "select",
+ "options": [
+ "sine",
+ "square",
+ "triangle",
+ "sawtooth"
+ ],
+ "default": "sine",
+ "desc": "The waveform type of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "waveform",
+ "value": "sine"
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The amplitude of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "amplitude",
+ "value": 2
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1,
+ "desc": "The wave frequency in radians/2pi.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "frequency",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The y axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "offset",
+ "value": 5
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The x axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "phase",
+ "value": 1
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair",
+ "desc": "x: time domain\ny: generated signal"
+ }
+ ],
+ "path": "DATA/GENERATION/SIMULATIONS/BASIC_OSCILLATOR/BASIC_OSCILLATOR.py"
+ },
+ "position": {
+ "x": -356.8896911005901,
+ "y": 166.0972138398535
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -356.8896911005901,
+ "y": 166.0972138398535
+ },
+ "dragging": true
+ },
+ {
+ "width": 72,
+ "height": 72,
+ "id": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "type": "ARITHMETIC",
+ "data": {
+ "id": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "label": "MULTIPLY",
+ "func": "MULTIPLY",
+ "type": "ARITHMETIC",
+ "ctrls": {},
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "a",
+ "id": "a",
+ "type": "OrderedPair|Scalar|Vector",
+ "multiple": false,
+ "desc": "The input a use to compute the product of a and b."
+ },
+ {
+ "name": "b",
+ "id": "b",
+ "type": "OrderedPair|Scalar|Vector",
+ "multiple": true,
+ "desc": "The input b use to compute the product of a and b."
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair|Scalar|Vector",
+ "desc": "OrderedPair if a is an OrderedPair.\nx: the x-axis of input a.\ny: the result of the product of input a and input b.\n\nScalar if a is a Scalar.\nc: the result of the product of input a and input b.\n\nVector if a is a Vector.\nv: the result of the product of input a and input b."
+ }
+ ],
+ "path": "MATH/ARITHMETIC/MULTIPLY/MULTIPLY.py"
+ },
+ "position": {
+ "x": -29.35682713839612,
+ "y": 129.60080736694715
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -29.35682713839612,
+ "y": 129.60080736694715
+ },
+ "dragging": true
+ },
+ {
+ "width": 380,
+ "height": 293,
+ "id": "LINE-f160352e-ab73-47c2-a1b9-658bd41a8865",
+ "type": "VISUALIZATION",
+ "data": {
+ "id": "LINE-f160352e-ab73-47c2-a1b9-658bd41a8865",
+ "label": "LINE",
+ "func": "LINE",
+ "type": "VISUALIZATION",
+ "ctrls": {},
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair|DataFrame|Matrix|Vector",
+ "multiple": false,
+ "desc": "the DataContainer to be visualized"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "Plotly",
+ "desc": "the DataContainer containing the Plotly Line visualization of the input data"
+ }
+ ],
+ "path": "DATA/VISUALIZATION/PLOTLY/LINE/LINE.py"
+ },
+ "position": {
+ "x": 257.6493418294323,
+ "y": 219.14870774764609
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 257.6493418294323,
+ "y": 219.14870774764609
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3",
+ "type": "HARDWARE",
+ "data": {
+ "id": "OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3",
+ "label": "OUTPUT AFG31000",
+ "func": "OUTPUT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "ch1": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 1 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1",
+ "value": "on"
+ },
+ "ch2": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 2 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2",
+ "value": "on"
+ },
+ "ch1_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 1 impedance.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1_impedance",
+ "value": "50"
+ },
+ "ch2_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 2 impedance",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2_impedance",
+ "value": "50"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py"
+ },
+ "position": {
+ "x": 521.5212679159422,
+ "y": -167.45967092017608
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 521.5212679159422,
+ "y": -167.45967092017608
+ },
+ "dragging": true
+ },
+ {
+ "width": 210,
+ "height": 96,
+ "id": "BASIC_OSCILLATOR-fc420f32-3b96-4cf9-ad6f-a16bbab741d8",
+ "type": "DATA",
+ "data": {
+ "id": "BASIC_OSCILLATOR-fc420f32-3b96-4cf9-ad6f-a16bbab741d8",
+ "label": "BASIC OSCILLATOR 2",
+ "func": "BASIC_OSCILLATOR",
+ "type": "DATA",
+ "ctrls": {
+ "sample_rate": {
+ "type": "int",
+ "default": 100,
+ "desc": "The number of samples that are taken in a second.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "sample_rate",
+ "value": 500
+ },
+ "time": {
+ "type": "int",
+ "default": 10,
+ "desc": "The total amount of time of the signal.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "time",
+ "value": 4
+ },
+ "waveform": {
+ "type": "select",
+ "options": [
+ "sine",
+ "square",
+ "triangle",
+ "sawtooth"
+ ],
+ "default": "sine",
+ "desc": "The waveform type of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "waveform",
+ "value": "sine"
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The amplitude of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "amplitude",
+ "value": 2
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1,
+ "desc": "The wave frequency in radians/2pi.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "frequency",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The y axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "offset",
+ "value": 5
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The x axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "phase",
+ "value": 1
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair",
+ "desc": "x: time domain\ny: generated signal"
+ }
+ ],
+ "path": "DATA/GENERATION/SIMULATIONS/BASIC_OSCILLATOR/BASIC_OSCILLATOR.py"
+ },
+ "position": {
+ "x": -350.3747265214252,
+ "y": 299.2271519922165
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -350.3747265214252,
+ "y": 299.2271519922165
+ },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "sourceHandle": "default",
+ "target": "ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2ac",
+ "targetHandle": "input",
+ "id": "reactflow__edge-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1cadefault-ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2acinput"
+ },
+ {
+ "source": "BASIC_OSCILLATOR-5ea02552-dcaf-43d9-b296-075501fa958a",
+ "sourceHandle": "default",
+ "target": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "targetHandle": "a",
+ "id": "reactflow__edge-BASIC_OSCILLATOR-5ea02552-dcaf-43d9-b296-075501fa958adefault-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1caa"
+ },
+ {
+ "source": "BASIC_OSCILLATOR-7ce8d7e2-ec85-4e06-a3c3-c04359d10b94",
+ "sourceHandle": "default",
+ "target": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "targetHandle": "b",
+ "id": "reactflow__edge-BASIC_OSCILLATOR-7ce8d7e2-ec85-4e06-a3c3-c04359d10b94default-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1cab"
+ },
+ {
+ "source": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "sourceHandle": "default",
+ "target": "LINE-f160352e-ab73-47c2-a1b9-658bd41a8865",
+ "targetHandle": "default",
+ "id": "reactflow__edge-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1cadefault-LINE-f160352e-ab73-47c2-a1b9-658bd41a8865default"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781input"
+ },
+ {
+ "source": "COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3",
+ "targetHandle": "input",
+ "id": "reactflow__edge-COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781default-OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3input"
+ },
+ {
+ "source": "ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2ac",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3",
+ "targetHandle": "input",
+ "id": "reactflow__edge-ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2acdefault-OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3input"
+ },
+ {
+ "source": "BASIC_OSCILLATOR-fc420f32-3b96-4cf9-ad6f-a16bbab741d8",
+ "sourceHandle": "default",
+ "target": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "targetHandle": "b",
+ "id": "reactflow__edge-BASIC_OSCILLATOR-fc420f32-3b96-4cf9-ad6f-a16bbab741d8default-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1cab"
+ }
+ ],
+ "viewport": {
+ "x": 998.0979704909867,
+ "y": 583.9050842369531,
+ "zoom": 0.9793470432493011
+ }
+ },
+ "textNodes": []
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/block_data.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/block_data.json
new file mode 100644
index 00000000..03b52bbb
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/block_data.json
@@ -0,0 +1,50 @@
+{
+ "docstring": {
+ "long_description": "This block should also work with compatible Tektronix AFG31XXX instruments.",
+ "short_description": "Take the input waveform and use it as the arbitrary wavefunction.",
+ "parameters": [
+ {
+ "name": "connection",
+ "type": "VisaConnection",
+ "description": "The VISA address (requires the CONNECTION_AFG31000 block)."
+ },
+ {
+ "name": "memory_state",
+ "type": "select, default=EMEM1",
+ "description": "Save the function in \"Edit Memory\" 1 or 2."
+ },
+ {
+ "name": "channel",
+ "type": "select, default=1",
+ "description": "Choose the channel to use with the waveform."
+ },
+ {
+ "name": "frequency",
+ "type": "float, default=1e6",
+ "description": "The voltage of the waveform to set, in Hz."
+ },
+ {
+ "name": "amplitude",
+ "type": "float, default=1",
+ "description": "The voltage of the waveform to set."
+ },
+ {
+ "name": "offset",
+ "type": "float, default=0",
+ "description": "The voltage offset to set the waveform to, in volts."
+ },
+ {
+ "name": "phase",
+ "type": "float, default=0",
+ "description": "The phase to set the waveform to, in degrees."
+ }
+ ],
+ "returns": [
+ {
+ "name": null,
+ "type": "String",
+ "description": "Set FG parameters"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/example.md b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/example.md
new file mode 100644
index 00000000..ec67e308
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/example.md
@@ -0,0 +1,20 @@
+In this example, an Tektronix AFG31000 is used to generate an arbitrary waveform.
+
+First the necessary blocks were added:
+
+- `CONNECT_AFG31000`
+- `COPY_AFG31000`
+- `ARBITRARY_AFG31000`
+- `BASIC_PARAMETERS_AFG31000`
+- `OUTPUT_AFG31000`
+- 3x `BASIC_OSCILLATOR`
+- `MULTIPLY`
+- `LINE`
+
+The instrument address was set for each `AFG31000` block. Ensure the `OUTPUT_AFG31000` block has channel 1 output turned on. Note the `COPY_AFG31000` block is rename `PLACEHOLDER` here and it preset for block running order reasons. The `BASIC_PARAMETERS_AFG31000` block is used to change frequency, offset, voltage, and phase for a single channel, without changing the function itself.
+
+The blocks were connected as shown and the app was run. The 3 `BASIC_OSCILLATOR` blocks were used to generate the arbitrary waveform. Any waveform generated in Flojoy can be used as the input for `ARBITRARY_AFG31000` to allow for any output.
+
+An oscilloscope was connected to the AFG31000 resulting in waveform:
+
+![image](https://res.cloudinary.com/dhopxs1y3/image/upload/v1701277907/flojoy-docs/afg31000/afg31000_arb.png)
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/BASIC_PARAMETERS_AFG31000.py b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/BASIC_PARAMETERS_AFG31000.py
new file mode 100644
index 00000000..4b61c31c
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/BASIC_PARAMETERS_AFG31000.py
@@ -0,0 +1,49 @@
+from flojoy import flojoy, DataContainer, String, VisaConnection
+from typing import Optional, Literal
+
+
+@flojoy(inject_connection=True)
+def BASIC_PARAMETERS_AFG31000(
+ connection: VisaConnection,
+ source: Literal["1", "2"] = "1",
+ frequency: float = 1e6,
+ amplitude: float = 1,
+ offset: float = 0,
+ phase: float = 0,
+ input: Optional[DataContainer] = None,
+) -> String:
+ """Set basic parameters such as frequency for a single channel.
+
+ This block should also work with compatible Tektronix AFG31XXX instruments.
+
+ Parameters
+ ----------
+ connection: VisaConnection
+ The VISA address (requires the CONNECTION_AFG31000 block).
+ channel: select, default=1
+ Choose the channel to alter.
+ frequency: float, default=1e6
+ The voltage of the waveform to set, in Hz.
+ amplitude: float, default=1
+ The voltage of the waveform to set.
+ offset: float, default=0
+ The voltage offset to set the waveform to, in volts.
+ phase: float, default=0
+ The phase to set the waveform to, in degrees.
+
+ Returns
+ -------
+ String
+ Placeholder
+ """
+
+ assert -180.0 <= phase <= 180.0, "The phase must be between -180 and 180 degrees."
+
+ afg = connection.get_handle()
+
+ afg.write(f"SOURCE{source}:FREQUENCY {frequency}")
+ afg.write(f"SOURCE{source}:VOLTAGE:AMPLITUDE {amplitude}")
+ afg.write(f"SOURCE{source}:VOLTAGE:OFFSET {offset}")
+ afg.write(f"SOURCE{source}:PHASE:ADJUST {phase}DEG")
+
+ return String(s="Set FG parameters")
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/app.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/app.json
new file mode 100644
index 00000000..7e448660
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/app.json
@@ -0,0 +1,796 @@
+{
+ "rfInstance": {
+ "nodes": [
+ {
+ "width": 192,
+ "height": 192,
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "type": "HARDWARE",
+ "data": {
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "label": "CONNECT AFG31000",
+ "func": "CONNECT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "device": {
+ "type": "VisaDevice",
+ "default": null,
+ "desc": "The VISA address to connect to.",
+ "overload": null,
+ "functionName": "CONNECT_AFG31000",
+ "param": "device",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "The IP or VISA address of the VISA device."
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py"
+ },
+ "position": {
+ "x": -174.2226058564158,
+ "y": -353.6710962643813
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -174.2226058564158,
+ "y": -353.6710962643813
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2ac",
+ "type": "HARDWARE",
+ "data": {
+ "id": "ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2ac",
+ "label": "ARBITRARY AFG31000",
+ "func": "ARBITRARY_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "memory_state": {
+ "type": "select",
+ "options": [
+ "EMEM1",
+ "EMEM2"
+ ],
+ "default": "EMEM1",
+ "desc": "Save the function in \"Edit Memory\" 1 or 2.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "memory_state",
+ "value": "EMEM1"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "source",
+ "value": "1"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "frequency",
+ "value": 100000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "amplitude",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "offset",
+ "value": 0
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "phase",
+ "value": 0
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "OrderedPair|Vector",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/ARBITRARY_AFG31000.py"
+ },
+ "position": {
+ "x": 145.66871932962246,
+ "y": -43.37213414482457
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 145.66871932962246,
+ "y": -43.37213414482457
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781",
+ "type": "HARDWARE",
+ "data": {
+ "id": "COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781",
+ "label": "PLACEHOLDER",
+ "func": "COPY_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "COPY_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "channel": {
+ "type": "select",
+ "options": [
+ "ch1",
+ "ch2"
+ ],
+ "default": "ch1",
+ "desc": "Which channel to copy to the other channel.",
+ "overload": null,
+ "functionName": "COPY_AFG31000",
+ "param": "channel",
+ "value": "ch1"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/COPY_AFG31000.py"
+ },
+ "position": {
+ "x": 144.4620281465655,
+ "y": -351.58208891808863
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 144.4620281465655,
+ "y": -351.58208891808863
+ },
+ "dragging": true
+ },
+ {
+ "width": 210,
+ "height": 96,
+ "id": "BASIC_OSCILLATOR-5ea02552-dcaf-43d9-b296-075501fa958a",
+ "type": "DATA",
+ "data": {
+ "id": "BASIC_OSCILLATOR-5ea02552-dcaf-43d9-b296-075501fa958a",
+ "label": "BASIC OSCILLATOR",
+ "func": "BASIC_OSCILLATOR",
+ "type": "DATA",
+ "ctrls": {
+ "sample_rate": {
+ "type": "int",
+ "default": 100,
+ "desc": "The number of samples that are taken in a second.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "sample_rate",
+ "value": 1000
+ },
+ "time": {
+ "type": "int",
+ "default": 10,
+ "desc": "The total amount of time of the signal.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "time",
+ "value": 2
+ },
+ "waveform": {
+ "type": "select",
+ "options": [
+ "sine",
+ "square",
+ "triangle",
+ "sawtooth"
+ ],
+ "default": "sine",
+ "desc": "The waveform type of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "waveform",
+ "value": "sine"
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The amplitude of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "amplitude",
+ "value": 1
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1,
+ "desc": "The wave frequency in radians/2pi.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "frequency",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The y axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "offset",
+ "value": 0
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The x axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "phase",
+ "value": 0
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair",
+ "desc": "x: time domain\ny: generated signal"
+ }
+ ],
+ "path": "DATA/GENERATION/SIMULATIONS/BASIC_OSCILLATOR/BASIC_OSCILLATOR.py"
+ },
+ "position": {
+ "x": -362.1075027285308,
+ "y": 31.080632360951938
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -362.1075027285308,
+ "y": 31.080632360951938
+ },
+ "dragging": true
+ },
+ {
+ "width": 210,
+ "height": 96,
+ "id": "BASIC_OSCILLATOR-7ce8d7e2-ec85-4e06-a3c3-c04359d10b94",
+ "type": "DATA",
+ "data": {
+ "id": "BASIC_OSCILLATOR-7ce8d7e2-ec85-4e06-a3c3-c04359d10b94",
+ "label": "BASIC OSCILLATOR 1",
+ "func": "BASIC_OSCILLATOR",
+ "type": "DATA",
+ "ctrls": {
+ "sample_rate": {
+ "type": "int",
+ "default": 100,
+ "desc": "The number of samples that are taken in a second.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "sample_rate",
+ "value": 2000
+ },
+ "time": {
+ "type": "int",
+ "default": 10,
+ "desc": "The total amount of time of the signal.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "time",
+ "value": 1
+ },
+ "waveform": {
+ "type": "select",
+ "options": [
+ "sine",
+ "square",
+ "triangle",
+ "sawtooth"
+ ],
+ "default": "sine",
+ "desc": "The waveform type of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "waveform",
+ "value": "sine"
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The amplitude of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "amplitude",
+ "value": 2
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1,
+ "desc": "The wave frequency in radians/2pi.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "frequency",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The y axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "offset",
+ "value": 5
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The x axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "phase",
+ "value": 1
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair",
+ "desc": "x: time domain\ny: generated signal"
+ }
+ ],
+ "path": "DATA/GENERATION/SIMULATIONS/BASIC_OSCILLATOR/BASIC_OSCILLATOR.py"
+ },
+ "position": {
+ "x": -356.8896911005901,
+ "y": 166.0972138398535
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -356.8896911005901,
+ "y": 166.0972138398535
+ },
+ "dragging": true
+ },
+ {
+ "width": 72,
+ "height": 72,
+ "id": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "type": "ARITHMETIC",
+ "data": {
+ "id": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "label": "MULTIPLY",
+ "func": "MULTIPLY",
+ "type": "ARITHMETIC",
+ "ctrls": {},
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "a",
+ "id": "a",
+ "type": "OrderedPair|Scalar|Vector",
+ "multiple": false,
+ "desc": "The input a use to compute the product of a and b."
+ },
+ {
+ "name": "b",
+ "id": "b",
+ "type": "OrderedPair|Scalar|Vector",
+ "multiple": true,
+ "desc": "The input b use to compute the product of a and b."
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair|Scalar|Vector",
+ "desc": "OrderedPair if a is an OrderedPair.\nx: the x-axis of input a.\ny: the result of the product of input a and input b.\n\nScalar if a is a Scalar.\nc: the result of the product of input a and input b.\n\nVector if a is a Vector.\nv: the result of the product of input a and input b."
+ }
+ ],
+ "path": "MATH/ARITHMETIC/MULTIPLY/MULTIPLY.py"
+ },
+ "position": {
+ "x": -29.35682713839612,
+ "y": 129.60080736694715
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -29.35682713839612,
+ "y": 129.60080736694715
+ },
+ "dragging": true
+ },
+ {
+ "width": 380,
+ "height": 293,
+ "id": "LINE-f160352e-ab73-47c2-a1b9-658bd41a8865",
+ "type": "VISUALIZATION",
+ "data": {
+ "id": "LINE-f160352e-ab73-47c2-a1b9-658bd41a8865",
+ "label": "LINE",
+ "func": "LINE",
+ "type": "VISUALIZATION",
+ "ctrls": {},
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair|DataFrame|Matrix|Vector",
+ "multiple": false,
+ "desc": "the DataContainer to be visualized"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "Plotly",
+ "desc": "the DataContainer containing the Plotly Line visualization of the input data"
+ }
+ ],
+ "path": "DATA/VISUALIZATION/PLOTLY/LINE/LINE.py"
+ },
+ "position": {
+ "x": 257.6493418294323,
+ "y": 219.14870774764609
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 257.6493418294323,
+ "y": 219.14870774764609
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3",
+ "type": "HARDWARE",
+ "data": {
+ "id": "OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3",
+ "label": "OUTPUT AFG31000",
+ "func": "OUTPUT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "ch1": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 1 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1",
+ "value": "on"
+ },
+ "ch2": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 2 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2",
+ "value": "on"
+ },
+ "ch1_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 1 impedance.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1_impedance",
+ "value": "50"
+ },
+ "ch2_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 2 impedance",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2_impedance",
+ "value": "50"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py"
+ },
+ "position": {
+ "x": 521.5212679159422,
+ "y": -167.45967092017608
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 521.5212679159422,
+ "y": -167.45967092017608
+ },
+ "dragging": true
+ },
+ {
+ "width": 210,
+ "height": 96,
+ "id": "BASIC_OSCILLATOR-fc420f32-3b96-4cf9-ad6f-a16bbab741d8",
+ "type": "DATA",
+ "data": {
+ "id": "BASIC_OSCILLATOR-fc420f32-3b96-4cf9-ad6f-a16bbab741d8",
+ "label": "BASIC OSCILLATOR 2",
+ "func": "BASIC_OSCILLATOR",
+ "type": "DATA",
+ "ctrls": {
+ "sample_rate": {
+ "type": "int",
+ "default": 100,
+ "desc": "The number of samples that are taken in a second.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "sample_rate",
+ "value": 500
+ },
+ "time": {
+ "type": "int",
+ "default": 10,
+ "desc": "The total amount of time of the signal.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "time",
+ "value": 4
+ },
+ "waveform": {
+ "type": "select",
+ "options": [
+ "sine",
+ "square",
+ "triangle",
+ "sawtooth"
+ ],
+ "default": "sine",
+ "desc": "The waveform type of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "waveform",
+ "value": "sine"
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The amplitude of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "amplitude",
+ "value": 2
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1,
+ "desc": "The wave frequency in radians/2pi.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "frequency",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The y axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "offset",
+ "value": 5
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The x axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "phase",
+ "value": 1
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair",
+ "desc": "x: time domain\ny: generated signal"
+ }
+ ],
+ "path": "DATA/GENERATION/SIMULATIONS/BASIC_OSCILLATOR/BASIC_OSCILLATOR.py"
+ },
+ "position": {
+ "x": -350.3747265214252,
+ "y": 299.2271519922165
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -350.3747265214252,
+ "y": 299.2271519922165
+ },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "sourceHandle": "default",
+ "target": "ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2ac",
+ "targetHandle": "input",
+ "id": "reactflow__edge-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1cadefault-ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2acinput"
+ },
+ {
+ "source": "BASIC_OSCILLATOR-5ea02552-dcaf-43d9-b296-075501fa958a",
+ "sourceHandle": "default",
+ "target": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "targetHandle": "a",
+ "id": "reactflow__edge-BASIC_OSCILLATOR-5ea02552-dcaf-43d9-b296-075501fa958adefault-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1caa"
+ },
+ {
+ "source": "BASIC_OSCILLATOR-7ce8d7e2-ec85-4e06-a3c3-c04359d10b94",
+ "sourceHandle": "default",
+ "target": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "targetHandle": "b",
+ "id": "reactflow__edge-BASIC_OSCILLATOR-7ce8d7e2-ec85-4e06-a3c3-c04359d10b94default-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1cab"
+ },
+ {
+ "source": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "sourceHandle": "default",
+ "target": "LINE-f160352e-ab73-47c2-a1b9-658bd41a8865",
+ "targetHandle": "default",
+ "id": "reactflow__edge-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1cadefault-LINE-f160352e-ab73-47c2-a1b9-658bd41a8865default"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781input"
+ },
+ {
+ "source": "COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3",
+ "targetHandle": "input",
+ "id": "reactflow__edge-COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781default-OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3input"
+ },
+ {
+ "source": "ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2ac",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3",
+ "targetHandle": "input",
+ "id": "reactflow__edge-ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2acdefault-OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3input"
+ },
+ {
+ "source": "BASIC_OSCILLATOR-fc420f32-3b96-4cf9-ad6f-a16bbab741d8",
+ "sourceHandle": "default",
+ "target": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "targetHandle": "b",
+ "id": "reactflow__edge-BASIC_OSCILLATOR-fc420f32-3b96-4cf9-ad6f-a16bbab741d8default-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1cab"
+ }
+ ],
+ "viewport": {
+ "x": 998.0979704909867,
+ "y": 583.9050842369531,
+ "zoom": 0.9793470432493011
+ }
+ },
+ "textNodes": []
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/block_data.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/block_data.json
new file mode 100644
index 00000000..c7fee765
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/block_data.json
@@ -0,0 +1,45 @@
+{
+ "docstring": {
+ "long_description": "This block should also work with compatible Tektronix AFG31XXX instruments.",
+ "short_description": "Set basic parameters such as frequency for a single channel.",
+ "parameters": [
+ {
+ "name": "connection",
+ "type": "VisaConnection",
+ "description": "The VISA address (requires the CONNECTION_AFG31000 block)."
+ },
+ {
+ "name": "channel",
+ "type": "select, default=1",
+ "description": "Choose the channel to alter."
+ },
+ {
+ "name": "frequency",
+ "type": "float, default=1e6",
+ "description": "The voltage of the waveform to set, in Hz."
+ },
+ {
+ "name": "amplitude",
+ "type": "float, default=1",
+ "description": "The voltage of the waveform to set."
+ },
+ {
+ "name": "offset",
+ "type": "float, default=0",
+ "description": "The voltage offset to set the waveform to, in volts."
+ },
+ {
+ "name": "phase",
+ "type": "float, default=0",
+ "description": "The phase to set the waveform to, in degrees."
+ }
+ ],
+ "returns": [
+ {
+ "name": null,
+ "type": "String",
+ "description": "Placeholder"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/example.md b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/example.md
new file mode 100644
index 00000000..ec67e308
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/example.md
@@ -0,0 +1,20 @@
+In this example, an Tektronix AFG31000 is used to generate an arbitrary waveform.
+
+First the necessary blocks were added:
+
+- `CONNECT_AFG31000`
+- `COPY_AFG31000`
+- `ARBITRARY_AFG31000`
+- `BASIC_PARAMETERS_AFG31000`
+- `OUTPUT_AFG31000`
+- 3x `BASIC_OSCILLATOR`
+- `MULTIPLY`
+- `LINE`
+
+The instrument address was set for each `AFG31000` block. Ensure the `OUTPUT_AFG31000` block has channel 1 output turned on. Note the `COPY_AFG31000` block is rename `PLACEHOLDER` here and it preset for block running order reasons. The `BASIC_PARAMETERS_AFG31000` block is used to change frequency, offset, voltage, and phase for a single channel, without changing the function itself.
+
+The blocks were connected as shown and the app was run. The 3 `BASIC_OSCILLATOR` blocks were used to generate the arbitrary waveform. Any waveform generated in Flojoy can be used as the input for `ARBITRARY_AFG31000` to allow for any output.
+
+An oscilloscope was connected to the AFG31000 resulting in waveform:
+
+![image](https://res.cloudinary.com/dhopxs1y3/image/upload/v1701277907/flojoy-docs/afg31000/afg31000_arb.png)
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py
new file mode 100644
index 00000000..cbb15380
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py
@@ -0,0 +1,42 @@
+from flojoy import VisaDevice, flojoy, String
+from flojoy.connection_manager import DeviceConnectionManager
+from pyvisa import ResourceManager
+from usb.core import USBError
+
+
+@flojoy
+def CONNECT_AFG31000(
+ device: VisaDevice,
+) -> String:
+ """Connect Flojoy to a AFG31000 function generator.
+
+ The connection is made with the VISA address in the Flojoy UI.
+
+ This block should also work with compatible Tektronix AFG31XXX instruments.
+
+ Parameters
+ ----------
+ device: VisaDevice
+ The VISA address to connect to.
+
+ Returns
+ -------
+ device_addr: String
+ The IP or VISA address of the VISA device.
+ """
+
+ rm = ResourceManager("@py")
+ addr = device.get_id()
+
+ try:
+ afg = rm.open_resource(addr)
+ except USBError as err:
+ raise Exception(
+ "USB port error. Trying unplugging+replugging the port."
+ ) from err
+
+ afg.read_termination = "\n"
+ afg.write_termination = "\n"
+ DeviceConnectionManager.register_connection(device, afg)
+
+ return String(s=addr)
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/app.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/app.json
new file mode 100644
index 00000000..cfe2cd71
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/app.json
@@ -0,0 +1,633 @@
+{
+ "rfInstance": {
+ "nodes": [
+ {
+ "width": 192,
+ "height": 192,
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "type": "HARDWARE",
+ "data": {
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "label": "CONNECT AFG31000",
+ "func": "CONNECT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "device": {
+ "type": "VisaDevice",
+ "default": null,
+ "desc": "The VISA address to connect to.",
+ "overload": null,
+ "functionName": "CONNECT_AFG31000",
+ "param": "device",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "The IP or VISA address of the VISA device."
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py"
+ },
+ "position": {
+ "x": -356.99744674030666,
+ "y": -192.33911380820962
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -356.99744674030666,
+ "y": -192.33911380820962
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "type": "HARDWARE",
+ "data": {
+ "id": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "label": "ALIGN PHASES AFG31000",
+ "func": "ALIGN_PHASES_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "ALIGN_PHASES_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "channel": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": "Which channel is the reference?",
+ "overload": null,
+ "functionName": "ALIGN_PHASES_AFG31000",
+ "param": "channel",
+ "value": "1"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/ALIGN_PHASES_AFG31000.py"
+ },
+ "position": {
+ "x": 439.9476681838445,
+ "y": -194.69759194078154
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 439.9476681838445,
+ "y": -194.69759194078154
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "type": "HARDWARE",
+ "data": {
+ "id": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "label": "OUTPUT AFG31000",
+ "func": "OUTPUT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "ch1": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 1 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1",
+ "value": "on"
+ },
+ "ch2": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 2 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2",
+ "value": "on"
+ },
+ "ch1_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 1 impedance.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1_impedance",
+ "value": "50"
+ },
+ "ch2_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 2 impedance",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2_impedance",
+ "value": "50"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py"
+ },
+ "position": {
+ "x": 193.0241524368904,
+ "y": -193.99838203480326
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 193.0241524368904,
+ "y": -193.99838203480326
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "type": "HARDWARE",
+ "data": {
+ "id": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "label": "SAVE STATE AFG31000",
+ "func": "SAVE_STATE_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "save_recall": {
+ "type": "select",
+ "options": [
+ "save",
+ "recall"
+ ],
+ "default": "save",
+ "desc": "Save or recall the save state.",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "save_recall",
+ "value": "save"
+ },
+ "option": {
+ "type": "select",
+ "options": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5"
+ ],
+ "default": "1",
+ "desc": "Choose from the 5 save states.",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "option",
+ "value": "2"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Save state"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/SAVE_STATE_AFG31000.py"
+ },
+ "position": {
+ "x": 680.0566763496477,
+ "y": -192.15162100388233
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 680.0566763496477,
+ "y": -192.15162100388233
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "type": "HARDWARE",
+ "data": {
+ "id": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "label": "FUNCTION AFG31000",
+ "func": "FUNCTION_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "source",
+ "value": "1"
+ },
+ "functions": {
+ "type": "select",
+ "options": [
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine"
+ ],
+ "default": "sinusoid",
+ "desc": "Choose the function to output",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "functions",
+ "value": "sinusoid"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "frequency",
+ "value": 2000000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "amplitude",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "offset",
+ "value": 0
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "phase",
+ "value": 0
+ },
+ "pulse_width": {
+ "type": "float",
+ "default": 0.000001,
+ "desc": "The pulse width in nanoseconds if the PULS waveform is used.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "pulse_width",
+ "value": 0.000001
+ },
+ "ramp_symmetry": {
+ "type": "float",
+ "default": 50,
+ "desc": "The ramp symmetry if the RAMP waveform is used, in percent.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "ramp_symmetry",
+ "value": 50
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py"
+ },
+ "position": {
+ "x": -67.77699444442803,
+ "y": -334.69885402865026
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -67.77699444442803,
+ "y": -334.69885402865026
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "type": "HARDWARE",
+ "data": {
+ "id": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "label": "FUNCTION AFG31000 1",
+ "func": "FUNCTION_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "source",
+ "value": "2"
+ },
+ "functions": {
+ "type": "select",
+ "options": [
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine"
+ ],
+ "default": "sinusoid",
+ "desc": "Choose the function to output",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "functions",
+ "value": "gaussian"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "frequency",
+ "value": 5000000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "amplitude",
+ "value": 2
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "offset",
+ "value": -0.5
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "phase",
+ "value": 45
+ },
+ "pulse_width": {
+ "type": "float",
+ "default": 0.000001,
+ "desc": "The pulse width in nanoseconds if the PULS waveform is used.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "pulse_width",
+ "value": 0.000001
+ },
+ "ramp_symmetry": {
+ "type": "float",
+ "default": 50,
+ "desc": "The ramp symmetry if the RAMP waveform is used, in percent.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "ramp_symmetry",
+ "value": 50
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py"
+ },
+ "position": {
+ "x": -62.333665463218566,
+ "y": -90.14297151518164
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -62.333665463218566,
+ "y": -90.14297151518164
+ },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "sourceHandle": "default",
+ "target": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "targetHandle": "input",
+ "id": "reactflow__edge-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1default-ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749input"
+ },
+ {
+ "source": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "targetHandle": "input",
+ "id": "reactflow__edge-FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527default-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1input"
+ },
+ {
+ "source": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "targetHandle": "input",
+ "id": "reactflow__edge-FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2adefault-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1input"
+ },
+ {
+ "source": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "sourceHandle": "default",
+ "target": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "targetHandle": "input",
+ "id": "reactflow__edge-ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749default-SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dcinput"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527input"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2ainput"
+ }
+ ],
+ "viewport": {
+ "x": 998.0979704909867,
+ "y": 583.9050842369531,
+ "zoom": 0.9793470432493011
+ }
+ },
+ "textNodes": []
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/block_data.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/block_data.json
new file mode 100644
index 00000000..607638b3
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/block_data.json
@@ -0,0 +1,20 @@
+{
+ "docstring": {
+ "long_description": "The connection is made with the VISA address in the Flojoy UI.\n\nThis block should also work with compatible Tektronix AFG31XXX instruments.",
+ "short_description": "Connect Flojoy to a AFG31000 function generator.",
+ "parameters": [
+ {
+ "name": "device",
+ "type": "VisaDevice",
+ "description": "The VISA address to connect to."
+ }
+ ],
+ "returns": [
+ {
+ "name": "device_addr",
+ "type": "String",
+ "description": "The IP or VISA address of the VISA device."
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/example.md b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/example.md
new file mode 100644
index 00000000..4c1183ad
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/example.md
@@ -0,0 +1,18 @@
+In this example, an Tektronix AFG31000 is used to generate two waveforms.
+
+First the necessary blocks were added:
+
+- `CONNECT_AFG31000`
+- `RESET_AFG31000`
+- 2x `FUNCTION_AFG31000`
+- `ALIGN_PHASES_AFG31000`
+- `OUTPUT_AFG31000`
+- `SAVE_STATE_AFG31000`
+
+The instrument address was set for each `AFG31000` block. Ensure the `OUTPUT_AFG31000` block has both channels turn on.
+
+The blocks were connected as shown and the app was run. The `SAVE_STATE_AFG31000` block can be used to save and recall the current state of the AFG. However, you must use a `OUTPUT_AFG31000` block to turn the outputs back on.
+
+An oscilloscope was connected to the AFG31000 resulting in waveform:
+
+![image](https://res.cloudinary.com/dhopxs1y3/image/upload/v1701277906/flojoy-docs/afg31000/afg31000_basic.png)
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/COPY_AFG31000.py b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/COPY_AFG31000.py
new file mode 100644
index 00000000..101cd937
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/COPY_AFG31000.py
@@ -0,0 +1,35 @@
+from flojoy import flojoy, DataContainer, String, VisaConnection
+from typing import Optional, Literal
+
+
+@flojoy(inject_connection=True)
+def COPY_AFG31000(
+ connection: VisaConnection,
+ channel: Literal["ch1", "ch2"] = "ch1",
+ input: Optional[DataContainer] = None,
+) -> String:
+ """Copy the setup parameters to the other channel.
+
+ This block should also work with compatible Tektronix AFG31XXX instruments.
+
+ Parameters
+ ----------
+ connection: VisaConnection
+ The VISA address (requires the CONNECTION_AFG31000 block).
+ channel: select, default=ch1
+ Which channel to copy to the other channel.
+
+ Returns
+ -------
+ String
+ Placeholder
+ """
+
+ afg = connection.get_handle()
+
+ if channel == "ch1":
+ afg.write("AFGControl:CSCopy CH1,CH2")
+ else:
+ afg.write("AFGControl:CSCopy CH2,CH1")
+
+ return String(s="Copied channel parameters")
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/app.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/app.json
new file mode 100644
index 00000000..7e448660
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/app.json
@@ -0,0 +1,796 @@
+{
+ "rfInstance": {
+ "nodes": [
+ {
+ "width": 192,
+ "height": 192,
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "type": "HARDWARE",
+ "data": {
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "label": "CONNECT AFG31000",
+ "func": "CONNECT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "device": {
+ "type": "VisaDevice",
+ "default": null,
+ "desc": "The VISA address to connect to.",
+ "overload": null,
+ "functionName": "CONNECT_AFG31000",
+ "param": "device",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "The IP or VISA address of the VISA device."
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py"
+ },
+ "position": {
+ "x": -174.2226058564158,
+ "y": -353.6710962643813
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -174.2226058564158,
+ "y": -353.6710962643813
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2ac",
+ "type": "HARDWARE",
+ "data": {
+ "id": "ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2ac",
+ "label": "ARBITRARY AFG31000",
+ "func": "ARBITRARY_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "memory_state": {
+ "type": "select",
+ "options": [
+ "EMEM1",
+ "EMEM2"
+ ],
+ "default": "EMEM1",
+ "desc": "Save the function in \"Edit Memory\" 1 or 2.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "memory_state",
+ "value": "EMEM1"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "source",
+ "value": "1"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "frequency",
+ "value": 100000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "amplitude",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "offset",
+ "value": 0
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "ARBITRARY_AFG31000",
+ "param": "phase",
+ "value": 0
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "OrderedPair|Vector",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/ARBITRARY_AFG31000.py"
+ },
+ "position": {
+ "x": 145.66871932962246,
+ "y": -43.37213414482457
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 145.66871932962246,
+ "y": -43.37213414482457
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781",
+ "type": "HARDWARE",
+ "data": {
+ "id": "COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781",
+ "label": "PLACEHOLDER",
+ "func": "COPY_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "COPY_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "channel": {
+ "type": "select",
+ "options": [
+ "ch1",
+ "ch2"
+ ],
+ "default": "ch1",
+ "desc": "Which channel to copy to the other channel.",
+ "overload": null,
+ "functionName": "COPY_AFG31000",
+ "param": "channel",
+ "value": "ch1"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/COPY_AFG31000.py"
+ },
+ "position": {
+ "x": 144.4620281465655,
+ "y": -351.58208891808863
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 144.4620281465655,
+ "y": -351.58208891808863
+ },
+ "dragging": true
+ },
+ {
+ "width": 210,
+ "height": 96,
+ "id": "BASIC_OSCILLATOR-5ea02552-dcaf-43d9-b296-075501fa958a",
+ "type": "DATA",
+ "data": {
+ "id": "BASIC_OSCILLATOR-5ea02552-dcaf-43d9-b296-075501fa958a",
+ "label": "BASIC OSCILLATOR",
+ "func": "BASIC_OSCILLATOR",
+ "type": "DATA",
+ "ctrls": {
+ "sample_rate": {
+ "type": "int",
+ "default": 100,
+ "desc": "The number of samples that are taken in a second.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "sample_rate",
+ "value": 1000
+ },
+ "time": {
+ "type": "int",
+ "default": 10,
+ "desc": "The total amount of time of the signal.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "time",
+ "value": 2
+ },
+ "waveform": {
+ "type": "select",
+ "options": [
+ "sine",
+ "square",
+ "triangle",
+ "sawtooth"
+ ],
+ "default": "sine",
+ "desc": "The waveform type of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "waveform",
+ "value": "sine"
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The amplitude of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "amplitude",
+ "value": 1
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1,
+ "desc": "The wave frequency in radians/2pi.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "frequency",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The y axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "offset",
+ "value": 0
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The x axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "phase",
+ "value": 0
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair",
+ "desc": "x: time domain\ny: generated signal"
+ }
+ ],
+ "path": "DATA/GENERATION/SIMULATIONS/BASIC_OSCILLATOR/BASIC_OSCILLATOR.py"
+ },
+ "position": {
+ "x": -362.1075027285308,
+ "y": 31.080632360951938
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -362.1075027285308,
+ "y": 31.080632360951938
+ },
+ "dragging": true
+ },
+ {
+ "width": 210,
+ "height": 96,
+ "id": "BASIC_OSCILLATOR-7ce8d7e2-ec85-4e06-a3c3-c04359d10b94",
+ "type": "DATA",
+ "data": {
+ "id": "BASIC_OSCILLATOR-7ce8d7e2-ec85-4e06-a3c3-c04359d10b94",
+ "label": "BASIC OSCILLATOR 1",
+ "func": "BASIC_OSCILLATOR",
+ "type": "DATA",
+ "ctrls": {
+ "sample_rate": {
+ "type": "int",
+ "default": 100,
+ "desc": "The number of samples that are taken in a second.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "sample_rate",
+ "value": 2000
+ },
+ "time": {
+ "type": "int",
+ "default": 10,
+ "desc": "The total amount of time of the signal.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "time",
+ "value": 1
+ },
+ "waveform": {
+ "type": "select",
+ "options": [
+ "sine",
+ "square",
+ "triangle",
+ "sawtooth"
+ ],
+ "default": "sine",
+ "desc": "The waveform type of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "waveform",
+ "value": "sine"
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The amplitude of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "amplitude",
+ "value": 2
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1,
+ "desc": "The wave frequency in radians/2pi.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "frequency",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The y axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "offset",
+ "value": 5
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The x axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "phase",
+ "value": 1
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair",
+ "desc": "x: time domain\ny: generated signal"
+ }
+ ],
+ "path": "DATA/GENERATION/SIMULATIONS/BASIC_OSCILLATOR/BASIC_OSCILLATOR.py"
+ },
+ "position": {
+ "x": -356.8896911005901,
+ "y": 166.0972138398535
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -356.8896911005901,
+ "y": 166.0972138398535
+ },
+ "dragging": true
+ },
+ {
+ "width": 72,
+ "height": 72,
+ "id": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "type": "ARITHMETIC",
+ "data": {
+ "id": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "label": "MULTIPLY",
+ "func": "MULTIPLY",
+ "type": "ARITHMETIC",
+ "ctrls": {},
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "a",
+ "id": "a",
+ "type": "OrderedPair|Scalar|Vector",
+ "multiple": false,
+ "desc": "The input a use to compute the product of a and b."
+ },
+ {
+ "name": "b",
+ "id": "b",
+ "type": "OrderedPair|Scalar|Vector",
+ "multiple": true,
+ "desc": "The input b use to compute the product of a and b."
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair|Scalar|Vector",
+ "desc": "OrderedPair if a is an OrderedPair.\nx: the x-axis of input a.\ny: the result of the product of input a and input b.\n\nScalar if a is a Scalar.\nc: the result of the product of input a and input b.\n\nVector if a is a Vector.\nv: the result of the product of input a and input b."
+ }
+ ],
+ "path": "MATH/ARITHMETIC/MULTIPLY/MULTIPLY.py"
+ },
+ "position": {
+ "x": -29.35682713839612,
+ "y": 129.60080736694715
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -29.35682713839612,
+ "y": 129.60080736694715
+ },
+ "dragging": true
+ },
+ {
+ "width": 380,
+ "height": 293,
+ "id": "LINE-f160352e-ab73-47c2-a1b9-658bd41a8865",
+ "type": "VISUALIZATION",
+ "data": {
+ "id": "LINE-f160352e-ab73-47c2-a1b9-658bd41a8865",
+ "label": "LINE",
+ "func": "LINE",
+ "type": "VISUALIZATION",
+ "ctrls": {},
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair|DataFrame|Matrix|Vector",
+ "multiple": false,
+ "desc": "the DataContainer to be visualized"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "Plotly",
+ "desc": "the DataContainer containing the Plotly Line visualization of the input data"
+ }
+ ],
+ "path": "DATA/VISUALIZATION/PLOTLY/LINE/LINE.py"
+ },
+ "position": {
+ "x": 257.6493418294323,
+ "y": 219.14870774764609
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 257.6493418294323,
+ "y": 219.14870774764609
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3",
+ "type": "HARDWARE",
+ "data": {
+ "id": "OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3",
+ "label": "OUTPUT AFG31000",
+ "func": "OUTPUT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "ch1": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 1 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1",
+ "value": "on"
+ },
+ "ch2": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 2 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2",
+ "value": "on"
+ },
+ "ch1_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 1 impedance.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1_impedance",
+ "value": "50"
+ },
+ "ch2_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 2 impedance",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2_impedance",
+ "value": "50"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py"
+ },
+ "position": {
+ "x": 521.5212679159422,
+ "y": -167.45967092017608
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 521.5212679159422,
+ "y": -167.45967092017608
+ },
+ "dragging": true
+ },
+ {
+ "width": 210,
+ "height": 96,
+ "id": "BASIC_OSCILLATOR-fc420f32-3b96-4cf9-ad6f-a16bbab741d8",
+ "type": "DATA",
+ "data": {
+ "id": "BASIC_OSCILLATOR-fc420f32-3b96-4cf9-ad6f-a16bbab741d8",
+ "label": "BASIC OSCILLATOR 2",
+ "func": "BASIC_OSCILLATOR",
+ "type": "DATA",
+ "ctrls": {
+ "sample_rate": {
+ "type": "int",
+ "default": 100,
+ "desc": "The number of samples that are taken in a second.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "sample_rate",
+ "value": 500
+ },
+ "time": {
+ "type": "int",
+ "default": 10,
+ "desc": "The total amount of time of the signal.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "time",
+ "value": 4
+ },
+ "waveform": {
+ "type": "select",
+ "options": [
+ "sine",
+ "square",
+ "triangle",
+ "sawtooth"
+ ],
+ "default": "sine",
+ "desc": "The waveform type of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "waveform",
+ "value": "sine"
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The amplitude of the wave.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "amplitude",
+ "value": 2
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1,
+ "desc": "The wave frequency in radians/2pi.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "frequency",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The y axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "offset",
+ "value": 5
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The x axis offset of the function.",
+ "overload": null,
+ "functionName": "BASIC_OSCILLATOR",
+ "param": "phase",
+ "value": 1
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair",
+ "desc": "x: time domain\ny: generated signal"
+ }
+ ],
+ "path": "DATA/GENERATION/SIMULATIONS/BASIC_OSCILLATOR/BASIC_OSCILLATOR.py"
+ },
+ "position": {
+ "x": -350.3747265214252,
+ "y": 299.2271519922165
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -350.3747265214252,
+ "y": 299.2271519922165
+ },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "sourceHandle": "default",
+ "target": "ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2ac",
+ "targetHandle": "input",
+ "id": "reactflow__edge-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1cadefault-ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2acinput"
+ },
+ {
+ "source": "BASIC_OSCILLATOR-5ea02552-dcaf-43d9-b296-075501fa958a",
+ "sourceHandle": "default",
+ "target": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "targetHandle": "a",
+ "id": "reactflow__edge-BASIC_OSCILLATOR-5ea02552-dcaf-43d9-b296-075501fa958adefault-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1caa"
+ },
+ {
+ "source": "BASIC_OSCILLATOR-7ce8d7e2-ec85-4e06-a3c3-c04359d10b94",
+ "sourceHandle": "default",
+ "target": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "targetHandle": "b",
+ "id": "reactflow__edge-BASIC_OSCILLATOR-7ce8d7e2-ec85-4e06-a3c3-c04359d10b94default-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1cab"
+ },
+ {
+ "source": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "sourceHandle": "default",
+ "target": "LINE-f160352e-ab73-47c2-a1b9-658bd41a8865",
+ "targetHandle": "default",
+ "id": "reactflow__edge-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1cadefault-LINE-f160352e-ab73-47c2-a1b9-658bd41a8865default"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781input"
+ },
+ {
+ "source": "COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3",
+ "targetHandle": "input",
+ "id": "reactflow__edge-COPY_AFG31000-3f95b109-8283-4ab0-84bf-d4f1a9123781default-OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3input"
+ },
+ {
+ "source": "ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2ac",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3",
+ "targetHandle": "input",
+ "id": "reactflow__edge-ARBITRARY_AFG31000-82d2ab69-9799-49ac-9259-8f0f668dd2acdefault-OUTPUT_AFG31000-03bf3003-a20a-4fc5-9cfb-7fbb4538dee3input"
+ },
+ {
+ "source": "BASIC_OSCILLATOR-fc420f32-3b96-4cf9-ad6f-a16bbab741d8",
+ "sourceHandle": "default",
+ "target": "MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1ca",
+ "targetHandle": "b",
+ "id": "reactflow__edge-BASIC_OSCILLATOR-fc420f32-3b96-4cf9-ad6f-a16bbab741d8default-MULTIPLY-280a75f4-7a1c-4f5f-84cf-1453439aa1cab"
+ }
+ ],
+ "viewport": {
+ "x": 998.0979704909867,
+ "y": 583.9050842369531,
+ "zoom": 0.9793470432493011
+ }
+ },
+ "textNodes": []
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/block_data.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/block_data.json
new file mode 100644
index 00000000..b6ada852
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/block_data.json
@@ -0,0 +1,25 @@
+{
+ "docstring": {
+ "long_description": "This block should also work with compatible Tektronix AFG31XXX instruments.",
+ "short_description": "Copy the setup parameters to the other channel.",
+ "parameters": [
+ {
+ "name": "connection",
+ "type": "VisaConnection",
+ "description": "The VISA address (requires the CONNECTION_AFG31000 block)."
+ },
+ {
+ "name": "channel",
+ "type": "select, default=ch1",
+ "description": "Which channel to copy to the other channel."
+ }
+ ],
+ "returns": [
+ {
+ "name": null,
+ "type": "String",
+ "description": "Placeholder"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/example.md b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/example.md
new file mode 100644
index 00000000..ec67e308
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/example.md
@@ -0,0 +1,20 @@
+In this example, an Tektronix AFG31000 is used to generate an arbitrary waveform.
+
+First the necessary blocks were added:
+
+- `CONNECT_AFG31000`
+- `COPY_AFG31000`
+- `ARBITRARY_AFG31000`
+- `BASIC_PARAMETERS_AFG31000`
+- `OUTPUT_AFG31000`
+- 3x `BASIC_OSCILLATOR`
+- `MULTIPLY`
+- `LINE`
+
+The instrument address was set for each `AFG31000` block. Ensure the `OUTPUT_AFG31000` block has channel 1 output turned on. Note the `COPY_AFG31000` block is rename `PLACEHOLDER` here and it preset for block running order reasons. The `BASIC_PARAMETERS_AFG31000` block is used to change frequency, offset, voltage, and phase for a single channel, without changing the function itself.
+
+The blocks were connected as shown and the app was run. The 3 `BASIC_OSCILLATOR` blocks were used to generate the arbitrary waveform. Any waveform generated in Flojoy can be used as the input for `ARBITRARY_AFG31000` to allow for any output.
+
+An oscilloscope was connected to the AFG31000 resulting in waveform:
+
+![image](https://res.cloudinary.com/dhopxs1y3/image/upload/v1701277907/flojoy-docs/afg31000/afg31000_arb.png)
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py
new file mode 100644
index 00000000..f4ee54e0
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py
@@ -0,0 +1,78 @@
+from flojoy import flojoy, DataContainer, String, VisaConnection
+from typing import Optional, Literal
+
+
+@flojoy(inject_connection=True)
+def FUNCTION_AFG31000(
+ connection: VisaConnection,
+ source: Literal["1", "2"] = "1",
+ functions: Literal[
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine",
+ ] = "sinusoid",
+ frequency: float = 1e6,
+ amplitude: float = 1,
+ offset: float = 0,
+ phase: float = 0,
+ pulse_width: float = 1e-6,
+ ramp_symmetry: float = 50,
+ input: Optional[DataContainer] = None,
+) -> String:
+ """Set the parameters for the built-in function generator.
+
+ This block should also work with compatible Tektronix AFG31XXX instruments.
+
+ Parameters
+ ----------
+ connection: VisaConnection
+ The VISA address (requires the CONNECTION_AFG31000 block).
+ channel: select, default=1
+ Choose the channel to alter.
+ functions: select, default=sinusoid
+ Choose the function to output
+ frequency: float, default=1e6
+ The voltage of the waveform to set, in Hz.
+ amplitude: float, default=1
+ The voltage of the waveform to set.
+ offset: float, default=0
+ The voltage offset to set the waveform to, in volts.
+ phase: float, default=0
+ The phase to set the waveform to, in degrees.
+ pulse_width: float, default=1e-6
+ The pulse width in nanoseconds if the PULS waveform is used.
+ ramp_symmetry: float, default=50
+ The ramp symmetry if the RAMP waveform is used, in percent.
+
+ Returns
+ -------
+ String
+ Placeholder
+ """
+
+ assert -180.0 <= phase <= 180.0, "The phase must be between -180 and 180 degrees."
+
+ afg = connection.get_handle()
+
+ afg.write(f"SOURCE{source}:FUNCtion:SHAPe {functions}")
+ afg.write(f"SOURCE{source}:FREQUENCY {frequency}")
+ afg.write(f"SOURCE{source}:VOLTAGE:AMPLITUDE {amplitude}")
+ afg.write(f"SOURCE{source}:VOLTAGE:OFFSET {offset}")
+ afg.write(f"SOURCE{source}:PHASE:ADJUST {phase}DEG")
+
+ if functions == "pulse":
+ afg.write(f"SOURCE{source}:PULSE:WIDTH {pulse_width}")
+ if functions == "ramp":
+ assert 0 <= ramp_symmetry <= 100.0, "The phase must be between 0 and 100%."
+ afg.write(f"SOURCE{source}:FUNCtion:RAMP:SYMMETRY {ramp_symmetry}")
+
+ return String(s="Set FG parameters")
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/app.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/app.json
new file mode 100644
index 00000000..cfe2cd71
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/app.json
@@ -0,0 +1,633 @@
+{
+ "rfInstance": {
+ "nodes": [
+ {
+ "width": 192,
+ "height": 192,
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "type": "HARDWARE",
+ "data": {
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "label": "CONNECT AFG31000",
+ "func": "CONNECT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "device": {
+ "type": "VisaDevice",
+ "default": null,
+ "desc": "The VISA address to connect to.",
+ "overload": null,
+ "functionName": "CONNECT_AFG31000",
+ "param": "device",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "The IP or VISA address of the VISA device."
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py"
+ },
+ "position": {
+ "x": -356.99744674030666,
+ "y": -192.33911380820962
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -356.99744674030666,
+ "y": -192.33911380820962
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "type": "HARDWARE",
+ "data": {
+ "id": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "label": "ALIGN PHASES AFG31000",
+ "func": "ALIGN_PHASES_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "ALIGN_PHASES_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "channel": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": "Which channel is the reference?",
+ "overload": null,
+ "functionName": "ALIGN_PHASES_AFG31000",
+ "param": "channel",
+ "value": "1"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/ALIGN_PHASES_AFG31000.py"
+ },
+ "position": {
+ "x": 439.9476681838445,
+ "y": -194.69759194078154
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 439.9476681838445,
+ "y": -194.69759194078154
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "type": "HARDWARE",
+ "data": {
+ "id": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "label": "OUTPUT AFG31000",
+ "func": "OUTPUT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "ch1": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 1 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1",
+ "value": "on"
+ },
+ "ch2": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 2 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2",
+ "value": "on"
+ },
+ "ch1_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 1 impedance.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1_impedance",
+ "value": "50"
+ },
+ "ch2_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 2 impedance",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2_impedance",
+ "value": "50"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py"
+ },
+ "position": {
+ "x": 193.0241524368904,
+ "y": -193.99838203480326
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 193.0241524368904,
+ "y": -193.99838203480326
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "type": "HARDWARE",
+ "data": {
+ "id": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "label": "SAVE STATE AFG31000",
+ "func": "SAVE_STATE_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "save_recall": {
+ "type": "select",
+ "options": [
+ "save",
+ "recall"
+ ],
+ "default": "save",
+ "desc": "Save or recall the save state.",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "save_recall",
+ "value": "save"
+ },
+ "option": {
+ "type": "select",
+ "options": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5"
+ ],
+ "default": "1",
+ "desc": "Choose from the 5 save states.",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "option",
+ "value": "2"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Save state"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/SAVE_STATE_AFG31000.py"
+ },
+ "position": {
+ "x": 680.0566763496477,
+ "y": -192.15162100388233
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 680.0566763496477,
+ "y": -192.15162100388233
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "type": "HARDWARE",
+ "data": {
+ "id": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "label": "FUNCTION AFG31000",
+ "func": "FUNCTION_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "source",
+ "value": "1"
+ },
+ "functions": {
+ "type": "select",
+ "options": [
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine"
+ ],
+ "default": "sinusoid",
+ "desc": "Choose the function to output",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "functions",
+ "value": "sinusoid"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "frequency",
+ "value": 2000000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "amplitude",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "offset",
+ "value": 0
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "phase",
+ "value": 0
+ },
+ "pulse_width": {
+ "type": "float",
+ "default": 0.000001,
+ "desc": "The pulse width in nanoseconds if the PULS waveform is used.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "pulse_width",
+ "value": 0.000001
+ },
+ "ramp_symmetry": {
+ "type": "float",
+ "default": 50,
+ "desc": "The ramp symmetry if the RAMP waveform is used, in percent.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "ramp_symmetry",
+ "value": 50
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py"
+ },
+ "position": {
+ "x": -67.77699444442803,
+ "y": -334.69885402865026
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -67.77699444442803,
+ "y": -334.69885402865026
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "type": "HARDWARE",
+ "data": {
+ "id": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "label": "FUNCTION AFG31000 1",
+ "func": "FUNCTION_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "source",
+ "value": "2"
+ },
+ "functions": {
+ "type": "select",
+ "options": [
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine"
+ ],
+ "default": "sinusoid",
+ "desc": "Choose the function to output",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "functions",
+ "value": "gaussian"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "frequency",
+ "value": 5000000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "amplitude",
+ "value": 2
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "offset",
+ "value": -0.5
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "phase",
+ "value": 45
+ },
+ "pulse_width": {
+ "type": "float",
+ "default": 0.000001,
+ "desc": "The pulse width in nanoseconds if the PULS waveform is used.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "pulse_width",
+ "value": 0.000001
+ },
+ "ramp_symmetry": {
+ "type": "float",
+ "default": 50,
+ "desc": "The ramp symmetry if the RAMP waveform is used, in percent.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "ramp_symmetry",
+ "value": 50
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py"
+ },
+ "position": {
+ "x": -62.333665463218566,
+ "y": -90.14297151518164
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -62.333665463218566,
+ "y": -90.14297151518164
+ },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "sourceHandle": "default",
+ "target": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "targetHandle": "input",
+ "id": "reactflow__edge-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1default-ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749input"
+ },
+ {
+ "source": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "targetHandle": "input",
+ "id": "reactflow__edge-FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527default-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1input"
+ },
+ {
+ "source": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "targetHandle": "input",
+ "id": "reactflow__edge-FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2adefault-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1input"
+ },
+ {
+ "source": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "sourceHandle": "default",
+ "target": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "targetHandle": "input",
+ "id": "reactflow__edge-ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749default-SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dcinput"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527input"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2ainput"
+ }
+ ],
+ "viewport": {
+ "x": 998.0979704909867,
+ "y": 583.9050842369531,
+ "zoom": 0.9793470432493011
+ }
+ },
+ "textNodes": []
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/block_data.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/block_data.json
new file mode 100644
index 00000000..6cd405ea
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/block_data.json
@@ -0,0 +1,60 @@
+{
+ "docstring": {
+ "long_description": "This block should also work with compatible Tektronix AFG31XXX instruments.",
+ "short_description": "Set the parameters for the built-in function generator.",
+ "parameters": [
+ {
+ "name": "connection",
+ "type": "VisaConnection",
+ "description": "The VISA address (requires the CONNECTION_AFG31000 block)."
+ },
+ {
+ "name": "channel",
+ "type": "select, default=1",
+ "description": "Choose the channel to alter."
+ },
+ {
+ "name": "functions",
+ "type": "select, default=sinusoid",
+ "description": "Choose the function to output"
+ },
+ {
+ "name": "frequency",
+ "type": "float, default=1e6",
+ "description": "The voltage of the waveform to set, in Hz."
+ },
+ {
+ "name": "amplitude",
+ "type": "float, default=1",
+ "description": "The voltage of the waveform to set."
+ },
+ {
+ "name": "offset",
+ "type": "float, default=0",
+ "description": "The voltage offset to set the waveform to, in volts."
+ },
+ {
+ "name": "phase",
+ "type": "float, default=0",
+ "description": "The phase to set the waveform to, in degrees."
+ },
+ {
+ "name": "pulse_width",
+ "type": "float, default=1e-6",
+ "description": "The pulse width in nanoseconds if the PULS waveform is used."
+ },
+ {
+ "name": "ramp_symmetry",
+ "type": "float, default=50",
+ "description": "The ramp symmetry if the RAMP waveform is used, in percent."
+ }
+ ],
+ "returns": [
+ {
+ "name": null,
+ "type": "String",
+ "description": "Placeholder"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/example.md b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/example.md
new file mode 100644
index 00000000..4c1183ad
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/example.md
@@ -0,0 +1,18 @@
+In this example, an Tektronix AFG31000 is used to generate two waveforms.
+
+First the necessary blocks were added:
+
+- `CONNECT_AFG31000`
+- `RESET_AFG31000`
+- 2x `FUNCTION_AFG31000`
+- `ALIGN_PHASES_AFG31000`
+- `OUTPUT_AFG31000`
+- `SAVE_STATE_AFG31000`
+
+The instrument address was set for each `AFG31000` block. Ensure the `OUTPUT_AFG31000` block has both channels turn on.
+
+The blocks were connected as shown and the app was run. The `SAVE_STATE_AFG31000` block can be used to save and recall the current state of the AFG. However, you must use a `OUTPUT_AFG31000` block to turn the outputs back on.
+
+An oscilloscope was connected to the AFG31000 resulting in waveform:
+
+![image](https://res.cloudinary.com/dhopxs1y3/image/upload/v1701277906/flojoy-docs/afg31000/afg31000_basic.png)
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py
new file mode 100644
index 00000000..8a7115b1
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py
@@ -0,0 +1,44 @@
+from flojoy import flojoy, DataContainer, String, VisaConnection
+from typing import Optional, Literal
+
+
+@flojoy(inject_connection=True)
+def OUTPUT_AFG31000(
+ connection: VisaConnection,
+ ch1: Literal["on", "off"] = "on",
+ ch2: Literal["on", "off"] = "on",
+ ch1_impedance: Literal["50", "1e6"] = "50",
+ ch2_impedance: Literal["50", "1e6"] = "50",
+ input: Optional[DataContainer] = None,
+) -> String:
+ """Set impedances and turn the outputs on or off.
+
+ This block should also work with compatible Tektronix AFG31XXX instruments.
+
+ Parameters
+ ----------
+ connection: VisaConnection
+ The VISA address (requires the CONNECTION_AFG31000 block).
+ ch1: select, default=on
+ Turn channel 1 output on or off.
+ ch2: select, default=on
+ Turn channel 2 output on or off.
+ ch1_impedance: select, default=50
+ Choosen channel 1 impedance.
+ ch2_impedance: select, default=50
+ Choosen channel 2 impedance
+
+ Returns
+ -------
+ String
+ Placeholder
+ """
+
+ afg = connection.get_handle()
+
+ afg.write(f"OUTPut1:IMPedance {int(ch1_impedance)}")
+ afg.write(f"OUTPut2:IMPedance {int(ch2_impedance)}")
+ afg.write(f"OUTPUT1:STATE {ch1}")
+ afg.write(f"OUTPUT2:STATE {ch2}")
+
+ return String(s="Set output parameters")
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/app.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/app.json
new file mode 100644
index 00000000..cfe2cd71
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/app.json
@@ -0,0 +1,633 @@
+{
+ "rfInstance": {
+ "nodes": [
+ {
+ "width": 192,
+ "height": 192,
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "type": "HARDWARE",
+ "data": {
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "label": "CONNECT AFG31000",
+ "func": "CONNECT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "device": {
+ "type": "VisaDevice",
+ "default": null,
+ "desc": "The VISA address to connect to.",
+ "overload": null,
+ "functionName": "CONNECT_AFG31000",
+ "param": "device",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "The IP or VISA address of the VISA device."
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py"
+ },
+ "position": {
+ "x": -356.99744674030666,
+ "y": -192.33911380820962
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -356.99744674030666,
+ "y": -192.33911380820962
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "type": "HARDWARE",
+ "data": {
+ "id": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "label": "ALIGN PHASES AFG31000",
+ "func": "ALIGN_PHASES_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "ALIGN_PHASES_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "channel": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": "Which channel is the reference?",
+ "overload": null,
+ "functionName": "ALIGN_PHASES_AFG31000",
+ "param": "channel",
+ "value": "1"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/ALIGN_PHASES_AFG31000.py"
+ },
+ "position": {
+ "x": 439.9476681838445,
+ "y": -194.69759194078154
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 439.9476681838445,
+ "y": -194.69759194078154
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "type": "HARDWARE",
+ "data": {
+ "id": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "label": "OUTPUT AFG31000",
+ "func": "OUTPUT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "ch1": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 1 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1",
+ "value": "on"
+ },
+ "ch2": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 2 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2",
+ "value": "on"
+ },
+ "ch1_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 1 impedance.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1_impedance",
+ "value": "50"
+ },
+ "ch2_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 2 impedance",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2_impedance",
+ "value": "50"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py"
+ },
+ "position": {
+ "x": 193.0241524368904,
+ "y": -193.99838203480326
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 193.0241524368904,
+ "y": -193.99838203480326
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "type": "HARDWARE",
+ "data": {
+ "id": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "label": "SAVE STATE AFG31000",
+ "func": "SAVE_STATE_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "save_recall": {
+ "type": "select",
+ "options": [
+ "save",
+ "recall"
+ ],
+ "default": "save",
+ "desc": "Save or recall the save state.",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "save_recall",
+ "value": "save"
+ },
+ "option": {
+ "type": "select",
+ "options": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5"
+ ],
+ "default": "1",
+ "desc": "Choose from the 5 save states.",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "option",
+ "value": "2"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Save state"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/SAVE_STATE_AFG31000.py"
+ },
+ "position": {
+ "x": 680.0566763496477,
+ "y": -192.15162100388233
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 680.0566763496477,
+ "y": -192.15162100388233
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "type": "HARDWARE",
+ "data": {
+ "id": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "label": "FUNCTION AFG31000",
+ "func": "FUNCTION_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "source",
+ "value": "1"
+ },
+ "functions": {
+ "type": "select",
+ "options": [
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine"
+ ],
+ "default": "sinusoid",
+ "desc": "Choose the function to output",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "functions",
+ "value": "sinusoid"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "frequency",
+ "value": 2000000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "amplitude",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "offset",
+ "value": 0
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "phase",
+ "value": 0
+ },
+ "pulse_width": {
+ "type": "float",
+ "default": 0.000001,
+ "desc": "The pulse width in nanoseconds if the PULS waveform is used.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "pulse_width",
+ "value": 0.000001
+ },
+ "ramp_symmetry": {
+ "type": "float",
+ "default": 50,
+ "desc": "The ramp symmetry if the RAMP waveform is used, in percent.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "ramp_symmetry",
+ "value": 50
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py"
+ },
+ "position": {
+ "x": -67.77699444442803,
+ "y": -334.69885402865026
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -67.77699444442803,
+ "y": -334.69885402865026
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "type": "HARDWARE",
+ "data": {
+ "id": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "label": "FUNCTION AFG31000 1",
+ "func": "FUNCTION_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "source",
+ "value": "2"
+ },
+ "functions": {
+ "type": "select",
+ "options": [
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine"
+ ],
+ "default": "sinusoid",
+ "desc": "Choose the function to output",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "functions",
+ "value": "gaussian"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "frequency",
+ "value": 5000000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "amplitude",
+ "value": 2
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "offset",
+ "value": -0.5
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "phase",
+ "value": 45
+ },
+ "pulse_width": {
+ "type": "float",
+ "default": 0.000001,
+ "desc": "The pulse width in nanoseconds if the PULS waveform is used.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "pulse_width",
+ "value": 0.000001
+ },
+ "ramp_symmetry": {
+ "type": "float",
+ "default": 50,
+ "desc": "The ramp symmetry if the RAMP waveform is used, in percent.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "ramp_symmetry",
+ "value": 50
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py"
+ },
+ "position": {
+ "x": -62.333665463218566,
+ "y": -90.14297151518164
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -62.333665463218566,
+ "y": -90.14297151518164
+ },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "sourceHandle": "default",
+ "target": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "targetHandle": "input",
+ "id": "reactflow__edge-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1default-ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749input"
+ },
+ {
+ "source": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "targetHandle": "input",
+ "id": "reactflow__edge-FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527default-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1input"
+ },
+ {
+ "source": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "targetHandle": "input",
+ "id": "reactflow__edge-FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2adefault-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1input"
+ },
+ {
+ "source": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "sourceHandle": "default",
+ "target": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "targetHandle": "input",
+ "id": "reactflow__edge-ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749default-SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dcinput"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527input"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2ainput"
+ }
+ ],
+ "viewport": {
+ "x": 998.0979704909867,
+ "y": 583.9050842369531,
+ "zoom": 0.9793470432493011
+ }
+ },
+ "textNodes": []
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/block_data.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/block_data.json
new file mode 100644
index 00000000..f0e350af
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/block_data.json
@@ -0,0 +1,40 @@
+{
+ "docstring": {
+ "long_description": "This block should also work with compatible Tektronix AFG31XXX instruments.",
+ "short_description": "Set impedances and turn the outputs on or off.",
+ "parameters": [
+ {
+ "name": "connection",
+ "type": "VisaConnection",
+ "description": "The VISA address (requires the CONNECTION_AFG31000 block)."
+ },
+ {
+ "name": "ch1",
+ "type": "select, default=on",
+ "description": "Turn channel 1 output on or off."
+ },
+ {
+ "name": "ch2",
+ "type": "select, default=on",
+ "description": "Turn channel 2 output on or off."
+ },
+ {
+ "name": "ch1_impedance",
+ "type": "select, default=50",
+ "description": "Choosen channel 1 impedance."
+ },
+ {
+ "name": "ch2_impedance",
+ "type": "select, default=50",
+ "description": "Choosen channel 2 impedance"
+ }
+ ],
+ "returns": [
+ {
+ "name": null,
+ "type": "String",
+ "description": "Placeholder"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/example.md b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/example.md
new file mode 100644
index 00000000..4c1183ad
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/example.md
@@ -0,0 +1,18 @@
+In this example, an Tektronix AFG31000 is used to generate two waveforms.
+
+First the necessary blocks were added:
+
+- `CONNECT_AFG31000`
+- `RESET_AFG31000`
+- 2x `FUNCTION_AFG31000`
+- `ALIGN_PHASES_AFG31000`
+- `OUTPUT_AFG31000`
+- `SAVE_STATE_AFG31000`
+
+The instrument address was set for each `AFG31000` block. Ensure the `OUTPUT_AFG31000` block has both channels turn on.
+
+The blocks were connected as shown and the app was run. The `SAVE_STATE_AFG31000` block can be used to save and recall the current state of the AFG. However, you must use a `OUTPUT_AFG31000` block to turn the outputs back on.
+
+An oscilloscope was connected to the AFG31000 resulting in waveform:
+
+![image](https://res.cloudinary.com/dhopxs1y3/image/upload/v1701277906/flojoy-docs/afg31000/afg31000_basic.png)
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/RESET_AFG31000.py b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/RESET_AFG31000.py
new file mode 100644
index 00000000..0cf71988
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/RESET_AFG31000.py
@@ -0,0 +1,29 @@
+from flojoy import flojoy, DataContainer, String, VisaConnection
+from typing import Optional
+
+
+@flojoy(inject_connection=True)
+def RESET_AFG31000(
+ connection: VisaConnection,
+ input: Optional[DataContainer] = None,
+) -> String:
+ """Reset the instrument.
+
+ This block should also work with compatible Tektronix AFG31XXX instruments.
+
+ Parameters
+ ----------
+ connection: VisaConnection
+ The VISA address (requires the CONNECTION_AFG31000 block).
+
+ Returns
+ -------
+ String
+ Placeholder
+ """
+
+ afg = connection.get_handle()
+
+ afg.write("*RST")
+
+ return String(s="Reset channel parameters")
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/app.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/app.json
new file mode 100644
index 00000000..cfe2cd71
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/app.json
@@ -0,0 +1,633 @@
+{
+ "rfInstance": {
+ "nodes": [
+ {
+ "width": 192,
+ "height": 192,
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "type": "HARDWARE",
+ "data": {
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "label": "CONNECT AFG31000",
+ "func": "CONNECT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "device": {
+ "type": "VisaDevice",
+ "default": null,
+ "desc": "The VISA address to connect to.",
+ "overload": null,
+ "functionName": "CONNECT_AFG31000",
+ "param": "device",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "The IP or VISA address of the VISA device."
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py"
+ },
+ "position": {
+ "x": -356.99744674030666,
+ "y": -192.33911380820962
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -356.99744674030666,
+ "y": -192.33911380820962
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "type": "HARDWARE",
+ "data": {
+ "id": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "label": "ALIGN PHASES AFG31000",
+ "func": "ALIGN_PHASES_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "ALIGN_PHASES_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "channel": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": "Which channel is the reference?",
+ "overload": null,
+ "functionName": "ALIGN_PHASES_AFG31000",
+ "param": "channel",
+ "value": "1"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/ALIGN_PHASES_AFG31000.py"
+ },
+ "position": {
+ "x": 439.9476681838445,
+ "y": -194.69759194078154
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 439.9476681838445,
+ "y": -194.69759194078154
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "type": "HARDWARE",
+ "data": {
+ "id": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "label": "OUTPUT AFG31000",
+ "func": "OUTPUT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "ch1": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 1 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1",
+ "value": "on"
+ },
+ "ch2": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 2 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2",
+ "value": "on"
+ },
+ "ch1_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 1 impedance.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1_impedance",
+ "value": "50"
+ },
+ "ch2_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 2 impedance",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2_impedance",
+ "value": "50"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py"
+ },
+ "position": {
+ "x": 193.0241524368904,
+ "y": -193.99838203480326
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 193.0241524368904,
+ "y": -193.99838203480326
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "type": "HARDWARE",
+ "data": {
+ "id": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "label": "SAVE STATE AFG31000",
+ "func": "SAVE_STATE_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "save_recall": {
+ "type": "select",
+ "options": [
+ "save",
+ "recall"
+ ],
+ "default": "save",
+ "desc": "Save or recall the save state.",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "save_recall",
+ "value": "save"
+ },
+ "option": {
+ "type": "select",
+ "options": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5"
+ ],
+ "default": "1",
+ "desc": "Choose from the 5 save states.",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "option",
+ "value": "2"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Save state"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/SAVE_STATE_AFG31000.py"
+ },
+ "position": {
+ "x": 680.0566763496477,
+ "y": -192.15162100388233
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 680.0566763496477,
+ "y": -192.15162100388233
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "type": "HARDWARE",
+ "data": {
+ "id": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "label": "FUNCTION AFG31000",
+ "func": "FUNCTION_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "source",
+ "value": "1"
+ },
+ "functions": {
+ "type": "select",
+ "options": [
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine"
+ ],
+ "default": "sinusoid",
+ "desc": "Choose the function to output",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "functions",
+ "value": "sinusoid"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "frequency",
+ "value": 2000000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "amplitude",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "offset",
+ "value": 0
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "phase",
+ "value": 0
+ },
+ "pulse_width": {
+ "type": "float",
+ "default": 0.000001,
+ "desc": "The pulse width in nanoseconds if the PULS waveform is used.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "pulse_width",
+ "value": 0.000001
+ },
+ "ramp_symmetry": {
+ "type": "float",
+ "default": 50,
+ "desc": "The ramp symmetry if the RAMP waveform is used, in percent.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "ramp_symmetry",
+ "value": 50
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py"
+ },
+ "position": {
+ "x": -67.77699444442803,
+ "y": -334.69885402865026
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -67.77699444442803,
+ "y": -334.69885402865026
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "type": "HARDWARE",
+ "data": {
+ "id": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "label": "FUNCTION AFG31000 1",
+ "func": "FUNCTION_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "source",
+ "value": "2"
+ },
+ "functions": {
+ "type": "select",
+ "options": [
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine"
+ ],
+ "default": "sinusoid",
+ "desc": "Choose the function to output",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "functions",
+ "value": "gaussian"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "frequency",
+ "value": 5000000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "amplitude",
+ "value": 2
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "offset",
+ "value": -0.5
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "phase",
+ "value": 45
+ },
+ "pulse_width": {
+ "type": "float",
+ "default": 0.000001,
+ "desc": "The pulse width in nanoseconds if the PULS waveform is used.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "pulse_width",
+ "value": 0.000001
+ },
+ "ramp_symmetry": {
+ "type": "float",
+ "default": 50,
+ "desc": "The ramp symmetry if the RAMP waveform is used, in percent.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "ramp_symmetry",
+ "value": 50
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py"
+ },
+ "position": {
+ "x": -62.333665463218566,
+ "y": -90.14297151518164
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -62.333665463218566,
+ "y": -90.14297151518164
+ },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "sourceHandle": "default",
+ "target": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "targetHandle": "input",
+ "id": "reactflow__edge-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1default-ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749input"
+ },
+ {
+ "source": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "targetHandle": "input",
+ "id": "reactflow__edge-FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527default-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1input"
+ },
+ {
+ "source": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "targetHandle": "input",
+ "id": "reactflow__edge-FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2adefault-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1input"
+ },
+ {
+ "source": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "sourceHandle": "default",
+ "target": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "targetHandle": "input",
+ "id": "reactflow__edge-ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749default-SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dcinput"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527input"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2ainput"
+ }
+ ],
+ "viewport": {
+ "x": 998.0979704909867,
+ "y": 583.9050842369531,
+ "zoom": 0.9793470432493011
+ }
+ },
+ "textNodes": []
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/block_data.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/block_data.json
new file mode 100644
index 00000000..6f52e3bb
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/block_data.json
@@ -0,0 +1,20 @@
+{
+ "docstring": {
+ "long_description": "This block should also work with compatible Tektronix AFG31XXX instruments.",
+ "short_description": "Reset the instrument.",
+ "parameters": [
+ {
+ "name": "connection",
+ "type": "VisaConnection",
+ "description": "The VISA address (requires the CONNECTION_AFG31000 block)."
+ }
+ ],
+ "returns": [
+ {
+ "name": null,
+ "type": "String",
+ "description": "Placeholder"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/example.md b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/example.md
new file mode 100644
index 00000000..4c1183ad
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/example.md
@@ -0,0 +1,18 @@
+In this example, an Tektronix AFG31000 is used to generate two waveforms.
+
+First the necessary blocks were added:
+
+- `CONNECT_AFG31000`
+- `RESET_AFG31000`
+- 2x `FUNCTION_AFG31000`
+- `ALIGN_PHASES_AFG31000`
+- `OUTPUT_AFG31000`
+- `SAVE_STATE_AFG31000`
+
+The instrument address was set for each `AFG31000` block. Ensure the `OUTPUT_AFG31000` block has both channels turn on.
+
+The blocks were connected as shown and the app was run. The `SAVE_STATE_AFG31000` block can be used to save and recall the current state of the AFG. However, you must use a `OUTPUT_AFG31000` block to turn the outputs back on.
+
+An oscilloscope was connected to the AFG31000 resulting in waveform:
+
+![image](https://res.cloudinary.com/dhopxs1y3/image/upload/v1701277906/flojoy-docs/afg31000/afg31000_basic.png)
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/SAVE_STATE_AFG31000.py b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/SAVE_STATE_AFG31000.py
new file mode 100644
index 00000000..3da23aa3
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/SAVE_STATE_AFG31000.py
@@ -0,0 +1,40 @@
+from flojoy import flojoy, DataContainer, String, VisaConnection
+from typing import Optional, Literal
+
+
+@flojoy(inject_connection=True)
+def SAVE_STATE_AFG31000(
+ connection: VisaConnection,
+ save_recall: Literal["save", "recall"] = "save",
+ option: Literal["1", "2", "3", "4", "5"] = "1",
+ input: Optional[DataContainer] = None,
+) -> String:
+ """Saves or recalls the state for the AFG31000.
+
+ The channel output state is not save (i.e. if the channel was outputing).
+
+ This block should also work with compatible Tektronix AFG31XXX instruments.
+
+ Parameters
+ ----------
+ connection: VisaConnection
+ The VISA address (requires the CONNECTION_AFG31000 block).
+ save_recall: select, default=save
+ Save or recall the save state.
+ option: select, default=1
+ Choose from the 5 save states.
+
+ Returns
+ -------
+ String
+ Save state
+ """
+
+ afg = connection.get_handle()
+
+ if save_recall == "save":
+ afg.write(f"*SAV {option}")
+ else:
+ afg.write(f"*RCL {option}")
+
+ return String(s=f"Save state {option}")
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/app.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/app.json
new file mode 100644
index 00000000..cfe2cd71
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/app.json
@@ -0,0 +1,633 @@
+{
+ "rfInstance": {
+ "nodes": [
+ {
+ "width": 192,
+ "height": 192,
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "type": "HARDWARE",
+ "data": {
+ "id": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "label": "CONNECT AFG31000",
+ "func": "CONNECT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "device": {
+ "type": "VisaDevice",
+ "default": null,
+ "desc": "The VISA address to connect to.",
+ "overload": null,
+ "functionName": "CONNECT_AFG31000",
+ "param": "device",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ }
+ },
+ "initCtrls": {},
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "The IP or VISA address of the VISA device."
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py"
+ },
+ "position": {
+ "x": -356.99744674030666,
+ "y": -192.33911380820962
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -356.99744674030666,
+ "y": -192.33911380820962
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "type": "HARDWARE",
+ "data": {
+ "id": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "label": "ALIGN PHASES AFG31000",
+ "func": "ALIGN_PHASES_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "ALIGN_PHASES_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "channel": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": "Which channel is the reference?",
+ "overload": null,
+ "functionName": "ALIGN_PHASES_AFG31000",
+ "param": "channel",
+ "value": "1"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/ALIGN_PHASES_AFG31000.py"
+ },
+ "position": {
+ "x": 439.9476681838445,
+ "y": -194.69759194078154
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 439.9476681838445,
+ "y": -194.69759194078154
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "type": "HARDWARE",
+ "data": {
+ "id": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "label": "OUTPUT AFG31000",
+ "func": "OUTPUT_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "ch1": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 1 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1",
+ "value": "on"
+ },
+ "ch2": {
+ "type": "select",
+ "options": [
+ "on",
+ "off"
+ ],
+ "default": "on",
+ "desc": "Turn channel 2 output on or off.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2",
+ "value": "on"
+ },
+ "ch1_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 1 impedance.",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch1_impedance",
+ "value": "50"
+ },
+ "ch2_impedance": {
+ "type": "select",
+ "options": [
+ "50",
+ "1e6"
+ ],
+ "default": "50",
+ "desc": "Choosen channel 2 impedance",
+ "overload": null,
+ "functionName": "OUTPUT_AFG31000",
+ "param": "ch2_impedance",
+ "value": "50"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py"
+ },
+ "position": {
+ "x": 193.0241524368904,
+ "y": -193.99838203480326
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 193.0241524368904,
+ "y": -193.99838203480326
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "type": "HARDWARE",
+ "data": {
+ "id": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "label": "SAVE STATE AFG31000",
+ "func": "SAVE_STATE_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "save_recall": {
+ "type": "select",
+ "options": [
+ "save",
+ "recall"
+ ],
+ "default": "save",
+ "desc": "Save or recall the save state.",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "save_recall",
+ "value": "save"
+ },
+ "option": {
+ "type": "select",
+ "options": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5"
+ ],
+ "default": "1",
+ "desc": "Choose from the 5 save states.",
+ "overload": null,
+ "functionName": "SAVE_STATE_AFG31000",
+ "param": "option",
+ "value": "2"
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Save state"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/SAVE_STATE_AFG31000.py"
+ },
+ "position": {
+ "x": 680.0566763496477,
+ "y": -192.15162100388233
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 680.0566763496477,
+ "y": -192.15162100388233
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "type": "HARDWARE",
+ "data": {
+ "id": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "label": "FUNCTION AFG31000",
+ "func": "FUNCTION_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "source",
+ "value": "1"
+ },
+ "functions": {
+ "type": "select",
+ "options": [
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine"
+ ],
+ "default": "sinusoid",
+ "desc": "Choose the function to output",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "functions",
+ "value": "sinusoid"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "frequency",
+ "value": 2000000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "amplitude",
+ "value": 1
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "offset",
+ "value": 0
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "phase",
+ "value": 0
+ },
+ "pulse_width": {
+ "type": "float",
+ "default": 0.000001,
+ "desc": "The pulse width in nanoseconds if the PULS waveform is used.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "pulse_width",
+ "value": 0.000001
+ },
+ "ramp_symmetry": {
+ "type": "float",
+ "default": 50,
+ "desc": "The ramp symmetry if the RAMP waveform is used, in percent.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "ramp_symmetry",
+ "value": 50
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py"
+ },
+ "position": {
+ "x": -67.77699444442803,
+ "y": -334.69885402865026
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -67.77699444442803,
+ "y": -334.69885402865026
+ },
+ "dragging": true
+ },
+ {
+ "width": 192,
+ "height": 192,
+ "id": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "type": "HARDWARE",
+ "data": {
+ "id": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "label": "FUNCTION AFG31000 1",
+ "func": "FUNCTION_AFG31000",
+ "type": "HARDWARE",
+ "ctrls": {
+ "connection": {
+ "type": "VisaConnection",
+ "default": null,
+ "desc": "The VISA address (requires the CONNECTION_AFG31000 block).",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "connection",
+ "value": "TCPIP::169.254.145.144::INSTR"
+ },
+ "source": {
+ "type": "select",
+ "options": [
+ "1",
+ "2"
+ ],
+ "default": "1",
+ "desc": null,
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "source",
+ "value": "2"
+ },
+ "functions": {
+ "type": "select",
+ "options": [
+ "sinusoid",
+ "square",
+ "pulse",
+ "ramp",
+ "prnoise",
+ "DC",
+ "sinc",
+ "gaussian",
+ "lorentz",
+ "erise",
+ "edecay",
+ "haversine"
+ ],
+ "default": "sinusoid",
+ "desc": "Choose the function to output",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "functions",
+ "value": "gaussian"
+ },
+ "frequency": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The voltage of the waveform to set, in Hz.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "frequency",
+ "value": 5000000
+ },
+ "amplitude": {
+ "type": "float",
+ "default": 1,
+ "desc": "The voltage of the waveform to set.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "amplitude",
+ "value": 2
+ },
+ "offset": {
+ "type": "float",
+ "default": 0,
+ "desc": "The voltage offset to set the waveform to, in volts.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "offset",
+ "value": -0.5
+ },
+ "phase": {
+ "type": "float",
+ "default": 0,
+ "desc": "The phase to set the waveform to, in degrees.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "phase",
+ "value": 45
+ },
+ "pulse_width": {
+ "type": "float",
+ "default": 0.000001,
+ "desc": "The pulse width in nanoseconds if the PULS waveform is used.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "pulse_width",
+ "value": 0.000001
+ },
+ "ramp_symmetry": {
+ "type": "float",
+ "default": 50,
+ "desc": "The ramp symmetry if the RAMP waveform is used, in percent.",
+ "overload": null,
+ "functionName": "FUNCTION_AFG31000",
+ "param": "ramp_symmetry",
+ "value": 50
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "String",
+ "desc": "Placeholder"
+ }
+ ],
+ "path": "HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py"
+ },
+ "position": {
+ "x": -62.333665463218566,
+ "y": -90.14297151518164
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -62.333665463218566,
+ "y": -90.14297151518164
+ },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "sourceHandle": "default",
+ "target": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "targetHandle": "input",
+ "id": "reactflow__edge-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1default-ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749input"
+ },
+ {
+ "source": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "targetHandle": "input",
+ "id": "reactflow__edge-FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527default-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1input"
+ },
+ {
+ "source": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "sourceHandle": "default",
+ "target": "OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1",
+ "targetHandle": "input",
+ "id": "reactflow__edge-FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2adefault-OUTPUT_AFG31000-f318cbb8-f463-43c8-b06b-9f3fe2a62fe1input"
+ },
+ {
+ "source": "ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749",
+ "sourceHandle": "default",
+ "target": "SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dc",
+ "targetHandle": "input",
+ "id": "reactflow__edge-ALIGN_PHASES_AFG31000-32845bcc-be43-4ddc-adf3-8daad721c749default-SAVE_STATE_AFG31000-8f3cb51f-6cd9-49c1-bb78-9f05988a82dcinput"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-FUNCTION_AFG31000-d59ef12d-1210-419c-a3e0-db44576fc527input"
+ },
+ {
+ "source": "CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3e",
+ "sourceHandle": "default",
+ "target": "FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2a",
+ "targetHandle": "input",
+ "id": "reactflow__edge-CONNECT_AFG31000-6e227039-f81f-4f48-92a5-e4a1c0207f3edefault-FUNCTION_AFG31000-300873f1-7bc9-455a-bad4-1c9565f82b2ainput"
+ }
+ ],
+ "viewport": {
+ "x": 998.0979704909867,
+ "y": 583.9050842369531,
+ "zoom": 0.9793470432493011
+ }
+ },
+ "textNodes": []
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/block_data.json b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/block_data.json
new file mode 100644
index 00000000..3177ad5c
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/block_data.json
@@ -0,0 +1,30 @@
+{
+ "docstring": {
+ "long_description": "The channel output state is not save (i.e. if the channel was outputing).\n\nThis block should also work with compatible Tektronix AFG31XXX instruments.",
+ "short_description": "Saves or recalls the state for the AFG31000.",
+ "parameters": [
+ {
+ "name": "connection",
+ "type": "VisaConnection",
+ "description": "The VISA address (requires the CONNECTION_AFG31000 block)."
+ },
+ {
+ "name": "save_recall",
+ "type": "select, default=save",
+ "description": "Save or recall the save state."
+ },
+ {
+ "name": "option",
+ "type": "select, default=1",
+ "description": "Choose from the 5 save states."
+ }
+ ],
+ "returns": [
+ {
+ "name": null,
+ "type": "String",
+ "description": "Save state"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/example.md b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/example.md
new file mode 100644
index 00000000..4c1183ad
--- /dev/null
+++ b/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/example.md
@@ -0,0 +1,18 @@
+In this example, an Tektronix AFG31000 is used to generate two waveforms.
+
+First the necessary blocks were added:
+
+- `CONNECT_AFG31000`
+- `RESET_AFG31000`
+- 2x `FUNCTION_AFG31000`
+- `ALIGN_PHASES_AFG31000`
+- `OUTPUT_AFG31000`
+- `SAVE_STATE_AFG31000`
+
+The instrument address was set for each `AFG31000` block. Ensure the `OUTPUT_AFG31000` block has both channels turn on.
+
+The blocks were connected as shown and the app was run. The `SAVE_STATE_AFG31000` block can be used to save and recall the current state of the AFG. However, you must use a `OUTPUT_AFG31000` block to turn the outputs back on.
+
+An oscilloscope was connected to the AFG31000 resulting in waveform:
+
+![image](https://res.cloudinary.com/dhopxs1y3/image/upload/v1701277906/flojoy-docs/afg31000/afg31000_basic.png)
diff --git a/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000.mdx b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000.mdx
new file mode 100644
index 00000000..950652b1
--- /dev/null
+++ b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000.mdx
@@ -0,0 +1,43 @@
+---
+title: ALIGN_PHASES_AFG31000
+description: "Run this block to align the phases for ch1 and ch2."
+slug: blocks/hardware/function-generators/tektronix/afg31000/align-phases-afg31000
+---
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
+
+import block_data from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/block_data.json";
+import PythonDocsDisplay from "@/components/PythonDocsDisplay.astro";
+
+
+
+Python Code
+
+import pythonCode from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/ALIGN_PHASES_AFG31000.py?raw";
+
+import { Code } from 'astro:components';
+
+
+
+[Find this Flojoy Block on GitHub](https://github.com/flojoy-ai/blocks/blob/main/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/ALIGN_PHASES_AFG31000.py)
+
+
+
+## Example
+
+import GetHelpWidget from "@/components/GetHelpWidget.astro";
+
+
+
+import app from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/app.json";
+import AppDisplay from "@/components/AppDisplay.tsx";
+
+
+
+import Example from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ALIGN_PHASES_AFG31000/example.md";
+
+
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
diff --git a/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000.mdx b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000.mdx
new file mode 100644
index 00000000..854ac2a1
--- /dev/null
+++ b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000.mdx
@@ -0,0 +1,43 @@
+---
+title: ARBITRARY_AFG31000
+description: "Take the input waveform and use it as the arbitrary wavefunction."
+slug: blocks/hardware/function-generators/tektronix/afg31000/arbitrary-afg31000
+---
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
+
+import block_data from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/block_data.json";
+import PythonDocsDisplay from "@/components/PythonDocsDisplay.astro";
+
+
+
+Python Code
+
+import pythonCode from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/ARBITRARY_AFG31000.py?raw";
+
+import { Code } from 'astro:components';
+
+
+
+[Find this Flojoy Block on GitHub](https://github.com/flojoy-ai/blocks/blob/main/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/ARBITRARY_AFG31000.py)
+
+
+
+## Example
+
+import GetHelpWidget from "@/components/GetHelpWidget.astro";
+
+
+
+import app from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/app.json";
+import AppDisplay from "@/components/AppDisplay.tsx";
+
+
+
+import Example from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/ARBITRARY_AFG31000/example.md";
+
+
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
diff --git a/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000.mdx b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000.mdx
new file mode 100644
index 00000000..def42588
--- /dev/null
+++ b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000.mdx
@@ -0,0 +1,43 @@
+---
+title: BASIC_PARAMETERS_AFG31000
+description: "Set basic parameters such as frequency for a single channel."
+slug: blocks/hardware/function-generators/tektronix/afg31000/basic-parameters-afg31000
+---
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
+
+import block_data from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/block_data.json";
+import PythonDocsDisplay from "@/components/PythonDocsDisplay.astro";
+
+
+
+Python Code
+
+import pythonCode from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/BASIC_PARAMETERS_AFG31000.py?raw";
+
+import { Code } from 'astro:components';
+
+
+
+[Find this Flojoy Block on GitHub](https://github.com/flojoy-ai/blocks/blob/main/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/BASIC_PARAMETERS_AFG31000.py)
+
+
+
+## Example
+
+import GetHelpWidget from "@/components/GetHelpWidget.astro";
+
+
+
+import app from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/app.json";
+import AppDisplay from "@/components/AppDisplay.tsx";
+
+
+
+import Example from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/BASIC_PARAMETERS_AFG31000/example.md";
+
+
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
diff --git a/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000.mdx b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000.mdx
new file mode 100644
index 00000000..7bd0759a
--- /dev/null
+++ b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000.mdx
@@ -0,0 +1,43 @@
+---
+title: CONNECT_AFG31000
+description: "Connect Flojoy to a AFG31000 function generator."
+slug: blocks/hardware/function-generators/tektronix/afg31000/connect-afg31000
+---
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
+
+import block_data from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/block_data.json";
+import PythonDocsDisplay from "@/components/PythonDocsDisplay.astro";
+
+
+
+Python Code
+
+import pythonCode from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py?raw";
+
+import { Code } from 'astro:components';
+
+
+
+[Find this Flojoy Block on GitHub](https://github.com/flojoy-ai/blocks/blob/main/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/CONNECT_AFG31000.py)
+
+
+
+## Example
+
+import GetHelpWidget from "@/components/GetHelpWidget.astro";
+
+
+
+import app from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/app.json";
+import AppDisplay from "@/components/AppDisplay.tsx";
+
+
+
+import Example from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/CONNECT_AFG31000/example.md";
+
+
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
diff --git a/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000.mdx b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000.mdx
new file mode 100644
index 00000000..2653839c
--- /dev/null
+++ b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000.mdx
@@ -0,0 +1,43 @@
+---
+title: COPY_AFG31000
+description: "Copy the setup parameters to the other channel."
+slug: blocks/hardware/function-generators/tektronix/afg31000/copy-afg31000
+---
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
+
+import block_data from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/block_data.json";
+import PythonDocsDisplay from "@/components/PythonDocsDisplay.astro";
+
+
+
+Python Code
+
+import pythonCode from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/COPY_AFG31000.py?raw";
+
+import { Code } from 'astro:components';
+
+
+
+[Find this Flojoy Block on GitHub](https://github.com/flojoy-ai/blocks/blob/main/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/COPY_AFG31000.py)
+
+
+
+## Example
+
+import GetHelpWidget from "@/components/GetHelpWidget.astro";
+
+
+
+import app from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/app.json";
+import AppDisplay from "@/components/AppDisplay.tsx";
+
+
+
+import Example from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/COPY_AFG31000/example.md";
+
+
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
diff --git a/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000.mdx b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000.mdx
new file mode 100644
index 00000000..29aac2f1
--- /dev/null
+++ b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000.mdx
@@ -0,0 +1,43 @@
+---
+title: FUNCTION_AFG31000
+description: "Set the parameters for the built-in function generator."
+slug: blocks/hardware/function-generators/tektronix/afg31000/function-afg31000
+---
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
+
+import block_data from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/block_data.json";
+import PythonDocsDisplay from "@/components/PythonDocsDisplay.astro";
+
+
+
+Python Code
+
+import pythonCode from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py?raw";
+
+import { Code } from 'astro:components';
+
+
+
+[Find this Flojoy Block on GitHub](https://github.com/flojoy-ai/blocks/blob/main/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/FUNCTION_AFG31000.py)
+
+
+
+## Example
+
+import GetHelpWidget from "@/components/GetHelpWidget.astro";
+
+
+
+import app from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/app.json";
+import AppDisplay from "@/components/AppDisplay.tsx";
+
+
+
+import Example from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/FUNCTION_AFG31000/example.md";
+
+
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
diff --git a/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000.mdx b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000.mdx
new file mode 100644
index 00000000..3d429645
--- /dev/null
+++ b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000.mdx
@@ -0,0 +1,43 @@
+---
+title: OUTPUT_AFG31000
+description: "Set impedances and turn the outputs on or off."
+slug: blocks/hardware/function-generators/tektronix/afg31000/output-afg31000
+---
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
+
+import block_data from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/block_data.json";
+import PythonDocsDisplay from "@/components/PythonDocsDisplay.astro";
+
+
+
+Python Code
+
+import pythonCode from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py?raw";
+
+import { Code } from 'astro:components';
+
+
+
+[Find this Flojoy Block on GitHub](https://github.com/flojoy-ai/blocks/blob/main/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/OUTPUT_AFG31000.py)
+
+
+
+## Example
+
+import GetHelpWidget from "@/components/GetHelpWidget.astro";
+
+
+
+import app from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/app.json";
+import AppDisplay from "@/components/AppDisplay.tsx";
+
+
+
+import Example from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/OUTPUT_AFG31000/example.md";
+
+
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
diff --git a/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000.mdx b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000.mdx
new file mode 100644
index 00000000..1da3305c
--- /dev/null
+++ b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000.mdx
@@ -0,0 +1,43 @@
+---
+title: RESET_AFG31000
+description: "Reset the instrument."
+slug: blocks/hardware/function-generators/tektronix/afg31000/reset-afg31000
+---
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
+
+import block_data from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/block_data.json";
+import PythonDocsDisplay from "@/components/PythonDocsDisplay.astro";
+
+
+
+Python Code
+
+import pythonCode from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/RESET_AFG31000.py?raw";
+
+import { Code } from 'astro:components';
+
+
+
+[Find this Flojoy Block on GitHub](https://github.com/flojoy-ai/blocks/blob/main/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/RESET_AFG31000.py)
+
+
+
+## Example
+
+import GetHelpWidget from "@/components/GetHelpWidget.astro";
+
+
+
+import app from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/app.json";
+import AppDisplay from "@/components/AppDisplay.tsx";
+
+
+
+import Example from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/RESET_AFG31000/example.md";
+
+
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
diff --git a/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000.mdx b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000.mdx
new file mode 100644
index 00000000..99769070
--- /dev/null
+++ b/docs/src/content/docs/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000.mdx
@@ -0,0 +1,43 @@
+---
+title: SAVE_STATE_AFG31000
+description: "Saves or recalls the state for the AFG31000."
+slug: blocks/hardware/function-generators/tektronix/afg31000/save-state-afg31000
+---
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
+
+import block_data from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/block_data.json";
+import PythonDocsDisplay from "@/components/PythonDocsDisplay.astro";
+
+
+
+Python Code
+
+import pythonCode from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/SAVE_STATE_AFG31000.py?raw";
+
+import { Code } from 'astro:components';
+
+
+
+[Find this Flojoy Block on GitHub](https://github.com/flojoy-ai/blocks/blob/main/blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/SAVE_STATE_AFG31000.py)
+
+
+
+## Example
+
+import GetHelpWidget from "@/components/GetHelpWidget.astro";
+
+
+
+import app from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/app.json";
+import AppDisplay from "@/components/AppDisplay.tsx";
+
+
+
+import Example from "@blocks/HARDWARE/FUNCTION_GENERATORS/TEKTRONIX/AFG31000/SAVE_STATE_AFG31000/example.md";
+
+
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
diff --git a/docs/src/content/docs/blocks/HARDWARE/overview.mdx b/docs/src/content/docs/blocks/HARDWARE/overview.mdx
index 3a0ccd25..92cd4530 100644
--- a/docs/src/content/docs/blocks/HARDWARE/overview.mdx
+++ b/docs/src/content/docs/blocks/HARDWARE/overview.mdx
@@ -37,6 +37,11 @@ import BlockCategory from "@/components/BlockCategory.astro";
+#### TEKTRONIX
+##### AFG31000
+
+
+
### IMAGING