Capture Configuration#
The capture_config
module provides classes for configuring capture operations on the Saleae Logic MSO device.
A CaptureConfig
object must be built and passed to MSO.capture()
to initiate an actual capture on the hardware. There are
a lot of different knobs that control a capture, and the class CaptureConfig
handles most of the validation of those various
settings.
When a capture happens, sometimes values on the CaptureConfig
object change slightly, i.e. to reflect the actual sample rate that
was used during the capture (not all sample rates are supported, some interpolation happens, especially at high sample rates). A Capture
object always contains the CaptureConfig
objects that best represents the capture settings along with it.
Not all settings need to be set explicitly to get started, many will get sensible defaults (or device defaults) when a capture is taken.
Note: capture durations are not exact. The Logic MSO will always give you at least the requested number of samples, but may give up to 255 more samples than requested due to it’s truncation logic.
Overview#
This module defines the configuration objects that control:
Which channels to capture (analog and digital)
Sample rates and other analog settings
Capture duration and trigger settings
Classes#
CaptureConfig
#
@dataclass
class CaptureConfig:
enabled_channels: list[ChannelConfig]
analog_settings: Optional[AnalogSettings] = None
capture_settings: Optional[CaptureSettings] = None
The main configuration object for captures. A capture must have at least one enabled channel, and
should include either analog_settings
or capture_settings
if a capture other than the defaults
below is desired.
Parameters:
enabled_channels
: List of analog and digital channels to captureanalog_settings
: Optional analog capture settings (defaults to device maximum sample rate and DROP mode)capture_settings
: Optional capture settings (defaults to 1ms timed capture)
Methods:
You likely won’t need to use these, they are used behind the scenes to persist CaptureConfig
objects
in human-readable JSON in capture directories.
to_dict
: Converts configuration to device format that the capture binary understandsdef to_dict(self, output_dir: Path, mso_part_number: MsoPodPartNumber) -> Dict[str, Any]:
to_dir
: Writes a full configuration to several files in a given directorydef to_dir(self, output_dir: Path, mso_part_number: MsoPodPartNumber) -> Path:
from_dir
: Reads a configuration from a given directory@classmethod def from_dir(cls, dir_path: Path) -> "CaptureConfig":
AnalogChannel
#
@dataclass
class AnalogChannel:
channel: int
name: Optional[str] = None
center_voltage: float = 0.0
voltage_range: float = 10.0
probe_attenuation: ProbeAttenuation = ProbeAttenuation.PROBE_10X # Default to the 10x probe included with the MSO
coupling: Coupling = Coupling.DC
bandwidth_mhz: BandwidthLimit = BandwidthLimit.MHz_350
Represents an analog channel configuration.
Parameters:
channel
: The channel number (0-based index)name
: Optional descriptive name for the channel (defaults to “CH_volts”) center_voltage
: Center voltage for the channel (default: 0.0V)voltage_range
: Voltage range for the channel (default: 10.0V)probe_attenuation
: Probe attenuation setting (default: 1x)coupling
: Coupling type (default: DC)bandwidth_mhz
: Bandwidth limit (default: 350MHz)
DigitalChannel
#
@dataclass
class DigitalChannel(ChannelConfig):
channel: int
name: Optional[str] = None
port: Optional[int] = None
threshold_volts: Optional[float] = None
minimum_pulse_width_samples: Optional[int] = None
Represents a digital channel configuration.
Parameters:
channel
: The channel number (0-based index)name
: Optional descriptive name for the channel (defaults to “P_CH _logic”) port
: The port number for the digital channel (required)threshold_volts
: Voltage threshold for digital signal detection (default: None, uses global threshold)minimum_pulse_width_samples
: Minimum pulse width in samples to filter out noise (default: None)
Note: Digital channels require a port number to be specified. All digital channels on the same port share the same voltage threshold, so setting threshold_volts
on one channel will apply to all channels on that port.
AnalogSettings
#
@dataclass
class AnalogSettings:
downsample_mode: DownsampleMode = DownsampleMode.AVERAGE
sample_rate: float = 1_600_000_000 # Defaults to 1.6 GSPS
Configures analog capture settings.
Parameters:
downsample_mode
: How to handle downsampling (default: AVERAGE)sample_rate
: The sample rate in Hz (default: 1.6GS/s)
TimedCapture
#
@dataclass
class TimedCapture(CaptureSettings):
capture_length_seconds: float
Configures a capture based on duration.
Parameters:
capture_length_seconds
: How long to capture in seconds
AnalogTriggered
#
@dataclass
class AnalogTriggered(CaptureSettings):
trigger: EdgeTrigger
pre_trigger_seconds: float = 0.0005
post_trigger_seconds: float = 0.0005
timeout_seconds: float = 1.0
Configures a capture triggered by an analog signal reaching a specific threshold. See the trigger documentation for more information on configuring a trigger.
Parameters:
trigger
: The trigger settingspre_trigger_seconds
: Time before trigger to capture (default: 0.5ms)post_trigger_seconds
: Time after trigger to capture (default: 0.5ms)timeout_seconds
: Maximum time to wait for trigger before throwing a timeout error (default: 1.0s)
Enums#
ProbeAttenuation
#
If you are using the probes included with your Logic MSO, leave this attenuation setting at Probe10x
which is
the default. Those probes attenuate the signal by 10x inherently. If you are connecting a signal directly to the
input of your Logic MSO with e.g. the BNC adapter and coaxial cable, then use the Probe1x
setting to inform the
MSO it will be receiving more signal per ADC count.
class ProbeAttenuation(Enum):
PROBE_10X = "Probe10x" # default, use this when using the probes included with MSO
PROBE_1X = "Probe1x"
DownsampleMode
#
class DownsampleMode(Enum):
DROP = "Drop"
AVERAGE = "Average"
Example Capture Configurations#
from pathlib import Path
from saleae import mso_api
from saleae.mso_api.part_number import MsoPodPartNumber as PN
# Capture 100ms of data in a timed capture on 2 analog channels and 4 digital ones
config1 = mso_api.CaptureConfig(
enabled_channels=[
mso_api.AnalogChannel(channel=0, name="clock", center_voltage=2.0, voltage_range=5.0),
mso_api.AnalogChannel(channel=1, name="data", center_voltage=2.0, voltage_range=5.0),
mso_api.DigitalChannel(port=0, channel=0, name="MISO", threshold_volts=1.5),
mso_api.DigitalChannel(port=0, channel=1, name="MOSI"),
mso_api.DigitalChannel(port=0, channel=2, name="CLK"),
mso_api.DigitalChannel(port=0, channel=3, name="CS")
],
analog_settings=mso_api.AnalogSettings(
downsample_mode=mso_api.DownsampleMode.AVERAGE,
sample_rate=100e6
),
capture_settings=mso_api.TimedCapture(capture_length_seconds=0.1)
)
# Trigger a capture on the rising edge of an analog channel at full sample rate (default)
config2 = mso_api.CaptureConfig(
enabled_channels=[
# signals directly connected via coax must be set to 1x attenuation mode
mso_api.AnalogChannel(
channel=0, name="clock",
probe_attenuation=mso_api.ProbeAttenuation.PROBE_1X
),
mso_api.AnalogChannel(
channel=1, name="signal",
probe_attenuation=mso_api.ProbeAttenuation.PROBE_1X
),
],
capture_settings=mso_api.AnalogTriggered(
# specify by channel_name, or channel_index, both work
trigger=mso_api.EdgeTrigger(
channel_name="clock", threshold_volts=1.6,
direction=mso_api.EdgeTriggerDirection.RISING
),
# capture 1/2 millisecond of data on either side of the trigger
pre_trigger_seconds=0.5e-3,
post_trigger_seconds=0.5e-3,
)
)
# running config.to_dict() or mso.capture(config, ...) will throw
# errors if the configuration is invalid
for n, config in enumerate([config1, config2], start=1):
_ = config.to_dict(Path("my-capture-save-dir"), PN.MsoPod_4ch_200Mhz_12b_1000Ms)
print(f"configuration #{n} is valid")
configuration #1 is valid
configuration #2 is valid