Skip to content

Commit 86fbe38

Browse files
committedJun 12, 2015
gui: DDS monitor/injection (WIP)
1 parent f84c51f commit 86fbe38

File tree

2 files changed

+131
-53
lines changed

2 files changed

+131
-53
lines changed
 

‎artiq/frontend/artiq_gui.py

+7-16
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111

1212
from artiq.protocols.file_db import FlatFileDB
1313
from artiq.protocols.pc_rpc import AsyncioClient
14-
from artiq.protocols.sync_struct import Subscriber
1514
from artiq.gui.explorer import ExplorerDock
16-
from artiq.gui.moninj import MonInjTTLDock, MonInjDDSDock
15+
from artiq.gui.moninj import MonInj
1716
from artiq.gui.parameters import ParametersDock
1817
from artiq.gui.schedule import ScheduleDock
1918
from artiq.gui.log import LogDock
@@ -65,20 +64,12 @@ def main():
6564
args.server, args.port_notify))
6665
atexit.register(lambda: loop.run_until_complete(d_explorer.sub_close()))
6766

68-
d_ttl = MonInjTTLDock()
69-
loop.run_until_complete(d_ttl.start())
70-
atexit.register(lambda: loop.run_until_complete(d_ttl.stop()))
71-
d_dds = MonInjDDSDock()
72-
devices_sub = Subscriber("devices",
73-
[d_ttl.init_devices, d_dds.init_devices])
74-
loop.run_until_complete(
75-
devices_sub.connect(args.server, args.port_notify))
76-
atexit.register(
77-
lambda: loop.run_until_complete(devices_sub.close()))
78-
79-
area.addDock(d_dds, "top")
80-
area.addDock(d_ttl, "above", d_dds)
81-
area.addDock(d_explorer, "above", d_ttl)
67+
d_ttl_dds = MonInj()
68+
loop.run_until_complete(d_ttl_dds.start(args.server, args.port_notify))
69+
atexit.register(lambda: loop.run_until_complete(d_ttl_dds.stop()))
70+
area.addDock(d_ttl_dds.dds_dock, "top")
71+
area.addDock(d_ttl_dds.ttl_dock, "above", d_ttl_dds.dds_dock)
72+
area.addDock(d_explorer, "above", d_ttl_dds.ttl_dock)
8273

8374
d_params = ParametersDock()
8475
area.addDock(d_params, "right", d_explorer)

‎artiq/gui/moninj.py

+124-37
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from pyqtgraph import dockarea
99

1010
from artiq.tools import TaskObject
11+
from artiq.protocols.sync_struct import Subscriber
1112

1213

1314
logger = logging.getLogger(__name__)
@@ -55,27 +56,30 @@ def __init__(self, send_to_device, channel, force_out, name):
5556
self._expctl_action.setCheckable(True)
5657
menu.addAction(self._expctl_action)
5758
self._value.addAction(self._expctl_action)
58-
self._expctl_action.triggered.connect(lambda: self.set_force("exp"))
59+
self._expctl_action.triggered.connect(lambda: self.set_mode("exp"))
60+
separator = QtGui.QAction(self._value)
61+
separator.setSeparator(True)
62+
self._value.addAction(separator)
5963
self._force1_action = QtGui.QAction("Force 1", self._value)
6064
self._force1_action.setCheckable(True)
6165
menu.addAction(self._force1_action)
6266
self._value.addAction(self._force1_action)
63-
self._force1_action.triggered.connect(lambda: self.set_force("1"))
67+
self._force1_action.triggered.connect(lambda: self.set_mode("1"))
6468
self._force0_action = QtGui.QAction("Force 0", self._value)
6569
self._force0_action.setCheckable(True)
6670
menu.addAction(self._force0_action)
6771
self._value.addAction(self._force0_action)
68-
self._force0_action.triggered.connect(lambda: self.set_force("0"))
72+
self._force0_action.triggered.connect(lambda: self.set_mode("0"))
6973
self._forcein_action = QtGui.QAction("Force input", self._value)
7074
self._forcein_action.setCheckable(True)
7175
self._forcein_action.setEnabled(not force_out)
7276
menu.addAction(self._forcein_action)
7377
self._value.addAction(self._forcein_action)
74-
self._forcein_action.triggered.connect(lambda: self.set_force("in"))
78+
self._forcein_action.triggered.connect(lambda: self.set_mode("in"))
7579

