Skip to main content
Capture and analyze digital signals using the logic analyzer functionality of mixed-signal oscilloscopes.

Import

from lager import Net, NetType

Methods

MethodDescription
enable()Enable the logic channel display
disable()Disable the logic channel display
start_capture()Start continuous acquisition
stop_capture()Stop acquisition
start_single_capture()Start single-shot capture
force_trigger()Force a trigger event
set_signal_threshold()Set logic level threshold voltage
display_position()Set channel display position
size_large() / size_medium() / size_small()Set display size

Method Reference

Net.get(name, type=NetType.Logic)

Get a logic analyzer net by name.
from lager import Net, NetType

logic = Net.get('SPI_CLK', type=NetType.Logic)
Parameters:
ParameterTypeDescription
namestrName of the logic net
typeNetTypeMust be NetType.Logic
Returns: Logic analyzer Net instance

enable()

Enable the logic channel display.
logic.enable()

disable()

Disable the logic channel display.
logic.disable()

start_capture()

Start continuous waveform acquisition.
logic.start_capture()

stop_capture()

Stop waveform acquisition.
logic.stop_capture()

start_single_capture()

Start single-shot capture (captures one triggered event).
logic.start_single_capture()

force_trigger()

Force a trigger event immediately.
logic.force_trigger()

set_signal_threshold(voltage)

Set the logic level threshold voltage.
logic.set_signal_threshold(1.65)  # 1.65V for 3.3V CMOS
logic.set_signal_threshold(2.5)   # 2.5V for 5V TTL
ParameterTypeDescription
voltagefloatThreshold voltage in volts
Note: Channels 0-7 share one threshold, channels 8-15 share another.

display_position(position)

Set the channel display position.
logic.display_position(100)  # Set vertical position
ParameterTypeDescription
positionintVertical position value

size_large() / size_medium() / size_small()

Set the display size for enabled channels.
logic.size_large()   # Maximum visibility
logic.size_medium()  # Balanced
logic.size_small()   # Compact view

Trigger Settings

Logic analyzer nets support advanced triggering through trigger_settings:

Edge Trigger

logic = Net.get('SPI_CLK', type=NetType.Logic)

# Set edge trigger on this channel
logic.trigger_settings.edge.set_source(logic)
logic.trigger_settings.edge.set_slope_rising()
logic.trigger_settings.set_mode_normal()
Edge trigger methods:
MethodDescription
edge.set_source(net)Set trigger source net
edge.set_slope_rising()Trigger on rising edge
edge.set_slope_falling()Trigger on falling edge
edge.set_slope_both()Trigger on either edge
edge.get_slope()Get current slope setting

Pulse Trigger

logic = Net.get('PULSE_SIG', type=NetType.Logic)

# Trigger on pulse width > 1ms
logic.trigger_settings.pulse.set_source(logic)
logic.trigger_settings.pulse.set_trigger_on_pulse_greater_than_width(0.001)

# Trigger on pulse width < 100us
logic.trigger_settings.pulse.set_trigger_on_pulse_less_than_width(0.0001)

Protocol Triggers

UART Trigger

logic = Net.get('UART_TX', type=NetType.Logic)

logic.trigger_settings.uart.set_source(logic)
logic.trigger_settings.uart.set_uart_params(baud=115200, bits=8, parity=None, stopbits=1)

# Trigger on start bit
logic.trigger_settings.uart.set_trigger_on_start()

# Trigger on specific data
logic.trigger_settings.uart.set_trigger_on_data(data=0x55)

# Trigger on frame error
logic.trigger_settings.uart.set_trigger_on_frame_error()

I2C Trigger

scl = Net.get('I2C_SCL', type=NetType.Logic)
sda = Net.get('I2C_SDA', type=NetType.Logic)

scl.trigger_settings.i2c.set_source(net_scl=scl, net_sda=sda)

# Trigger on start condition
scl.trigger_settings.i2c.set_trigger_on_start()

# Trigger on specific address
scl.trigger_settings.i2c.set_trigger_on_address(bits=7, address=0x48)

