Skip to content

Commit 37c7ea3

Browse files
committedJun 5, 2015
gui: TTL override support
1 parent 14cf244 commit 37c7ea3

File tree

3 files changed

+101
-25
lines changed

3 files changed

+101
-25
lines changed
 

Diff for: ‎artiq/gui/moninj.py

+79-22
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,18 @@
1313
logger = logging.getLogger(__name__)
1414

1515

16+
_mode_enc = {
17+
"exp": 0,
18+
"1": 1,
19+
"0": 2,
20+
"in": 3
21+
}
22+
23+
1624
class _TTLWidget(QtGui.QFrame):
17-
def __init__(self, force_out, name):
25+
def __init__(self, send_to_device, channel, force_out, name):
26+
self.send_to_device = send_to_device
27+
self.channel = channel
1828
self.force_out = force_out
1929

2030
QtGui.QFrame.__init__(self)
@@ -29,29 +39,72 @@ def __init__(self, force_out, name):
2939
grid.addWidget(label, 1, 1)
3040

3141
self._direction = QtGui.QLabel()
32-
self._value = QtGui.QLabel()
3342
self._direction.setAlignment(QtCore.Qt.AlignCenter)
34-
self._value.setAlignment(QtCore.Qt.AlignCenter)
35-
self.set_value(0, False, False)
3643
grid.addWidget(self._direction, 2, 1)
44+
self._value = QtGui.QLabel()
45+
self._value.setAlignment(QtCore.Qt.AlignCenter)
3746
grid.addWidget(self._value, 3, 1, 6, 1)
3847

48+
self._value.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
49+
menu = QtGui.QActionGroup(self._value)
50+
menu.setExclusive(True)
51+
self._expctl_action = QtGui.QAction("Experiment controlled", self._value)
52+
self._expctl_action.setCheckable(True)
53+
menu.addAction(self._expctl_action)
54+
self._value.addAction(self._expctl_action)
55+
self._expctl_action.triggered.connect(lambda: self.set_force("exp"))
56+
self._force1_action = QtGui.QAction("Force 1", self._value)
57+
self._force1_action.setCheckable(True)
58+
menu.addAction(self._force1_action)
59+
self._value.addAction(self._force1_action)
60+
self._force1_action.triggered.connect(lambda: self.set_force("1"))
61+
self._force0_action = QtGui.QAction("Force 0", self._value)
62+
self._force0_action.setCheckable(True)
63+
menu.addAction(self._force0_action)
64+
self._value.addAction(self._force0_action)
65+
self._force0_action.triggered.connect(lambda: self.set_force("0"))
66+
self._forcein_action = QtGui.QAction("Force input", self._value)
67+
self._forcein_action.setCheckable(True)
68+
self._forcein_action.setEnabled(not force_out)
69+
menu.addAction(self._forcein_action)
70+
self._value.addAction(self._forcein_action)
71+
self._forcein_action.triggered.connect(lambda: self.set_force("in"))
72+
73+
self.set_value(0, False, False)
74+
75+
def set_force(self, mode):
76+
data = struct.pack("bbb",
77+
2, # MONINJ_REQ_TTLSET
78+
self.channel, _mode_enc[mode])
79+
self.send_to_device(data)
80+
3981
def set_value(self, value, oe, override):
40-
value = "1" if value else "0"
82+
value_s = "1" if value else "0"
4183
if override:
42-
value = "<b>" + value + "</b>"
84+
value_s = "<b>" + value_s + "</b>"
4385
color = " color=\"red\""
4486
else:
4587
color = ""
4688
self._value.setText("<font size=\"9\"{}>{}</font>".format(
47-
color, value))
89+
color, value_s))
4890
oe = oe or self.force_out
4991
direction = "OUT" if oe else "IN"
5092
self._direction.setText("<font size=\"1\">" + direction + "</font>")
93+
if override:
94+
if oe:
95+
if value:
96+
self._force1_action.setChecked(True)
97+
else:
98+
self._force0_action.setChecked(True)
99+
else:
100+
self._forcein_action.setChecked(True)
101+
else:
102+
self._expctl_action.setChecked(True)
51103

52104

53105
class _DeviceManager:
54-
def __init__(self, init):
106+
def __init__(self, send_to_device, init):
107+
self.send_to_device = send_to_device
55108
self.ddb = dict()
56109
self.ttl_cb = lambda: None
57110
self.ttl_widgets = dict()
@@ -68,7 +121,8 @@ def __setitem__(self, k, v):
68121
if v["type"] == "local" and v["module"] == "artiq.coredevice.ttl":
69122
channel = v["arguments"]["channel"]
70123
force_out = v["class"] == "TTLOut"
71-
self.ttl_widgets[channel] = _TTLWidget(force_out, k)
124+
self.ttl_widgets[channel] = _TTLWidget(
125+
self.send_to_device, channel, force_out, k)
72126
self.ttl_cb()
73127
except KeyError:
74128
pass
@@ -92,7 +146,7 @@ def get_core_addr(self):
92146
class MonInjTTLDock(dockarea.Dock, TaskObject):
93147
def __init__(self):
94148
dockarea.Dock.__init__(self, "TTL", size=(1500, 500))
95-
self.dm = _DeviceManager(dict())
149+
self.dm = _DeviceManager(self.send_to_device, dict())
96150
self.transport = None
97151

