Skip to content

Commit

Permalink
Signal Generation Restructure and addition of high level methods (#246)
Browse files Browse the repository at this point in the history
fix: Added function generation to all signal generators

fix: fixes to strange resolutions to new commits and updates to docs

docs: update to documentation for signal generation

docs: fix to CHANGELOG.md and typos and grammer changes

docs: fixed changelog, some grammer changes and removal of some useless known words

docs: fixed changelog, changed docstring

docs: signal generation updates

fix: Added function generation to all signal generators

fix: fixes to strange resolutions to new commits and updates to docs

docs: update to documentation for signal generation

docs: fix to CHANGELOG.md and typos and grammer changes

docs: fixed changelog, some grammer changes and removal of some useless known words

docs: fixed changelog, changed docstring

docs: Updated the mkdocs plugin load order to fix weird capitalization issues in the new signal generation doc.

Also fixed a few things in the signal generation doc to make links render properly.

fix: Fix an issue where setup burst did not turn the channel on, so no burst would be generated

docs: Added more detail to the composition diagram in order to try to make it render more clearly

fix: Fix an issue where setup burst did not turn the channel on, so no burst would be generated

docs: Added more detail to the composition diagram in order to try to make it render more clearly
  • Loading branch information
qthompso authored Jul 24, 2024
1 parent 463004d commit 2e08380
Show file tree
Hide file tree
Showing 84 changed files with 6,531 additions and 914 deletions.
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ repos:
args: [--number, --end-of-line, keep, --ignore-missing-references]
additional_dependencies:
- setuptools # This is required since Python 3.12 no longer installs setuptools by default in virtual environments
- mdformat-admon
- mdformat-beautysh
- mdformat-config
- mdformat-footnote
Expand Down
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,30 @@ Valid subsections within a version are:

Things to be included in the next release go here.

### Added

- Added the constraint ranges for all signal generators
- Added drivers for AWG and AFG channels
- Added a property named `source_channel` in AWG's and AFG's.
- Added drivers for the internal AFG in TekScopes.
- Added a property named `internal_afg` in TekScope.
- Added implementation of `generate_function` for all AWG models.
- Added two burst functions to `SignalGeneratorMixin`: one to set up burst and one to generate the burst by forcing trigger.
- NOTE: Only the AFGs and Internal AFGs have these functions implemented.
- Added `OutputSignalPath` enum attribute in AWGs representing output signal path options.
- Added two functions for loading waveform set files in the AWG70k and AWG5200 drivers: one for loading a waveform set file and another for loading a specific waveform from a waveform set file.
- Added `sample_waveform_set_file` attribute in the AWG70k and AWG5200 drivers to define the default waveform set file.

### Changed

- <span style="color:red">BREAKING CHANGE</span>. Changed the term "signal source" to "signal generator".
- All uses of this term are changed. Import paths now use `signal_generator` instead of `signal_source`.
- <span style="color:red">BREAKING CHANGE</span>. Changed the function name of `generate_waveform()` to `generate_function()`.
- `generate_waveform()` only exists on AWGs now, however the functionality is entirely changed.
- <span style="color:red">BREAKING CHANGE</span>. Changed the `generate_function()` function by removing burst functionality.
- Any use of burst now must use `setup_burst()` and `generate_burst()` instead.
- Updated AWGs such that the `family_base_class` is at the series level.

---

## v1.5.0 (2024-06-10)
Expand Down
620 changes: 620 additions & 0 deletions docs/advanced/signal_generators.md

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions docs/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,27 @@ API
AWG
: Arbitrary Waveform Generator

DAC
: Digital to Analog Converter

DAQ
: Digital Acquisition System

DCA
: Direct-Coupled Amplifier

DMM
: Digital Multimeter

DPOJET
: A jitter, noise, timing, and eye diagram analysis tool for Tektronix Performance Digital Oscilloscopes

GPIB
: General Purpose Interface Bus

IAFG
: Internal Arbitrary Function Generator.

IDE
: Integrated Development Environment

Expand All @@ -47,6 +59,12 @@ MSO
MT
: Margin Tester

OCR
: Operation Condition Register

OPC
: Operation Complete

PI
: Programmable Interface

Expand All @@ -56,11 +74,32 @@ PSU
Scope
: Oscilloscope

SCPI
: Standard Commands for Programmable Instruments

SESR
: Standard Event Status Register

SMU
: Source Measure Unit

SRQ
: Service Request

SS
: System Switch

TCPIP
: Transmission Control Protocol/Internet Protocol

TSP
: Test Script Processor

USB
: Universal Serial Bus

VISA
: Virtual Instrument Software Architecture

WAI
: Wait
6 changes: 6 additions & 0 deletions docs/known_words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ api
artifact
artifacts
autocomplete
awgs
backend
backends
basic_curve_query
Expand All @@ -32,9 +33,11 @@ en
enum
executables
filepath
generate_function
get_acquisition_data
gh
github
haversine
hostname
hostnames
html
Expand All @@ -57,6 +60,7 @@ namespace
noqa
opensource
parallelization
pi
pre
psu
py
Expand All @@ -73,7 +77,9 @@ repo
runtime
sarif
sexualized
signal_generators
sim_devices
sinc
socio
stdout
styleguide
Expand Down
14 changes: 13 additions & 1 deletion examples/scopes/tekscope/generate_internal_afg_signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# Create a connection to the scope and indicate that it is a MSO5 scope for type hinting
scope: MSO5 = dm.add_scope("192.168.1.102")

# Generate the signal
# Generate the signal using individual PI commands.
scope.commands.afg.frequency.write(10e6) # set frequency
scope.commands.afg.offset.write(0.2) # set offset
scope.commands.afg.square.duty.write(50) # set duty cycle
Expand All @@ -18,3 +18,15 @@
scope.commands.esr.query() # check for any errors

scope.commands.acquire.stopafter.write("SEQUENCE") # perform a single sequence

# Generate the same signal using a single method call.
scope.generate_function(
frequency=10e6,
offset=0.2,
amplitude=0.5,
duty_cycle=50,
function=scope.source_device_constants.functions.SQUARE,
termination="FIFTY",
)
scope.commands.ch[1].scale.write(0.5, verify=True) # set and check vertical scale on CH1
scope.commands.acquire.stopafter.write("SEQUENCE") # perform a single sequence
18 changes: 18 additions & 0 deletions examples/signal_generators/generate_function.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""An example showing how to generate a function using an AFG."""

from tm_devices import DeviceManager
from tm_devices.drivers import AFG3K

with DeviceManager(verbose=True) as dm:
# Create a connection to the AFG and indicate that it is an AFG3K for type hinting
afg3k: AFG3K = dm.add_afg("192.168.0.1")

# Generate a RAMP waveform on SOURCE1 of the AFG3K with the provided properties.
afg3k.generate_function(
function=afg3k.source_device_constants.functions.RAMP,
channel="SOURCE1",
frequency=10e6,
amplitude=0.5,
offset=0,
symmetry=50.0,
)
17 changes: 17 additions & 0 deletions examples/signal_generators/set_source_channel_properties.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""An example showing the use of an AWG source channel."""

from tm_devices import DeviceManager
from tm_devices.drivers import AWG5K

with DeviceManager(verbose=True) as dm:
# Create a connection to the scope and indicate that it is an AWG5K for type hinting.
awg5k: AWG5K = dm.add_awg("192.168.0.1")

# Set the offset to 0.5 on SOURCE1 of the AWG5K
awg5k.source_channel["SOURCE1"].set_offset(0.5)

# Set the amplitude to 0.2 on SOURCE1 of the AWG5K
awg5k.source_channel["SOURCE1"].set_amplitude(0.2)

# Turn on SOURCE1 of the AWG5K
awg5k.source_channel["SOURCE1"].set_state(1)
110 changes: 110 additions & 0 deletions examples/signal_generators/waveform_constraints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
"""An example showing the use of waveform constraints for an AWG."""

from tm_devices import DeviceManager
from tm_devices.drivers import AWG5K
from tm_devices.helpers.enums import SignalGeneratorFunctionsAWG

# The desired frequency.
DESIRED_FREQUENCY = 10e18

# The desired amplitude.
DESIRED_AMPLITUDE = 5.0

# The desired sample rate.
DESIRED_SAMPLE_RATE = 1

# The desired function to generate.
DESIRED_FUNCTION = SignalGeneratorFunctionsAWG.SIN

# The desired waveform length to generate.
DESIRED_WAVEFORM_LENGTH = 1000000

# Format error message for function constraints.
FORMAT_ERROR_MESSAGE_FUNCTION = (
"The desired {desired_prop_name} ({desired_val}) is not within the device's "
"{desired_prop_name} range for generating a {function_name} waveform. "
"Must be in the range of [{lower}, {upper}]."
)

# Format error message for waveform length constraints.
FORMAT_ERROR_MESSAGE_WAVEFORM_LENGTH = (
"The desired {desired_prop_name} ({desired_val}) is not within the device's "
"{desired_prop_name} range for generating a waveform with a length of {waveform_length}. "
"Must be in the range of [{lower}, {upper}]."
)


with DeviceManager(verbose=True) as dm:
# Create a connection to the scope and indicate that it is an AWG5K for type hinting.
awg5k: AWG5K = dm.add_awg("192.168.0.1")

# Get the device constraints for generating the desired function on an AWG5K.
awg5k_constraints_function = awg5k.get_waveform_constraints(function=DESIRED_FUNCTION)

# Get the frequency constraints.
frequency_range = awg5k_constraints_function.frequency_range

# Print a message if the desired frequency is not within the frequency constraints.
if not frequency_range.lower <= DESIRED_FREQUENCY <= frequency_range.upper:
print(
FORMAT_ERROR_MESSAGE_FUNCTION.format(
desired_prop_name="frequency",
desired_val=DESIRED_FREQUENCY,
function_name=DESIRED_FUNCTION.name,
lower=frequency_range.lower,
upper=frequency_range.upper,
)
)
else:
# generate a function as the signal source should be able to handle it
awg5k.generate_function(
function=awg5k.source_device_constants.functions.RAMP,
channel="SOURCE1",
frequency=DESIRED_FREQUENCY,
amplitude=0.5,
offset=0,
)

# Get the amplitude constraints.
amplitude_range = awg5k_constraints_function.amplitude_range

# Print a message if the desired amplitude is not within the amplitude constraints.
if not amplitude_range.lower <= DESIRED_AMPLITUDE <= amplitude_range.upper:
print(
FORMAT_ERROR_MESSAGE_FUNCTION.format(
desired_prop_name="amplitude",
desired_val=DESIRED_AMPLITUDE,
function_name=DESIRED_FUNCTION.name,
lower=amplitude_range.lower,
upper=amplitude_range.upper,
)
)
else:
# generate a function as the signal source should be able to handle it
awg5k.generate_function(
function=awg5k.source_device_constants.functions.RAMP,
channel="SOURCE1",
frequency=500.0e3,
amplitude=DESIRED_AMPLITUDE,
offset=0,
)

# Get the device constraints for generating the desired waveform length on an AWG5K.
awg5k_constraints_waveform_length = awg5k.get_waveform_constraints(
waveform_length=DESIRED_WAVEFORM_LENGTH
)

# Get the frequency constraints.
sample_rate_range = awg5k_constraints_waveform_length.sample_rate_range

# Print a message if the desired sample rate is not within the sample rate constraints.
if not sample_rate_range.lower <= DESIRED_SAMPLE_RATE <= sample_rate_range.upper:
print(
FORMAT_ERROR_MESSAGE_WAVEFORM_LENGTH.format(
desired_prop_name="sample rate",
desired_val=DESIRED_SAMPLE_RATE,
waveform_length=DESIRED_WAVEFORM_LENGTH,
lower=sample_rate_range.lower,
upper=sample_rate_range.upper,
)
)
4 changes: 3 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ markdown_extensions:
- abbr
- smarty
- admonition
- footnotes
- md_in_html
- sane_lists
- attr_list
Expand All @@ -72,7 +73,6 @@ plugins:
- search:
prebuild_index: true
- include-markdown
- mermaid2
- section-index
- autorefs
- macros:
Expand All @@ -90,6 +90,7 @@ plugins:
use_default: true
inline_refs: none
markdown_links: true
- mermaid2
- mkdocstrings: # additional customization takes place in docs/generate_api_pages.py
# noinspection YAMLIncompatibleTypes
enabled: !ENV [TM_DEVICES_API_GENERATION, true]
Expand Down Expand Up @@ -165,6 +166,7 @@ nav: # The first entry in each section needs a hard-coded title to avoid being
- Advanced Topics:
- Architectural Overview: advanced/architecture.md
- advanced/advanced_usage.md
- advanced/signal_generators.md
- Troubleshooting:
- Troubleshooting Usage: troubleshooting/usage.md
- Troubleshooting Contributions: troubleshooting/contributions.md
Expand Down
4 changes: 2 additions & 2 deletions src/tm_devices/device_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
from tm_devices.drivers.pi.pi_device import PIDevice
from tm_devices.drivers.pi.power_supplies.power_supply import PowerSupplyUnit
from tm_devices.drivers.pi.scopes.scope import Scope
from tm_devices.drivers.pi.signal_sources.afgs.afg import AFG
from tm_devices.drivers.pi.signal_sources.awgs.awg import AWG
from tm_devices.drivers.pi.signal_generators.afgs.afg import AFG
from tm_devices.drivers.pi.signal_generators.awgs.awg import AWG
from tm_devices.drivers.pi.source_measure_units.source_measure_unit import SourceMeasureUnit
from tm_devices.drivers.pi.systems_switches.systems_switch import SystemsSwitch
from tm_devices.helpers import (
Expand Down
Loading

0 comments on commit 2e08380

Please sign in to comment.