# Trigger on NACK
scl.trigger_settings.i2c.set_trigger_on_nack()

SPI Trigger

clk = Net.get('SPI_CLK', type=NetType.Logic)
mosi = Net.get('SPI_MOSI', type=NetType.Logic)
cs = Net.get('SPI_CS', type=NetType.Logic)

clk.trigger_settings.spi.set_source(net_sck=clk, net_mosi_miso=mosi, net_cs=cs)
clk.trigger_settings.spi.set_clk_edge_positive()

# Trigger on specific data
clk.trigger_settings.spi.set_trigger_data(bits=8, data=0xAA)

# Trigger on CS
clk.trigger_settings.spi.set_trigger_on_cs_low()

CAN Trigger

can = Net.get('CAN_RX', type=NetType.Logic)

can.trigger_settings.can.set_source(can)
can.trigger_settings.can.set_baud(500000)

# Trigger on start of frame
can.trigger_settings.can.set_trigger_on_sof()

# Trigger on error frame
can.trigger_settings.can.set_trigger_on_error_frame()

Measurements

Logic analyzer nets support digital timing measurements:
logic = Net.get('CLK', type=NetType.Logic)

# Frequency and period
freq = logic.measurement.frequency()
period = logic.measurement.period()

# Pulse measurements
pos_width = logic.measurement.pulse_width_positive()
neg_width = logic.measurement.pulse_width_negative()
pos_duty = logic.measurement.duty_cycle_positive()
neg_duty = logic.measurement.duty_cycle_negative()

# Rise/fall times
rise = logic.measurement.rise_time()
fall = logic.measurement.fall_time()

# Edge counts
pos_edges = logic.measurement.positive_edge_count()
neg_edges = logic.measurement.negative_edge_count()

Bus Decoding

For protocol analysis, create bus decoders using multiple logic channels:

UART Bus

from lager.pcb.mappers.rigol_mso5000 import BusUART_RigolMSO5000FunctionMapper

tx = Net.get('UART_TX', type=NetType.Logic)
rx = Net.get('UART_RX', type=NetType.Logic)

bus = BusUART_RigolMSO5000FunctionMapper(tx=tx, rx=rx)
bus.set_baud(115200)
bus.set_data_bits(8)
bus.set_parity_none()
bus.set_stop_bits(1)

bus.enable()
bus.show_table()

I2C Bus

from lager.pcb.mappers.rigol_mso5000 import BusI2C_RigolMSO5000FunctionMapper

scl = Net.get('I2C_SCL', type=NetType.Logic)
sda = Net.get('I2C_SDA', type=NetType.Logic)

bus = BusI2C_RigolMSO5000FunctionMapper(scl=scl, sda=sda)
bus.set_signal_threshold(sda=1.5, scl=1.5)

bus.enable()
bus.show_table()

SPI Bus

from lager.pcb.mappers.rigol_mso5000 import BusSPI_RigolMSO5000FunctionMapper

clk = Net.get('SPI_CLK', type=NetType.Logic)
mosi = Net.get('SPI_MOSI', type=NetType.Logic)
miso = Net.get('SPI_MISO', type=NetType.Logic)
cs = Net.get('SPI_CS', type=NetType.Logic)

bus = BusSPI_RigolMSO5000FunctionMapper(clk=clk, mosi=mosi, miso=miso, cs=cs)
bus.set_sck_phase_rising_edge()
bus.set_data_width(8)
bus.set_endianness_msb()

bus.enable()
bus.show_table()

CAN Bus

from lager.pcb.mappers.rigol_mso5000 import BusCAN_RigolMSO5000FunctionMapper

can_net = Net.get('CAN_RX', type=NetType.Logic)

bus = BusCAN_RigolMSO5000FunctionMapper(can=can_net)
bus.set_baud(500000)
bus.set_signal_type_rx()
bus.set_signal_threshold(2.0)

bus.enable()
bus.show_table()

Examples

Basic Digital Signal Capture

from lager import Net, NetType
import time

# Get logic channel
clk = Net.get('SYS_CLK', type=NetType.Logic)