98152
self.grid = QtGui.QGridLayout()
@@ -118,42 +172,45 @@ def connection_made(self, transport):
118172
self.transport = transport
119173

120174
def datagram_received(self, data, addr):
121-
ttl_levels, ttl_oes = struct.unpack(">QQ", data)
175+
ttl_levels, ttl_oes, ttl_overrides = struct.unpack(">QQQ", data)
122176
for channel, w in self.dm.ttl_widgets.items():
123177
w.set_value(ttl_levels & (1 << channel),
124178
ttl_oes & (1 << channel),
125-
False)
179+
ttl_overrides & (1 << channel))
126180

127181
def error_received(self, exc):
128182
logger.warning("datagram endpoint error")
129183

130184
def connection_lost(self, exc):
131185
self.transport = None
132186

187+
def send_to_device(self, data):
188+
ca = self.dm.get_core_addr()
189+
if ca is None:
190+
logger.warning("could not find core device address")
191+
elif self.transport is None:
192+
logger.warning("datagram endpoint not available")
193+
else:
194+
self.transport.sendto(data, (ca, 3250))
195+
133196
@asyncio.coroutine
134197
def _do(self):
135198
while True:
136199
yield from asyncio.sleep(0.2)
137-
ca = self.dm.get_core_addr()
138-
if ca is None:
139-
logger.warning("could not find core device address")
140-
elif self.transport is None:
141-
logger.warning("datagram endpoint not available")
142-
else:
143-
# MONINJ_REQ_MONITOR
144-
self.transport.sendto(b"\x01", (ca, 3250))
200+
# MONINJ_REQ_MONITOR
201+
self.send_to_device(b"\x01")
145202

146203
def layout_ttl_widgets(self):
147204
w = self.grid.itemAt(0)
148205
while w is not None:
149206
self.grid.removeItem(w)
150207
w = self.grid.itemAt(0)
151208
for i, (_, w) in enumerate(sorted(self.dm.ttl_widgets.items(),
152-
key=itemgetter(0))):
209+
key=itemgetter(0))):
153210
self.grid.addWidget(w, i // 4, i % 4)
154211

155212
def init_devices(self, d):
156-
self.dm = _DeviceManager(d)
213+
self.dm = _DeviceManager(self.send_to_device, d)
157214
self.dm.ttl_cb = self.layout_ttl_widgets
158215
self.layout_ttl_widgets()
159216
return self.dm

Diff for: ‎artiq/test/worker.py

-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ def _run_experiment(experiment):
5555

5656

5757
class WatchdogCase(unittest.TestCase):
58-
5958
def setUp(self):
6059
self.loop = asyncio.new_event_loop()
6160
asyncio.set_event_loop(self.loop)

Diff for: ‎soc/runtime/moninj.c

+22-2
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,20 @@
1616
#include "moninj.h"
1717

1818
enum {
19-
MONINJ_REQ_MONITOR = 1
19+
MONINJ_REQ_MONITOR = 1,
20+
MONINJ_REQ_TTLSET = 2
2021
};
2122

2223
static struct udp_pcb *listen_pcb;
2324

2425
struct monitor_reply {
2526
long long int ttl_levels;
2627
long long int ttl_oes;
28+
long long int ttl_overrides;
2729
};
2830

31+
static long long int ttl_overrides;
32+
2933
static void moninj_monitor(const ip_addr_t *addr, u16_t port)
3034
{
3135
struct monitor_reply reply;
@@ -43,6 +47,7 @@ static void moninj_monitor(const ip_addr_t *addr, u16_t port)
4347
if(rtio_mon_probe_value_read())
4448
reply.ttl_oes |= 1LL << i;
4549
}
50+
reply.ttl_overrides = ttl_overrides;
4651

4752
reply_p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct monitor_reply), PBUF_RAM);
4853
if(!reply_p) {
@@ -54,14 +59,29 @@ static void moninj_monitor(const ip_addr_t *addr, u16_t port)
5459
pbuf_free(reply_p);
5560
}
5661

62+
static void moninj_ttlset(int channel, int mode)
63+
{
64+
if(mode)
65+
ttl_overrides |= (1LL << channel);
66+
else
67+
ttl_overrides &= ~(1LL << channel);
68+
}
69+
5770
static void moninj_recv(void *arg, struct udp_pcb *upcb, struct pbuf *req,
5871
const ip_addr_t *addr, u16_t port)
5972
{
73+
char *p = (char *)req->payload;
74+
6075
if(req->len >= 1) {
61-
switch(*(char *)req->payload) {
76+
switch(p[0]) {
6277
case MONINJ_REQ_MONITOR:
6378
moninj_monitor(addr, port);
6479
break;
80+
case MONINJ_REQ_TTLSET:
81+
if(req->len < 3)
82+
break;
83+
moninj_ttlset(p[1], p[2]);
84+
break;
6585
default:
6686
break;
6787
}

0 commit comments

Comments
 (0)
Please sign in to comment.