gui: DDS monitor/injection (WIP)

This commit is contained in:
Sebastien Bourdeauducq 2015-06-12 17:41:04 +08:00
parent f84c51fed5
commit 86fbe38371
2 changed files with 131 additions and 53 deletions

View File

@ -11,9 +11,8 @@ from pyqtgraph import dockarea
from artiq.protocols.file_db import FlatFileDB from artiq.protocols.file_db import FlatFileDB
from artiq.protocols.pc_rpc import AsyncioClient from artiq.protocols.pc_rpc import AsyncioClient
from artiq.protocols.sync_struct import Subscriber
from artiq.gui.explorer import ExplorerDock from artiq.gui.explorer import ExplorerDock
from artiq.gui.moninj import MonInjTTLDock, MonInjDDSDock from artiq.gui.moninj import MonInj
from artiq.gui.parameters import ParametersDock from artiq.gui.parameters import ParametersDock
from artiq.gui.schedule import ScheduleDock from artiq.gui.schedule import ScheduleDock
from artiq.gui.log import LogDock from artiq.gui.log import LogDock
@ -65,20 +64,12 @@ def main():
args.server, args.port_notify)) args.server, args.port_notify))
atexit.register(lambda: loop.run_until_complete(d_explorer.sub_close())) atexit.register(lambda: loop.run_until_complete(d_explorer.sub_close()))
d_ttl = MonInjTTLDock() d_ttl_dds = MonInj()
loop.run_until_complete(d_ttl.start()) loop.run_until_complete(d_ttl_dds.start(args.server, args.port_notify))
atexit.register(lambda: loop.run_until_complete(d_ttl.stop())) atexit.register(lambda: loop.run_until_complete(d_ttl_dds.stop()))
d_dds = MonInjDDSDock() area.addDock(d_ttl_dds.dds_dock, "top")
devices_sub = Subscriber("devices", area.addDock(d_ttl_dds.ttl_dock, "above", d_ttl_dds.dds_dock)
[d_ttl.init_devices, d_dds.init_devices]) area.addDock(d_explorer, "above", d_ttl_dds.ttl_dock)
loop.run_until_complete(
devices_sub.connect(args.server, args.port_notify))
atexit.register(
lambda: loop.run_until_complete(devices_sub.close()))
area.addDock(d_dds, "top")
area.addDock(d_ttl, "above", d_dds)
area.addDock(d_explorer, "above", d_ttl)
d_params = ParametersDock() d_params = ParametersDock()
area.addDock(d_params, "right", d_explorer) area.addDock(d_params, "right", d_explorer)

View File

