Skip to content
This repository was archived by the owner on Jan 7, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions SynthHDDevice/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""A simple implementation for controlling the SynthHD by windfreak.

Typical usage example:

SynthHDDevice('synth',com_port='COM4')

Rabi_pulse = str.encode(str(float(Rabi_freq)))
Pulse_amp = str.encode(str(Rabi_amp))
synth.add_start_command(b'C0') #selects the channel to output RF
synth.add_start_command(b'c0') #don't sweep continuous
synth.add_start_command(b'W'+Pulse_amp)
synth.add_start_command(b'f'+Rabi_pulse)
"""

import sys

if sys.version_info < (3, 6):
raise RuntimeError("SynthHD strongly prefers Python 3.6+")
14 changes: 14 additions & 0 deletions SynthHDDevice/blacs_tabs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
"""The file that generates the GUI for the SynthHD.

As it has no GUI this is just the barebones connection.

"""

from blacs.device_base_class import DeviceTab


class SynthHDDeviceTab(DeviceTab):
"""The class behind the GUI. It inherits from DeviceTab.


Attributes:
settings: Not sure here.
worker: Not sure here.
"""

def initialise_workers(self):

# Look up the COM port and baud rate in the connection table:
Expand Down
81 changes: 63 additions & 18 deletions SynthHDDevice/blacs_workers.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
"""This is where BLACS really connects to the hardware.

Everything elso is just sending it here.
"""

import serial
import time
import labscript_utils.h5_lock
import h5py

from blacs.tab_base_classes import Worker
from windfreak import SynthHD


class SynthHDWorker(Worker):
"""The class behind the Output Worker. It inherits from Worker.


Attributes:
"""

def __init__(self):
"""Initialize the Worker.

Initializes the serial connections and resets everything properly. Should be
called init instead of __init__. At least, this is how it is in all the other
devices.
"""
# Make a serial connection to the device. The com port and buad rate which
# were passed to us from the BLACS tab are now available as instance attributes

# every time the device is restarted in BLACS,we reset the arduino after opening the serial port; this is a peculiar nature of our setup.
# every time the device is restarted in BLACS,we reset the arduino after opening the
# serial port; this is a peculiar nature of our setup.
# Note that this reset when called here, doesn't run in every shot.
self.connection = serial.Serial(self.com_port, baudrate=self.baud_rate)

Expand All @@ -22,16 +38,37 @@ def __init__(self):
self.shot_file = None

# We don't use this method but it needs to be defined:
def program_manual(self, values):
def program_manual(self, front_panel_values):
"""Required - Performans manual updates from BLACS front panel.

Attributes:
front_panel_values: Not sure where they come from.

Returns:
dict: Which are the values the Arduino gives us back after we programmed it.
"""
# pylint: disable= W0613, R0201
return {}

def transition_to_buffered(self, device_name, h5_file, initial_values, fresh):
# Read commands from the shot file and send them to the device
# this is when the hardware communication begins. It's important to reset the arduino here.
"""Read commands from the shot file and send them to the device.

This is when the hardware communication begins. It's important to reset the arduino here.

Args:
device_name: Not sure here.
h5_file: Not sure here.
initial_values: Not sure here.
fresh: Not sure here.

Returns:
Empty dict.
"""
# pylint: disable= W0613

self.shot_file = h5_file
with h5py.File(self.shot_file, "r") as f:
group = f[f"devices/{self.device_name}"]
with h5py.File(self.shot_file, "r") as file:
group = file[f"devices/{self.device_name}"]
if "START_COMMANDS" in group:
start_commands = group["START_COMMANDS"][:]
else:
Expand All @@ -44,8 +81,9 @@ def transition_to_buffered(self, device_name, h5_file, initial_values, fresh):
print(f"sending command: {repr(command)}")
self.connection.write(command)
# self.connection.flush()
# this command is written in Experiment.py, which is fetched here and actually written onto the arduino
# you will see this in the BLACS device tab. It's nothing but the string that we should send to the arduino
# this command is written in Experiment.py, which is fetched here and
# actually written onto the arduino you will see this in the BLACS device
# tab. It's nothing but the string that we should send to the arduino
# inorder to control the DDS

# This is expected by BLACS, we should return the final values that numerical
Expand Down Expand Up @@ -73,19 +111,26 @@ def transition_to_manual(self):
return True

def shutdown(self):
# Called when BLACS closes
"""Called when BLACS closes.
"""
self.connection.close()

def abort_buffered(self):
# Called when a shot is aborted. We may or may not want to run
# transition_to_manual in this case. If not, then this method should do whatever
# else it needs to, and then return True. It should make sure to clear any state
# were storing about this shot (e.g. it should set self.shot_file = None)
""" Called when a shot is aborted.

We may or may not want to run transition_to_manual in this case. If not,
then this method should do whatever else it needs to, and then return True.
It should make sure to clear any state were storing about this shot
(e.g. it should set self.shot_file = None)

Returns:
boolean: indicate that it was successful.
"""
return self.transition_to_manual()

def abort_transition_to_buffered(self):
# This is called if transition_to_buffered fails with an exception or returns
# False.
""" called if transition_to_buffered fails with an exception or returns False.
"""
# Forget the shot file:
self.shot_file = None
return True # Indicates success
18 changes: 10 additions & 8 deletions SynthHDDevice/labscript_devices.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
"""The module to access the SynthHD within the shots.

The SynthHD exposes the SynthHD by windfreak to labscript.
"""


import numpy as np
import h5py

Expand All @@ -12,6 +18,10 @@ class SynthHDDevice(Device):
# connection table, so that BLACS can read them:
@set_passed_properties({"connection_table_properties": ["com_port", "baud_rate"]})
def __init__(self, name, com_port="COM1", baud_rate=115200, **kwargs):
"""Initialize the device.

TODO: somehow baud_rate is never used.
"""
Device.__init__(self, name=name, parent_device=None, connection=None, **kwargs)
self.start_commands = []
# self.stop_commands = []
Expand All @@ -25,14 +35,6 @@ def add_start_command(self, command):
raise TypeError("command must be a bytestring")
self.start_commands.append(command)

'''
def add_stop_command(self, command):
"""Add a serial command that should be send at the end of the experiment"""
if not isinstance(command, bytes):
raise TypeError("command must be a bytestring")
self.stop_commands.append(command)
'''

def generate_code(self, hdf5_file):
# Convert the lists of commands into numpy arrays and save them to the shot file
# as HDF5 datasets within our device's group:
Expand Down
5 changes: 5 additions & 0 deletions SynthHDDevice/register_classes.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""Register the SynthHD to blacs.

This is boilerplate and should be only minimally changed.
"""

from labscript_devices import register_classes

register_classes(
Expand Down