# Configure
clk.enable()
clk.set_signal_threshold(1.65)  # 3.3V logic
clk.size_medium()

# Set trigger
clk.trigger_settings.edge.set_source(clk)
clk.trigger_settings.edge.set_slope_rising()
clk.trigger_settings.set_mode_normal()

# Capture
clk.start_capture()
time.sleep(1)

# Measure
freq = clk.measurement.frequency()
print(f"Clock frequency: {freq / 1e6:.3f} MHz")

clk.stop_capture()
clk.disable()

SPI Communication Test

from lager import Net, NetType
from lager.pcb.mappers.rigol_mso5000 import BusSPI_RigolMSO5000FunctionMapper
import time

# Get SPI signals
clk = Net.get('SPI_CLK', type=NetType.Logic)
mosi = Net.get('SPI_MOSI', type=NetType.Logic)
miso = Net.get('SPI_MISO', type=NetType.Logic)
cs = Net.get('SPI_CS', type=NetType.Logic)

# Enable channels
for net in [clk, mosi, miso, cs]:
    net.enable()
    net.set_signal_threshold(1.65)

# Create bus decoder
bus = BusSPI_RigolMSO5000FunctionMapper(clk=clk, mosi=mosi, miso=miso, cs=cs)
bus.set_sck_phase_rising_edge()
bus.set_data_width(8)
bus.enable()
bus.show_table()

# Trigger on CS going low
clk.trigger_settings.spi.set_trigger_on_cs_low()
clk.trigger_settings.set_mode_single()

# Start capture
clk.start_single_capture()

# Wait for trigger or timeout
time.sleep(5)

# View decoded data in table
print("SPI transaction captured - check scope display")

# Clean up
bus.disable()
for net in [clk, mosi, miso, cs]:
    net.disable()

I2C Address Scanner

from lager import Net, NetType
import time

scl = Net.get('I2C_SCL', type=NetType.Logic)
sda = Net.get('I2C_SDA', type=NetType.Logic)

scl.enable()
sda.enable()
scl.set_signal_threshold(1.65)
sda.set_signal_threshold(1.65)

# Configure I2C trigger
scl.trigger_settings.i2c.set_source(net_scl=scl, net_sda=sda)
scl.trigger_settings.i2c.set_scl_trigger_level(1.65)
scl.trigger_settings.i2c.set_sda_trigger_level(1.65)

# Trigger on start condition to capture all traffic
scl.trigger_settings.i2c.set_trigger_on_start()
scl.trigger_settings.set_mode_normal()

scl.start_capture()
print("Monitoring I2C bus - trigger on start condition")

# Let it run and capture activity
time.sleep(10)

scl.stop_capture()
scl.disable()
sda.disable()

Protocol Timing Verification

from lager import Net, NetType

# Test UART timing
uart_tx = Net.get('UART_TX', type=NetType.Logic)
uart_tx.enable()
uart_tx.set_signal_threshold(1.65)

uart_tx.start_capture()

# Measure bit timing
period = uart_tx.measurement.period()
if period:
    measured_baud = 1.0 / period
    expected_baud = 115200
    error_pct = abs(measured_baud - expected_baud) / expected_baud * 100

    print(f"Measured baud: {measured_baud:.0f}")
    print(f"Expected baud: {expected_baud}")
    print(f"Error: {error_pct:.2f}%")

    if error_pct < 3:
        print("PASS: Baud rate within tolerance")
    else:
        print("FAIL: Baud rate out of tolerance")

uart_tx.stop_capture()
uart_tx.disable()

Digital Channels

ChannelRange
D0-D7Pod 1 (shared threshold)
D8-D15Pod 2 (shared threshold)

Supported Hardware

ManufacturerModelFeatures
RigolMSO5000 series16 digital channels, protocol decode

Notes

  • Logic channels are numbered D0-D15
  • Channels D0-D7 share one threshold voltage, D8-D15 share another
  • Protocol decoding requires enabling bus analysis mode
  • Use NetType.Logic for digital channels, NetType.Analog for analog
  • Bus decoders work with both Logic and Analog nets as sources
  • The trigger can use any combination of analog and digital channels