@ -8,6 +8,7 @@ from quamash import QtGui, QtCore
from pyqtgraph import dockarea from pyqtgraph import dockarea
from artiq.tools import TaskObject from artiq.tools import TaskObject
from artiq.protocols.sync_struct import Subscriber
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -55,27 +56,30 @@ class _TTLWidget(QtGui.QFrame):
self._expctl_action.setCheckable(True) self._expctl_action.setCheckable(True)
menu.addAction(self._expctl_action) menu.addAction(self._expctl_action)
self._value.addAction(self._expctl_action) self._value.addAction(self._expctl_action)
self._expctl_action.triggered.connect(lambda: self.set_force("exp")) self._expctl_action.triggered.connect(lambda: self.set_mode("exp"))
separator = QtGui.QAction(self._value)
separator.setSeparator(True)
self._value.addAction(separator)
self._force1_action = QtGui.QAction("Force 1", self._value) self._force1_action = QtGui.QAction("Force 1", self._value)
self._force1_action.setCheckable(True) self._force1_action.setCheckable(True)
menu.addAction(self._force1_action) menu.addAction(self._force1_action)
self._value.addAction(self._force1_action) self._value.addAction(self._force1_action)
self._force1_action.triggered.connect(lambda: self.set_force("1")) self._force1_action.triggered.connect(lambda: self.set_mode("1"))
self._force0_action = QtGui.QAction("Force 0", self._value) self._force0_action = QtGui.QAction("Force 0", self._value)
self._force0_action.setCheckable(True) self._force0_action.setCheckable(True)
menu.addAction(self._force0_action) menu.addAction(self._force0_action)
self._value.addAction(self._force0_action) self._value.addAction(self._force0_action)
self._force0_action.triggered.connect(lambda: self.set_force("0")) self._force0_action.triggered.connect(lambda: self.set_mode("0"))
self._forcein_action = QtGui.QAction("Force input", self._value) self._forcein_action = QtGui.QAction("Force input", self._value)
self._forcein_action.setCheckable(True) self._forcein_action.setCheckable(True)
self._forcein_action.setEnabled(not force_out) self._forcein_action.setEnabled(not force_out)
menu.addAction(self._forcein_action) menu.addAction(self._forcein_action)
self._value.addAction(self._forcein_action) self._value.addAction(self._forcein_action)
self._forcein_action.triggered.connect(lambda: self.set_force("in")) self._forcein_action.triggered.connect(lambda: self.set_mode("in"))
self.set_value(0, False, False) self.set_value(0, False, False)
def set_force(self, mode): def set_mode(self, mode):
data = struct.pack("bbb", data = struct.pack("bbb",
2, # MONINJ_REQ_TTLSET 2, # MONINJ_REQ_TTLSET
self.channel, _mode_enc[mode]) self.channel, _mode_enc[mode])
@ -107,12 +111,75 @@ class _TTLWidget(QtGui.QFrame):
self._expctl_action.setChecked(True) self._expctl_action.setChecked(True)
class _DDSWidget(QtGui.QFrame):
def __init__(self, send_to_device, channel, name):
self.send_to_device = send_to_device
self.channel = channel
self.name = name
QtGui.QFrame.__init__(self)
self.setFrameShape(QtGui.QFrame.Panel)
self.setFrameShadow(QtGui.QFrame.Raised)
grid = QtGui.QGridLayout()
self.setLayout(grid)
label = QtGui.QLabel(name)
label.setAlignment(QtCore.Qt.AlignCenter)
grid.addWidget(label, 1, 1)
self._override = QtGui.QLabel()
self._override.setAlignment(QtCore.Qt.AlignCenter)
grid.addWidget(self._override, 2, 1)
self._value = QtGui.QLabel()
self._value.setAlignment(QtCore.Qt.AlignCenter)
grid.addWidget(self._value, 3, 1, 6, 1)
self._value.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
self._override_action = QtGui.QAction("Override", self._value)
self._override_action.setCheckable(True)
self._value.addAction(self._override_action)
self._override_action.triggered.connect(self._override_clicked)
self.set_value(0.0, False)
def _override_clicked(self):
override_en = self._override_action.isChecked()
if override_en:
frequency, ok = QtGui.QInputDialog.getDouble(
None, "DDS override",
"Frequency in MHz for {}:".format(self.name),
value=self._frequency, min=0, decimals=3)
self._override_action.setChecked(ok)
if ok:
print("override set to", frequency)
else:
print("override disabled")
def set_value(self, frequency, override):
self._frequency = frequency
self._override_action.setChecked(override)
value_s = "{:.3f} MHz".format(frequency)
if override:
value_s = "<b>" + value_s + "</b>"
color = " color=\"red\""
self._override.setText("<font size=\"1\" color=\"red\">OVERRIDE</font>")
else:
color = ""
self._override.setText("")
self._value.setText("<font size=\"9\"{}>{}</font>"
.format(color, value_s))
class _DeviceManager: class _DeviceManager:
def __init__(self, send_to_device, init): def __init__(self, send_to_device, init):
self.send_to_device = send_to_device self.send_to_device = send_to_device
self.ddb = dict() self.ddb = dict()
self.ttl_cb = lambda: None self.ttl_cb = lambda: None
self.ttl_widgets = dict() self.ttl_widgets = dict()
self.dds_cb = lambda: None
self.dds_widgets = dict()
for k, v in init.items(): for k, v in init.items():
self[k] = v self[k] = v
@ -123,12 +190,19 @@ class _DeviceManager:
if not isinstance(v, dict): if not isinstance(v, dict):
return return
try: try:
if v["type"] == "local" and v["module"] == "artiq.coredevice.ttl": if v["type"] == "local":
if v["module"] == "artiq.coredevice.ttl":
channel = v["arguments"]["channel"] channel = v["arguments"]["channel"]
force_out = v["class"] == "TTLOut" force_out = v["class"] == "TTLOut"
self.ttl_widgets[channel] = _TTLWidget( self.ttl_widgets[channel] = _TTLWidget(
self.send_to_device, channel, force_out, k) self.send_to_device, channel, force_out, k)
self.ttl_cb() self.ttl_cb()
if (v["module"] == "artiq.coredevice.dds"
and v["class"] == "DDS"):
channel = v["arguments"]["channel"]
self.dds_widgets[channel] = _DDSWidget(
self.send_to_device, channel, k)
self.dds_cb()
except KeyError: except KeyError:
pass pass
@ -148,27 +222,53 @@ class _DeviceManager:
return None return None
class MonInjTTLDock(dockarea.Dock, TaskObject): class _MonInjDock(dockarea.Dock):
def __init__(self): def __init__(self, name):
dockarea.Dock.__init__(self, "TTL", size=(1500, 500)) dockarea.Dock.__init__(self, name, size=(1500, 500))
self.dm = _DeviceManager(self.send_to_device, dict())
self.transport = None
self.grid = QtGui.QGridLayout() self.grid = QtGui.QGridLayout()
gridw = QtGui.QWidget() gridw = QtGui.QWidget()
gridw.setLayout(self.grid) gridw.setLayout(self.grid)
self.addWidget(gridw) self.addWidget(gridw)
def layout_widgets(self, widgets):
w = self.grid.itemAt(0)
while w is not None:
self.grid.removeItem(w)
w = self.grid.itemAt(0)
for i, (_, w) in enumerate(sorted(widgets, key=itemgetter(0))):
self.grid.addWidget(w, i // 4, i % 4)
class MonInj(TaskObject):
def __init__(self):
self.ttl_dock = _MonInjDock("TTL")
self.dds_dock = _MonInjDock("DDS")
self.subscriber = Subscriber("devices", self.init_devices)
self.dm = _DeviceManager(self.send_to_device, dict())
self.transport = None
@asyncio.coroutine @asyncio.coroutine
def start(self): def start(self, server, port):
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
yield from loop.create_datagram_endpoint(lambda: self, yield from loop.create_datagram_endpoint(lambda: self,
family=socket.AF_INET) family=socket.AF_INET)
try:
yield from self.subscriber.connect(server, port)
try:
TaskObject.start(self) TaskObject.start(self)
except:
yield from self.subscriber.close()
raise
except:
self.transport.close()
raise
@asyncio.coroutine @asyncio.coroutine
def stop(self): def stop(self):
yield from TaskObject.stop(self) yield from TaskObject.stop(self)
yield from self.subscriber.close()
if self.transport is not None: if self.transport is not None:
self.transport.close() self.transport.close()
self.transport = None self.transport = None
@ -205,25 +305,12 @@ class MonInjTTLDock(dockarea.Dock, TaskObject):
# MONINJ_REQ_MONITOR # MONINJ_REQ_MONITOR
self.send_to_device(b"\x01") self.send_to_device(b"\x01")
def layout_ttl_widgets(self):
w = self.grid.itemAt(0)
while w is not None:
self.grid.removeItem(w)
w = self.grid.itemAt(0)
for i, (_, w) in enumerate(sorted(self.dm.ttl_widgets.items(),
key=itemgetter(0))):
self.grid.addWidget(w, i // 4, i % 4)
def init_devices(self, d): def init_devices(self, d):
self.dm = _DeviceManager(self.send_to_device, d) self.dm = _DeviceManager(self.send_to_device, d)
self.dm.ttl_cb = self.layout_ttl_widgets self.dm.ttl_cb = lambda: self.ttl_dock.layout_widgets(
self.layout_ttl_widgets() self.dm.ttl_widgets.items())
self.dm.dds_cb = lambda: self.dds_dock.layout_widgets(
self.dm.dds_widgets.items())
self.dm.ttl_cb()
self.dm.dds_cb()
return self.dm return self.dm
class MonInjDDSDock(dockarea.Dock):
def __init__(self):
dockarea.Dock.__init__(self, "DDS", size=(1500, 500))
def init_devices(self, d):
return d