7680
self.set_value(0, False, False)
7781

78-
def set_force(self, mode):
82+
def set_mode(self, mode):
7983
data = struct.pack("bbb",
8084
2, # MONINJ_REQ_TTLSET
8185
self.channel, _mode_enc[mode])
@@ -107,12 +111,75 @@ def set_value(self, value, oe, override):
107111
self._expctl_action.setChecked(True)
108112

109113

114+
class _DDSWidget(QtGui.QFrame):
115+
def __init__(self, send_to_device, channel, name):
116+
self.send_to_device = send_to_device
117+
self.channel = channel
118+
self.name = name
119+
120+
QtGui.QFrame.__init__(self)
121+
122+
self.setFrameShape(QtGui.QFrame.Panel)
123+
self.setFrameShadow(QtGui.QFrame.Raised)
124+
125+
grid = QtGui.QGridLayout()
126+
self.setLayout(grid)
127+
label = QtGui.QLabel(name)
128+
label.setAlignment(QtCore.Qt.AlignCenter)
129+
grid.addWidget(label, 1, 1)
130+
131+
self._override = QtGui.QLabel()
132+
self._override.setAlignment(QtCore.Qt.AlignCenter)
133+
grid.addWidget(self._override, 2, 1)
134+
135+
self._value = QtGui.QLabel()
136+
self._value.setAlignment(QtCore.Qt.AlignCenter)
137+
grid.addWidget(self._value, 3, 1, 6, 1)
138+
139+
self._value.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
140+
self._override_action = QtGui.QAction("Override", self._value)
141+
self._override_action.setCheckable(True)
142+
self._value.addAction(self._override_action)
143+
self._override_action.triggered.connect(self._override_clicked)
144+
145+
self.set_value(0.0, False)
146+
147+
def _override_clicked(self):
148+
override_en = self._override_action.isChecked()
149+
if override_en:
150+
frequency, ok = QtGui.QInputDialog.getDouble(
151+
None, "DDS override",
152+
"Frequency in MHz for {}:".format(self.name),
153+
value=self._frequency, min=0, decimals=3)
154+
self._override_action.setChecked(ok)
155+
if ok:
156+
print("override set to", frequency)
157+
else:
158+
print("override disabled")
159+
160+
def set_value(self, frequency, override):
161+
self._frequency = frequency
162+
self._override_action.setChecked(override)
163+
value_s = "{:.3f} MHz".format(frequency)
164+
if override:
165+
value_s = "<b>" + value_s + "</b>"
166+
color = " color=\"red\""
167+
self._override.setText("<font size=\"1\" color=\"red\">OVERRIDE</font>")
168+
else:
169+
color = ""
170+
self._override.setText("")
171+
self._value.setText("<font size=\"9\"{}>{}</font>"
172+
.format(color, value_s))
173+
174+
110175
class _DeviceManager:
111176
def __init__(self, send_to_device, init):
112177
self.send_to_device = send_to_device
113178
self.ddb = dict()
114179
self.ttl_cb = lambda: None
115180
self.ttl_widgets = dict()
181+
self.dds_cb = lambda: None
182+
self.dds_widgets = dict()
116183
for k, v in init.items():
117184
self[k] = v
118185

@@ -123,12 +190,19 @@ def __setitem__(self, k, v):
123190
if not isinstance(v, dict):
124191
return
125192
try:
126-
if v["type"] == "local" and v["module"] == "artiq.coredevice.ttl":
127-
channel = v["arguments"]["channel"]
128-
force_out = v["class"] == "TTLOut"
129-
self.ttl_widgets[channel] = _TTLWidget(
130-
self.send_to_device, channel, force_out, k)
131-
self.ttl_cb()
193+
if v["type"] == "local":
194+
if v["module"] == "artiq.coredevice.ttl":
195+
channel = v["arguments"]["channel"]
196+
force_out = v["class"] == "TTLOut"
197+
self.ttl_widgets[channel] = _TTLWidget(
198+
self.send_to_device, channel, force_out, k)
199+
self.ttl_cb()
200+
if (v["module"] == "artiq.coredevice.dds"
201+
and v["class"] == "DDS"):
202+
channel = v["arguments"]["channel"]
203+
self.dds_widgets[channel] = _DDSWidget(
204+
self.send_to_device, channel, k)
205+
self.dds_cb()
132206
except KeyError:
133207
pass
134208

