Python API Reference
This section provides detailed documentation for the microsync Python API.
Core Classes
- class Event(c_struct_data)[source]
Bases:
object
Represents a scheduled event in the device’s priority queue.
This class contains all the information needed to execute an event, including the function to call, its arguments, timing, and repetition parameters.
- func
Function name to execute
- Type:
- arg1
First argument (usually pin number)
- arg2
Second argument (usually level or duration)
- ts
Timestamp when to execute the event (in specified units)
- Type:
- N
Number of remaining event repetitions
- Type:
- intvl
Interval between event repetitions
- Type:
- unit
Time unit (“cts”, “us”, or “ms”)
- Type:
- __init__(c_struct_data)[source]
Create an Event from raw C structure data.
- Parameters:
c_struct_data (bytes) – 28-byte C structure data from device
- map_func(func_map)[source]
Map the function address to the corresponding function name. This is used to convert the function address returned by the device to the corresponding function name for pretty printing of the event table.
- class SyncDevice(port, log_file=None)[source]
Bases:
object
Python interface for 32-bit microscope synchronization device.
This class provides a high-level API for controlling the Arduino Due-based synchronization device. It handles communication, event scheduling, and provides convenient methods for common microscope control tasks.
The device supports microsecond-precision event scheduling with a priority queue system, laser shutter control, and various acquisition modes.
- com
Serial communication interface
- func_map
Mapping of function addresses from device
- _pending_tx_
Buffer for context manager commands
- _in_context
Context manager state flag
Note
Opening the port and connecting to the sync device resets the device.
Example
>>> sd = SyncDevice("COM4") >>> sd.pos_pulse("A0", 1000, N=10, interval=50000) >>> sd.go()
- property N_events
Get the number of scheduled events in the event queue.
- Returns:
Number of events currently in the queue
- Return type:
- N_frames_left()[source]
Get the number of camera frames remaining in the current acquisition.
- Returns:
Number of camera frames left to acquire, or 0 if no acquisition is running
- Return type:
Note
In the ALEX mode, the number of frames left to acquire is the number of remaining bursts times the number of laser channels.
Example
>>> frames_left = sd.N_frames_left() >>> print(f"Remaining frames: {frames_left}")
- __enter__()[source]
Enter context manager for batch command transmission.
After entering the context manager, commands sent to the device are not transmitted immediately. Instead, they are queued and transmitted as a single batch when exiting the context manager.
Example
>>> with sd as dev: ... dev.pos_pulse("A0", 1000, ts=0) ... dev.pos_pulse("A1", 1000, ts=5000)
- __exit__(*args, **kwargs)[source]
Exit context manager and transmit batched commands.
All commands collected within the context manager are sent as a single data packet to ensure precise timing and eliminate host OS jitter.
- __init__(port, log_file=None)[source]
Initialize connection to the sync device and reset it.
- Parameters:
- Raises:
ConnectionError – If device connection fails
RuntimeWarning – If firmware/driver version mismatch
Example
>>> sd = SyncDevice("COM4", log_file="sync.log") >>> sd = SyncDevice("/dev/ttyUSB0", log_file="print")
- property cam_readout_us
Get the pre-programmed camera readout time.
- Returns:
Pre-set camera readout time in microseconds
- Return type:
- clear()[source]
Clear all scheduled events from the event queue.
This method removes all pending events from the event queue. The system timer is not affected and keeps running - use stop() to halt processing and reset the timer.
Example
>>> sd.clear() # Remove all scheduled events
- close_shutters(mask=0)[source]
Close all laser shutters. Use the mask argument to specify which shutters to close. Omitting the mask argument will close all shutters.
- Parameters:
mask (int) –
Bitmask specifying which shutters to close:
0: Closes all shutters (note: This differs from the behavior of the mask in the selected_lasers property.)
1: Cy2 only
2: Cy3 only
4: Cy5 only
8: Cy7 only
Combinations: 1|2|4 = Cy2, Cy3, and Cy5
Example
>>> sd.close_shutters() # Close all shutters >>> sd.close_shutters(2) # Close Cy3 only
- disable_pin(pin, ts=0, N=0, interval=0)[source]
Disable a pin output. The previous logical value of the pin is preserved.
- Parameters:
Example
>>> sd.disable_pin("A0", ts=1000) # Disable A0 after 1ms
- enable_pin(pin, ts=0, N=0, interval=0)[source]
Enable a pin, setting it as active. The logical level of the pin is preserved.
- Parameters:
Example
>>> sd.disable_pin("A0") # Disable A0. It will stay low regardless of calls to set_pin() >>> sd.set_pin("A0", 1) # Set A0 high. It will still stay low as the pin is disabled >>> sd.enable_pin("A0", ts=1000) # Enable A0 after 1ms. It will restore logical high level set by the previous call to set_pin()
- get_events(unit='ms')[source]
Get all scheduled events from the device queue.
- Parameters:
unit (str) – Time unit for timestamps (“cts”, “us”, or “ms”)
- Returns:
List of Event objects representing scheduled events
- Return type:
Example
>>> events = sd.get_events("us") >>> for event in events: ... print(f"{event.func} at {event.ts} {event.unit}")
- get_function_addr()[source]
Get the function address mapping from the device.
- Returns:
Mapping of function names to their addresses
- Return type:
Note
This is used internally to map function addresses to readable names.
- get_property(prop)[source]
Get a device property value; if the property is write-only, it will return an error.
- Parameters:
prop – Property enum or integer ID, see props.h for available properties
- Returns:
Property value as string
- Return type:
Example
>>> version = sd.get_property(props.ro_VERSION)
- get_status()[source]
Get detailed system status information.
The status report includes the following information: - Firmware version - System status header - Number of events in the event queue - System timer status (RUNNING or STOPPED) - System time in seconds
Example
>>> status = sd.get_status() >>> print(status)
- go()[source]
Start the system timer and begin processing scheduled events.
This method starts the hardware timer that processes the event queue. All scheduled events will be called exactly at their specified timestamps.
If more than one event is scheduled at the same time, their order of execution is undefined.
Example
>>> sd.pos_pulse("A0", 1000, ts=1000) # Sends positive pulse 1ms after go() is called >>> sd.go() # Start processing events
- property interlock_enabled
Check if the laser interlock is enabled. The interlock is a safety feature that prevents the laser from being turned on if the interlock circuit is broken. By default, the interlock is active.
- Returns:
True if interlock is active, False otherwise
- Return type:
- neg_pulse(pin, duration=0, ts=0, N=0, interval=0)[source]
Generate a negative pulse on a pin. Attempting to generate a pulse on a previously unused pin configures it as an output pin.
- Parameters:
Example
>>> sd.neg_pulse("A0", 1000, ts=5000, N=10, interval=50000)
- open_shutters(mask=0)[source]
Open all laser shutters. Use the mask argument to specify which shutters to open. Omitting the mask argument will open all shutters.
- Parameters:
mask (int) –
Bitmask specifying which shutters to open:
0: Opens all shutters (note: This differs from the behavior of the mask in the selected_lasers property.)
1: Cy2 only
2: Cy3 only
4: Cy5 only
8: Cy7 only
Combinations: 1|2|4 = Cy2, Cy3, and Cy5
Example
>>> sd.open_shutters() # Open all shutters >>> sd.open_shutters(1 | 4) # Open Cy2 and Cy5 only
- pos_pulse(pin, duration=0, ts=0, N=0, interval=0)[source]
Generate a positive pulse on a pin. Attempting to generate a pulse on a previously unused pin configures it as an output pin.
- Parameters:
Example
>>> sd.pos_pulse("A0", 1000, ts=5000, N=10, interval=50000)
- property prescaler
Get the sync device timer prescaler value. The Arduino Due runs at 84 MHz, and the system timer is clocked at 84 MHz / prescaler. The prescaler defines the system time resolution (duration of one tick, ranging from 24 ns to 1.524 µs), as well as the maximum allowable timestamp value \(t_\mathrm{max}\) (\(2^{32}\) ticks).
\(t_\mathrm{max}\) is defined as \(2^{32} \cdot \mathrm{prescaler} / 84\) µs, and ranges from 1min 42s to 1h 49min.
- Returns:
Timer prescaler (2, 8, 32, or 128)
- Return type:
Note
The prescaler is hardcoded in the firmware, and cannot be changed at runtime.
See globals.h for the prescaler values and their corresponding system time resolution and maximum timestamp value.
- property pulse_duration_us
Get the default pulse duration in microseconds. The default pulse duration is the duration of a positive or negative pulse generated by the pos_pulse() and neg_pulse() methods, and can be changed at runtime.
- Returns:
Default pulse duration in microseconds
- Return type:
- pulse_train(period, duration=0, ts=0, N=0, interval=0)[source]
Generate a burst of pulses.
- Parameters:
Example
>>> sd.pulse_train(1000, 100, ts=0, N=1000) # 1000 pulses, 1kHz
- query(cmd, arg1=0, arg2=0, ts=0, N=0, interval=0)[source]
Query the sync device - write a command and read the reply.
- Parameters:
cmd (str)
- reset()[source]
Reset the sync device and clear all events.
This method performs a soft reset of the device, clearing all events and resetting system parameters to their default values. A “soft reset” triggers a processor reset via software by writing a key and command to the Reset Controller (RSTC), which restarts the CPU without cycling power or affecting external peripherals.
Note
This operation will immediately stop the running hardware system timer, clear the event queue, and restart the device firmware. All scheduled events and timer state will be lost, and the device will reboot to its initial state, and send a startup message, indicating the firmware version.
Example
>>> sd.reset() # Reset device to default state
- property running
Check whether the sync device system timer is running.
- Returns:
True if system timer is active, False otherwise
- Return type:
- property selected_lasers
Get the currently enabled laser channels.
- Returns:
Bitmask of enabled laser channels
- Return type:
Example
>>> mask = sd.selected_lasers >>> print(f"Enabled lasers: {bin(mask)}")
- set_pin(pin, level, ts=0, N=0, interval=0)[source]
Set a pin to a specific logical level. Attempting to set a previously unused pin configures it as an output pin.
- Parameters:
Example
>>> sd.set_pin("A0", 1, ts=1000) # Set A0 high after 1ms
- set_property(prop, value)[source]
Set a device property value; if the property is read-only, it will return an error.
- Parameters:
prop – Property enum or integer ID, see props.h for available properties
value – New property value
Example
>>> sd.set_property(props.rw_DFLT_PULSE_DURATION_us, 1000)
- property shutter_delay_us
Get the pre-programmed laser shutter delay time.
- Returns:
Shutter delay time in microseconds
- Return type:
- start_ALEX_acq(exp_time, N_bursts, ts=0, burst_period=0)[source]
Start ALEX (Alternating Laser Excitation) acquisition.
In ALEX mode, frames are acquired in bursts, with each frame in a burst illuminated by a different laser channel. This enables multi-spectral imaging, and is useful for acquiring images of multiple fluorophores with different emission wavelengths.
- Parameters:
Example
>>> sd.start_ALEX_acq(50000, 9, burst_period=400000)
- start_continuous_acq(exp_time, N_frames, ts=0)[source]
Start continuous acquisition mode.
In continuous mode, laser shutters remain open during the entire acquisition and the camera is triggered at precise intervals. The first frame is automatically discarded as it contains pre-acquisition noise.
- Parameters:
Example
>>> sd.start_continuous_acq(200000, 15, ts=500000) # Acquire 15 frames with 200ms exposure, start at t=500ms
- start_stroboscopic_acq(exp_time, N_frames, ts=0, frame_period=0)[source]
Start stroboscopic or timelapse acquisition.
In stroboscopic mode, the laser shutter is briefly opened during each camera exposure, followed by a readout period. The interval between frames is set by the optional frame_period parameter, which can be used to add a delay between laser pulses for timelapse acquisition.
- Parameters:
Example
>>> # Acquire 10 frames every 500ms with 100ms long laser exposure (timelapse mode) >>> sd.start_stroboscopic_acq(100000, 10, frame_period=500000)
- stop()[source]
Stop the sync device system timer and halt event processing.
This method stops and resets the hardware timer, and deletes the event queue.
Example
>>> sd.stop() # Pause event processing >>> # schedule some events >>> sd.go() # Start processing events (from t=0)
- property sys_time_cts
Get current sync device system time in counter ticks.
- Returns:
64-bit system time in counter ticks
- Return type:
- property sys_time_s
Get current sync device system time in seconds.
- Returns:
System time in seconds
- Return type:
- tgl_pin(pin, ts=0, N=0, interval=0)[source]
Toggle a pin state. Attempting to toggle a previously unused pin configures it as an output pin.
- Parameters:
Example
>>> sd.tgl_pin("D13", N=1000, interval=1000) # Toggle D13 every 1ms
- property version
Get the firmware version. The version is a string of the form “X.Y.Z”, where X=major, Y=minor, and Z=patch. The major and minor version number of the firmware and the driver must match.
- Returns:
Firmware version string (e.g., “2.4.0”)
- Return type:
- property watchdog_timeout_ms
Get the watchdog timeout value in milliseconds. The watchdog is a safety feature that resets the sync device if it stops responding for a certain amount of time. This can happen i.e. if too many events are scheduled, and the sync device is not managing to process them in a timely manner.
- Returns:
Watchdog timeout in milliseconds, 100 ms by default
- Return type:
- write(cmd, arg1=0, arg2=0, ts=0, N=0, interval=0)[source]
Send a command to the synchronization device. If the device is in a context manager, the command is queued and transmitted as a single batch when exiting the context manager. If the device is not in a context manager, the command is transmitted immediately.
- Parameters:
Note
This is a low-level method. For most applications, use the high-level methods like pos_pulse(), tgl_pin(), etc.
- class props(value)[source]
Bases:
Enum
Enum class for the properties of the sync device. See corresponding enum in props.h
- ro_N_EVENTS = 8
Number of events in queue (read-only)
- ro_SYS_TIMER_OVF_COUNT = 3
System timer overflow count (read-only)
- ro_SYS_TIMER_PRESCALER = 5
System timer prescaler value (read-only)
- ro_SYS_TIMER_STATUS = 1
System timer running status (read-only)
- ro_SYS_TIMER_VALUE = 2
Current system timer value (read-only)
- ro_SYS_TIME_s = 4
Current system time in seconds (read-only)
- ro_VERSION = 0
Device version number (read-only)
- ro_WATCHDOG_TIMEOUT_ms = 7
Watchdog timeout in milliseconds (read-only)
- rw_CAM_READOUT_us = 14
Camera readout time in microseconds (read-write)
- rw_DFLT_PULSE_DURATION_us = 6
Default pulse duration in microseconds (read-write)
- rw_INTLCK_ENABLED = 9
Laser interlock enabled state (read-write)
- rw_SELECTED_LASERS = 10
Selected laser mask (read-write)
- rw_SHUTTER_DELAY_us = 13
Shutter delay in microseconds (read-write)
- wo_CLOSE_SHUTTERS = 12
Close all shutters (write-only)
- wo_OPEN_SHUTTERS = 11
Open all shutters (write-only)
Modules
Constants module for microsync Python driver.
This module defines fundamental constants used throughout the microsync Python driver, including time units, frequency units, and device-specific configuration values.
- Constants:
ms: Time unit for milliseconds (0.001 seconds) us: Time unit for microseconds (0.001 milliseconds) kHz: Frequency unit for kilohertz (1000 Hz) MHz: Frequency unit for megahertz (1000 kHz) UNIFORM_TIME_DELAY: Default uniform time delay in microseconds BAUDRATE: UART communication baud rate
- BAUDRATE = 115200
UART communication baud rate for device communication.
- MHz = 1000000
Megahertz frequency unit (1000 kHz).
- UNIFORM_TIME_DELAY = 500
Default uniform time delay in microseconds for event scheduling.
- kHz = 1000
Kilohertz frequency unit (1000 Hz).
- ms = 0.001
Millisecond time unit (0.001 seconds).
- us = 1e-06
Microsecond time unit (0.001 milliseconds).
Reverse pin mapping for microsync Python driver.
This module provides a reverse mapping from internal pin IDs to human-readable Arduino Due pin names. The mapping converts the device’s internal pin numbering system to the familiar Arduino pin names (D0-D65, A0-A15).
The reverse pin map is used for: - Converting internal pin IDs to readable names in error messages - Providing user-friendly pin identification in logs and debugging - Maintaining compatibility with Arduino pin naming conventions
Note
This mapping is specific to the Arduino Due board and the SAM3X8E microcontroller pin configuration used in microsync.
- rev_pin_map = {0: 'A15', 1: 'A14', 2: 'A7', 3: 'A6', 4: 'A5', 6: 'A4', 7: 'D31', 8: 'D0', 9: 'D1', 10: 'D19', 11: 'D18', 12: 'D17', 13: 'D16', 14: 'D23', 15: 'D24', 16: 'A0', 19: 'D42', 20: 'D43', 22: 'A3', 23: 'A2', 24: 'A1', 28: 'D10', 29: 'D4', 44: 'D20', 45: 'D21', 46: 'D53', 47: 'A12', 48: 'A13', 49: 'A8', 50: 'A9', 51: 'A10', 52: 'A11', 53: 'D52', 57: 'D2', 58: 'D22', 59: 'D13', 65: 'D33', 66: 'D34', 67: 'D35', 68: 'D36', 69: 'D37', 70: 'D38', 71: 'D39', 72: 'D40', 73: 'D41', 76: 'D51', 77: 'D50', 78: 'D49', 79: 'D48', 80: 'D47', 81: 'D46', 82: 'D45', 83: 'D44', 85: 'D9', 86: 'D8', 87: 'D7', 88: 'D6', 89: 'D5', 92: 'D3', 96: 'D25', 97: 'D26', 98: 'D27', 99: 'D28', 100: 'D14', 101: 'D15', 102: 'D29', 103: 'D11', 104: 'D12', 105: 'D30', 106: 'D32'}
Reverse mapping from internal pin IDs to Arduino Due pin names.
This dictionary maps the device’s internal pin IDs to human-readable Arduino Due pin names. The mapping includes: - Digital pins D0 through D65 - Analog pins A0 through A15
The internal pin IDs are based on the SAM3X8E microcontroller’s port and pin numbering system, while the Arduino names follow the standard Arduino Due pinout convention.
Example
>>> rev_pin_map[8] 'D0' >>> rev_pin_map[16] 'A0'
__version__.py
Information about the current version of package
Utility Functions
- class Event(c_struct_data)[source]
Represents a scheduled event in the device’s priority queue.
This class contains all the information needed to execute an event, including the function to call, its arguments, timing, and repetition parameters.
- arg1
First argument (usually pin number)
- arg2
Second argument (usually level or duration)
- class SyncDevice(port, log_file=None)[source]
Python interface for 32-bit microscope synchronization device.
This class provides a high-level API for controlling the Arduino Due-based synchronization device. It handles communication, event scheduling, and provides convenient methods for common microscope control tasks.
The device supports microsecond-precision event scheduling with a priority queue system, laser shutter control, and various acquisition modes.
- com
Serial communication interface
- func_map
Mapping of function addresses from device
- _pending_tx_
Buffer for context manager commands
- _in_context
Context manager state flag
Note
Opening the port and connecting to the sync device resets the device.
Example
>>> sd = SyncDevice("COM4") >>> sd.pos_pulse("A0", 1000, N=10, interval=50000) >>> sd.go()
- property N_events
Get the number of scheduled events in the event queue.
- Returns:
Number of events currently in the queue
- Return type:
- N_frames_left()[source]
Get the number of camera frames remaining in the current acquisition.
- Returns:
Number of camera frames left to acquire, or 0 if no acquisition is running
- Return type:
Note
In the ALEX mode, the number of frames left to acquire is the number of remaining bursts times the number of laser channels.
Example
>>> frames_left = sd.N_frames_left() >>> print(f"Remaining frames: {frames_left}")
- __enter__()[source]
Enter context manager for batch command transmission.
After entering the context manager, commands sent to the device are not transmitted immediately. Instead, they are queued and transmitted as a single batch when exiting the context manager.
Example
>>> with sd as dev: ... dev.pos_pulse("A0", 1000, ts=0) ... dev.pos_pulse("A1", 1000, ts=5000)
- __exit__(*args, **kwargs)[source]
Exit context manager and transmit batched commands.
All commands collected within the context manager are sent as a single data packet to ensure precise timing and eliminate host OS jitter.
- __init__(port, log_file=None)[source]
Initialize connection to the sync device and reset it.
- Parameters:
- Raises:
ConnectionError – If device connection fails
RuntimeWarning – If firmware/driver version mismatch
Example
>>> sd = SyncDevice("COM4", log_file="sync.log") >>> sd = SyncDevice("/dev/ttyUSB0", log_file="print")
- property cam_readout_us
Get the pre-programmed camera readout time.
- Returns:
Pre-set camera readout time in microseconds
- Return type:
- clear()[source]
Clear all scheduled events from the event queue.
This method removes all pending events from the event queue. The system timer is not affected and keeps running - use stop() to halt processing and reset the timer.
Example
>>> sd.clear() # Remove all scheduled events
- close_shutters(mask=0)[source]
Close all laser shutters. Use the mask argument to specify which shutters to close. Omitting the mask argument will close all shutters.
- Parameters:
mask (int) –
Bitmask specifying which shutters to close:
0: Closes all shutters (note: This differs from the behavior of the mask in the selected_lasers property.)
1: Cy2 only
2: Cy3 only
4: Cy5 only
8: Cy7 only
Combinations: 1|2|4 = Cy2, Cy3, and Cy5
Example
>>> sd.close_shutters() # Close all shutters >>> sd.close_shutters(2) # Close Cy3 only
- disable_pin(pin, ts=0, N=0, interval=0)[source]
Disable a pin output. The previous logical value of the pin is preserved.
- Parameters:
Example
>>> sd.disable_pin("A0", ts=1000) # Disable A0 after 1ms
- enable_pin(pin, ts=0, N=0, interval=0)[source]
Enable a pin, setting it as active. The logical level of the pin is preserved.
- Parameters:
Example
>>> sd.disable_pin("A0") # Disable A0. It will stay low regardless of calls to set_pin() >>> sd.set_pin("A0", 1) # Set A0 high. It will still stay low as the pin is disabled >>> sd.enable_pin("A0", ts=1000) # Enable A0 after 1ms. It will restore logical high level set by the previous call to set_pin()
- get_events(unit='ms')[source]
Get all scheduled events from the device queue.
- Parameters:
unit (str) – Time unit for timestamps (“cts”, “us”, or “ms”)
- Returns:
List of Event objects representing scheduled events
- Return type:
Example
>>> events = sd.get_events("us") >>> for event in events: ... print(f"{event.func} at {event.ts} {event.unit}")
- get_function_addr()[source]
Get the function address mapping from the device.
- Returns:
Mapping of function names to their addresses
- Return type:
Note
This is used internally to map function addresses to readable names.
- get_property(prop)[source]
Get a device property value; if the property is write-only, it will return an error.
- Parameters:
prop – Property enum or integer ID, see props.h for available properties
- Returns:
Property value as string
- Return type:
Example
>>> version = sd.get_property(props.ro_VERSION)
- get_status()[source]
Get detailed system status information.
The status report includes the following information: - Firmware version - System status header - Number of events in the event queue - System timer status (RUNNING or STOPPED) - System time in seconds
Example
>>> status = sd.get_status() >>> print(status)
- go()[source]
Start the system timer and begin processing scheduled events.
This method starts the hardware timer that processes the event queue. All scheduled events will be called exactly at their specified timestamps.
If more than one event is scheduled at the same time, their order of execution is undefined.
Example
>>> sd.pos_pulse("A0", 1000, ts=1000) # Sends positive pulse 1ms after go() is called >>> sd.go() # Start processing events
- property interlock_enabled
Check if the laser interlock is enabled. The interlock is a safety feature that prevents the laser from being turned on if the interlock circuit is broken. By default, the interlock is active.
- Returns:
True if interlock is active, False otherwise
- Return type:
- neg_pulse(pin, duration=0, ts=0, N=0, interval=0)[source]
Generate a negative pulse on a pin. Attempting to generate a pulse on a previously unused pin configures it as an output pin.
- Parameters:
Example
>>> sd.neg_pulse("A0", 1000, ts=5000, N=10, interval=50000)
- open_shutters(mask=0)[source]
Open all laser shutters. Use the mask argument to specify which shutters to open. Omitting the mask argument will open all shutters.
- Parameters:
mask (int) –
Bitmask specifying which shutters to open:
0: Opens all shutters (note: This differs from the behavior of the mask in the selected_lasers property.)
1: Cy2 only
2: Cy3 only
4: Cy5 only
8: Cy7 only
Combinations: 1|2|4 = Cy2, Cy3, and Cy5
Example
>>> sd.open_shutters() # Open all shutters >>> sd.open_shutters(1 | 4) # Open Cy2 and Cy5 only
- pos_pulse(pin, duration=0, ts=0, N=0, interval=0)[source]
Generate a positive pulse on a pin. Attempting to generate a pulse on a previously unused pin configures it as an output pin.
- Parameters:
Example
>>> sd.pos_pulse("A0", 1000, ts=5000, N=10, interval=50000)
- property prescaler
Get the sync device timer prescaler value. The Arduino Due runs at 84 MHz, and the system timer is clocked at 84 MHz / prescaler. The prescaler defines the system time resolution (duration of one tick, ranging from 24 ns to 1.524 µs), as well as the maximum allowable timestamp value \(t_\mathrm{max}\) (\(2^{32}\) ticks).
\(t_\mathrm{max}\) is defined as \(2^{32} \cdot \mathrm{prescaler} / 84\) µs, and ranges from 1min 42s to 1h 49min.
- Returns:
Timer prescaler (2, 8, 32, or 128)
- Return type:
Note
The prescaler is hardcoded in the firmware, and cannot be changed at runtime.
See globals.h for the prescaler values and their corresponding system time resolution and maximum timestamp value.
- property pulse_duration_us
Get the default pulse duration in microseconds. The default pulse duration is the duration of a positive or negative pulse generated by the pos_pulse() and neg_pulse() methods, and can be changed at runtime.
- Returns:
Default pulse duration in microseconds
- Return type:
- pulse_train(period, duration=0, ts=0, N=0, interval=0)[source]
Generate a burst of pulses.
- Parameters:
Example
>>> sd.pulse_train(1000, 100, ts=0, N=1000) # 1000 pulses, 1kHz
- query(cmd, arg1=0, arg2=0, ts=0, N=0, interval=0)[source]
Query the sync device - write a command and read the reply.
- Parameters:
cmd (str)
- reset()[source]
Reset the sync device and clear all events.
This method performs a soft reset of the device, clearing all events and resetting system parameters to their default values. A “soft reset” triggers a processor reset via software by writing a key and command to the Reset Controller (RSTC), which restarts the CPU without cycling power or affecting external peripherals.
Note
This operation will immediately stop the running hardware system timer, clear the event queue, and restart the device firmware. All scheduled events and timer state will be lost, and the device will reboot to its initial state, and send a startup message, indicating the firmware version.
Example
>>> sd.reset() # Reset device to default state
- property running
Check whether the sync device system timer is running.
- Returns:
True if system timer is active, False otherwise
- Return type:
- property selected_lasers
Get the currently enabled laser channels.
- Returns:
Bitmask of enabled laser channels
- Return type:
Example
>>> mask = sd.selected_lasers >>> print(f"Enabled lasers: {bin(mask)}")
- set_pin(pin, level, ts=0, N=0, interval=0)[source]
Set a pin to a specific logical level. Attempting to set a previously unused pin configures it as an output pin.
- Parameters:
Example
>>> sd.set_pin("A0", 1, ts=1000) # Set A0 high after 1ms
- set_property(prop, value)[source]
Set a device property value; if the property is read-only, it will return an error.
- Parameters:
prop – Property enum or integer ID, see props.h for available properties
value – New property value
Example
>>> sd.set_property(props.rw_DFLT_PULSE_DURATION_us, 1000)
- property shutter_delay_us
Get the pre-programmed laser shutter delay time.
- Returns:
Shutter delay time in microseconds
- Return type:
- start_ALEX_acq(exp_time, N_bursts, ts=0, burst_period=0)[source]
Start ALEX (Alternating Laser Excitation) acquisition.
In ALEX mode, frames are acquired in bursts, with each frame in a burst illuminated by a different laser channel. This enables multi-spectral imaging, and is useful for acquiring images of multiple fluorophores with different emission wavelengths.
- Parameters:
Example
>>> sd.start_ALEX_acq(50000, 9, burst_period=400000)
- start_continuous_acq(exp_time, N_frames, ts=0)[source]
Start continuous acquisition mode.
In continuous mode, laser shutters remain open during the entire acquisition and the camera is triggered at precise intervals. The first frame is automatically discarded as it contains pre-acquisition noise.
- Parameters:
Example
>>> sd.start_continuous_acq(200000, 15, ts=500000) # Acquire 15 frames with 200ms exposure, start at t=500ms
- start_stroboscopic_acq(exp_time, N_frames, ts=0, frame_period=0)[source]
Start stroboscopic or timelapse acquisition.
In stroboscopic mode, the laser shutter is briefly opened during each camera exposure, followed by a readout period. The interval between frames is set by the optional frame_period parameter, which can be used to add a delay between laser pulses for timelapse acquisition.
- Parameters:
Example
>>> # Acquire 10 frames every 500ms with 100ms long laser exposure (timelapse mode) >>> sd.start_stroboscopic_acq(100000, 10, frame_period=500000)
- stop()[source]
Stop the sync device system timer and halt event processing.
This method stops and resets the hardware timer, and deletes the event queue.
Example
>>> sd.stop() # Pause event processing >>> # schedule some events >>> sd.go() # Start processing events (from t=0)
- property sys_time_cts
Get current sync device system time in counter ticks.
- Returns:
64-bit system time in counter ticks
- Return type:
- property sys_time_s
Get current sync device system time in seconds.
- Returns:
System time in seconds
- Return type:
- tgl_pin(pin, ts=0, N=0, interval=0)[source]
Toggle a pin state. Attempting to toggle a previously unused pin configures it as an output pin.
- Parameters:
Example
>>> sd.tgl_pin("D13", N=1000, interval=1000) # Toggle D13 every 1ms
- property version
Get the firmware version. The version is a string of the form “X.Y.Z”, where X=major, Y=minor, and Z=patch. The major and minor version number of the firmware and the driver must match.
- Returns:
Firmware version string (e.g., “2.4.0”)
- Return type:
- property watchdog_timeout_ms
Get the watchdog timeout value in milliseconds. The watchdog is a safety feature that resets the sync device if it stops responding for a certain amount of time. This can happen i.e. if too many events are scheduled, and the sync device is not managing to process them in a timely manner.
- Returns:
Watchdog timeout in milliseconds, 100 ms by default
- Return type:
- write(cmd, arg1=0, arg2=0, ts=0, N=0, interval=0)[source]
Send a command to the synchronization device. If the device is in a context manager, the command is queued and transmitted as a single batch when exiting the context manager. If the device is not in a context manager, the command is transmitted immediately.
- Parameters:
Note
This is a low-level method. For most applications, use the high-level methods like pos_pulse(), tgl_pin(), etc.
- class props(value)[source]
Enum class for the properties of the sync device. See corresponding enum in props.h
- ro_N_EVENTS = 8
Number of events in queue (read-only)
- ro_SYS_TIMER_OVF_COUNT = 3
System timer overflow count (read-only)
- ro_SYS_TIMER_PRESCALER = 5
System timer prescaler value (read-only)
- ro_SYS_TIMER_STATUS = 1
System timer running status (read-only)
- ro_SYS_TIMER_VALUE = 2
Current system timer value (read-only)
- ro_SYS_TIME_s = 4
Current system time in seconds (read-only)
- ro_VERSION = 0
Device version number (read-only)
- ro_WATCHDOG_TIMEOUT_ms = 7
Watchdog timeout in milliseconds (read-only)
- rw_CAM_READOUT_us = 14
Camera readout time in microseconds (read-write)
- rw_DFLT_PULSE_DURATION_us = 6
Default pulse duration in microseconds (read-write)
- rw_INTLCK_ENABLED = 9
Laser interlock enabled state (read-write)
- rw_SELECTED_LASERS = 10
Selected laser mask (read-write)
- rw_SHUTTER_DELAY_us = 13
Shutter delay in microseconds (read-write)
- wo_CLOSE_SHUTTERS = 12
Close all shutters (write-only)
- wo_OPEN_SHUTTERS = 11
Open all shutters (write-only)