@@ -148,27 +222,53 @@ def get_core_addr(self):
148222
return None
149223

150224

151-
class MonInjTTLDock(dockarea.Dock, TaskObject):
152-
def __init__(self):
153-
dockarea.Dock.__init__(self, "TTL", size=(1500, 500))
154-
self.dm = _DeviceManager(self.send_to_device, dict())
155-
self.transport = None
225+
class _MonInjDock(dockarea.Dock):
226+
def __init__(self, name):
227+
dockarea.Dock.__init__(self, name, size=(1500, 500))
156228

157229
self.grid = QtGui.QGridLayout()
158230
gridw = QtGui.QWidget()
159231
gridw.setLayout(self.grid)
160232
self.addWidget(gridw)
161233

234+
def layout_widgets(self, widgets):
235+
w = self.grid.itemAt(0)
236+
while w is not None:
237+
self.grid.removeItem(w)
238+
w = self.grid.itemAt(0)
239+
for i, (_, w) in enumerate(sorted(widgets, key=itemgetter(0))):
240+
self.grid.addWidget(w, i // 4, i % 4)
241+
242+
243+
class MonInj(TaskObject):
244+
def __init__(self):
245+
self.ttl_dock = _MonInjDock("TTL")
246+
self.dds_dock = _MonInjDock("DDS")
247+
248+
self.subscriber = Subscriber("devices", self.init_devices)
249+
self.dm = _DeviceManager(self.send_to_device, dict())
250+
self.transport = None
251+
162252
@asyncio.coroutine
163-
def start(self):
253+
def start(self, server, port):
164254
loop = asyncio.get_event_loop()
165255
yield from loop.create_datagram_endpoint(lambda: self,
166256
family=socket.AF_INET)
167-
TaskObject.start(self)
257+
try:
258+
yield from self.subscriber.connect(server, port)
259+
try:
260+
TaskObject.start(self)
261+
except:
262+
yield from self.subscriber.close()
263+
raise
264+
except:
265+
self.transport.close()
266+
raise
168267

169268
@asyncio.coroutine
170269
def stop(self):
171270
yield from TaskObject.stop(self)
271+
yield from self.subscriber.close()
172272
if self.transport is not None:
173273
self.transport.close()
174274
self.transport = None
@@ -205,25 +305,12 @@ def _do(self):
205305
# MONINJ_REQ_MONITOR
206306
self.send_to_device(b"\x01")
207307

208-
def layout_ttl_widgets(self):
209-
w = self.grid.itemAt(0)
210-
while w is not None:
211-
self.grid.removeItem(w)
212-
w = self.grid.itemAt(0)
213-
for i, (_, w) in enumerate(sorted(self.dm.ttl_widgets.items(),
214-
key=itemgetter(0))):
215-
self.grid.addWidget(w, i // 4, i % 4)
216-
217308
def init_devices(self, d):
218309
self.dm = _DeviceManager(self.send_to_device, d)
219-
self.dm.ttl_cb = self.layout_ttl_widgets
220-
self.layout_ttl_widgets()
310+
self.dm.ttl_cb = lambda: self.ttl_dock.layout_widgets(
311+
self.dm.ttl_widgets.items())
312+
self.dm.dds_cb = lambda: self.dds_dock.layout_widgets(
313+
self.dm.dds_widgets.items())
314+
self.dm.ttl_cb()
315+
self.dm.dds_cb()
221316
return self.dm
222-
223-
224-
class MonInjDDSDock(dockarea.Dock):
225-
def __init__(self):
226-
dockarea.Dock.__init__(self, "DDS", size=(1500, 500))
227-
228-
def init_devices(self, d):
229-
return d

0 commit comments

Comments
 (0)
Please sign in to comment.