Skip to content
Snippets Groups Projects
Commit 891e59ad authored by whooie's avatar whooie
Browse files

move all the stuff for rtcontrol into a submodule

parent 5341c27e
No related branches found
No related tags found
No related merge requests found
from __future__ import annotations
from lib.system import MAIN
from lib.ew import EventType
import lib.rtcontrol.parser as parser
import cmd
import readline
import getopt
import sys
def set_digital_state(state_args: list[tuple[int, int, int]]):
for connector, mask, state in state_args:
MAIN.default(EventType.Digital, c=connector, m=mask, s=state)
def set_analog_state(state_args: list[tuple[int, float]]):
for channel, state in state_args:
MAIN.default(EventType.Analog, ch=channel, s=state)
def set_zero(zero_type: tuple[bool, bool]):
if zero_type[0]:
MAIN.zero(EventType.Digital)
if zero_type[1]:
MAIN.zero(EventType.Analog)
helptext = """
Simple script to set the output state managed by the EntangleWare backend.
Usage:
rtcontrol [ options ]
rtcontrol [ command ]
Options:
-i, --interactive
Run the script in interactive mode. See the `help` command in this mode
for more information.
-h, --help
Print this text and exit.
Commands:
help [ command [ ... ] ]
Print usage information for the supplied command(s) or this text if none
are supplied, and exit.
digital <args>
Set the digital output state of the computer. See `help digital` for
more information.
analog <args>
Set the analog output state of the computer. See `help analog` for more
information.
zero <args>
Set all outputs of the given type(s) to be zero. See `help zero` for
more information.
"""[1:-1]
def print_help(arg: str):
cmds = arg.split(" ")
if cmds[0] == "":
print(helptext)
else:
for cmd in cmds:
if cmd == "digital":
print("Command `digital`")
print("=================")
print(RTControl.do_digital.__doc__[1:-1])
elif cmd == "analog":
print("Command `analog`")
print("================")
print(RTControl.do_analog.__doc__[1:-1])
elif cmd == "zero":
print("Command `zero`")
print("==============")
print(RTControl.do_zero.__doc__[1:-1])
class RTControl(cmd.Cmd):
intro = """
Welcome to the real-time EntangleWare control interface.
Type 'help' or '?' list available commands.
"""[1:-1]
prompt = "<EW> "
def do_digital(self, arg):
"""
Set the digital output state.
Usage:
digital <connector> <channel> <state>
Args:
connector : <int>[/<int>...]
Number(s) of the connector(s) whose state is to be set. To specify
multiple connectors, separate numbers by a slash ('/'). Connector
numbers must be 0-3.
channel : <int>[,<int>][/<int>,...]
Number(s) of the channel(s) whose state is to be set. To specify
multiple channels, separate channel numbers on the same connector by a
comma (',') and those on other connectors by a slash ('/'). The number
of slashes must equal that in the previous argument. Channel numbers
must be 0-31.
state : <0|1>[,<0|1>][/<0|1>,...]
HIGH/LOW state of the channel(s) to be set. To specify the states of
multiple channels, follow the same rules as those for <channel>. A state
must be specified for every channel number in the previous arg. States
must be 0 (LOW) or 1 (HIGH).
"""
try:
state_args = parser.parse_digital_state(arg)
except Exception as err:
print(err)
set_digital_state(state_args)
def do_analog(self, arg):
"""
Set the analog output state.
Usage:
analog <channel> <state>
Args:
channel : <int>[,<int>...]
Number(s) of the channel(s) whose state is to be set. To specify
multiple channels, separate channel numbers by a comma (','). Channel
numbers must be 0-31.
state : <float>[,<float>...]
Output states of the channel(s) to be set. To specify the states of
multiple channels, separate numbers by a comma (','). States must be in
the range [-10.0, +10.0].
"""
try:
state_args = parser.parse_analog_state(arg)
except Exception as err:
print(err)
set_analog_state(state_args)
def do_zero(self, arg):
"""
Set all channels of the given type to be zero.
Usage:
zero <type>
Args:
type : <str>
Type of the channels whose states are to be set to zero. Must be one of
{'digital', 'analog', 'all'}.
"""
try:
zero_type = parser.parse_zero(arg)
except Exception as err:
print(err)
set_zero(zero_type)
def do_quit(self, arg):
"""
Disconnect and quit.
"""
if MAIN._connected:
MAIN.disconnect()
return True
def main(script_args):
shortopts = "hi"
longopts = [
"help",
"interactive",
]
try:
opts, args = getopt.gnu_getopt(script_args, shortopts, longopts)
for opt, optarg in opts:
if opt in {"-h", "--help"}:
print(helptext)
sys.exit(0)
elif opt in {"-i", "--interactive"}:
MAIN.connect()
RTControl().cmdloop()
sys.exit(0)
assert len(args) >= 1, "Must provide a command"
cmd_args = " ".join(args[1:])
if args[0] == "help":
print_help(cmd_args)
elif args[0] == "digital":
MAIN.connect()
set_digital_state(parser.parse_digital_state(cmd_args))
MAIN.disconnect()
elif args[0] == "analog":
MAIN.connect()
set_analog_state(parser.parse_analog_state(cmd_args))
MAIN.disconnect()
elif args[0] == "zero":
MAIN.connect()
set_zero(parser.parse_zero(cmd_args))
MAIN.disconnect()
elif args[0] == "alldefaults":
system.set_defaults()
else:
print(helptext)
sys.exit(1)
sys.exit(0)
except Exception as ERR:
print(ERR)
if MAIN._connected:
MAIN.disconnect()
sys.exit(1)
from __future__ import annotations
from lib.system import MAIN
from lib.ew import EventType
CONNECTOR_D_RANGE = range(MAIN.num_connectors_d)
CHANNEL_D_RANGE = range(MAIN.num_channels_d)
STATE_D_RANGE = range(2)
CHANNEL_A_RANGE = range(MAIN.num_channels_a)
STATE_A_RANGE = (MAIN.Vmin, MAIN.Vmax)
def parse_digital_state(arg: str):
items = arg.split(' ')
while '' in items:
items.remove('')
assert len(items) == 3, \
"Command accepts exactly three arguments"
connectors = [int(c) for c in items[0].split('/')]
assert all(c in CONNECTOR_D_RANGE for c in connectors), \
"Invalid connector number"
channels = [[int(ch) for ch in CH.split(',')] for CH in items[1].split('/')]
assert len(channels) == len(connectors), \
"Channel specification does not match connector specification"
assert all(all(ch in CHANNEL_D_RANGE for ch in CH) for CH in channels), \
"Invalid channel specified"
states = [[int(s) for s in S.split(',')] for S in items[2].split('/')]
assert all(len(S) == len(CH) for S, CH in zip(states, channels)), \
"Channel state specification does not match channel specification"
assert all(all(s in STATE_D_RANGE for s in S) for S in states), \
"Invalid channel state specified"
state_args = [
(
C,
sum(2**ch for ch in CH),
sum(s * 2**ch for s, ch in zip(S, CH))
)
for C, CH, S in zip(connectors, channels, states)
]
return state_args
def parse_analog_state(arg: str):
items = arg.split(' ')
while '' in items:
items.remove('')
assert len(items) == 2, \
"Command accepts exactly two arguments"
channels = [int(ch) for ch in items[0].split(',')]
assert all(ch in CHANNEL_A_RANGE for ch in channels), \
"Invalid channel specified"
states = [float(s) for s in items[1].split(',')]
assert len(states) == len(channels), \
"Channel state specification does not match channel specification"
assert all(s >= STATE_A_RANGE[0] and s <= STATE_A_RANGE[1] for s in states), \
"Invalid channel state specified"
state_args = list(zip(channels, states))
return state_args
def parse_zero(arg: str):
items = arg.split(' ')
while '' in items:
items.remove('')
assert len(items) == 1, \
"Command accepts exactly one argument"
if items[0].lower() == "digital":
return (True, False)
elif items[0].lower() == "analog":
return (False, True)
elif items[0].lower() == "all":
return (True, True)
from __future__ import annotations import lib.rtcontrol.driver, sys
from lib import EventType, MAIN lib.rtcontrol.driver.main(sys.argv[1:])
import cmd
import readline
import getopt
import sys
CONNECTOR_D_RANGE = range(MAIN.num_connectors_d)
CHANNEL_D_RANGE = range(MAIN.num_channels_d)
STATE_D_RANGE = range(2)
CHANNEL_A_RANGE = range(MAIN.num_channels_a)
STATE_A_RANGE = (MAIN.Vmin, MAIN.Vmax)
def parse_digital_state(arg: str):
items = arg.split(' ')
while '' in items:
items.remove('')
assert len(items) == 3, \
"Command accepts exactly three arguments"
connectors = [int(c) for c in items[0].split('/')]
assert all(c in CONNECTOR_D_RANGE for c in connectors), \
"Invalid connector number"
channels = [[int(ch) for ch in CH.split(',')] for CH in items[1].split('/')]
assert len(channels) == len(connectors), \
"Channel specification does not match connector specification"
assert all(all(ch in CHANNEL_D_RANGE for ch in CH) for CH in channels), \
"Invalid channel specified"
states = [[int(s) for s in S.split(',')] for S in items[2].split('/')]
assert all(len(S) == len(CH) for S, CH in zip(states, channels)), \
"Channel state specification does not match channel specification"
assert all(all(s in STATE_D_RANGE for s in S) for S in states), \
"Invalid channel state specified"
state_args = [
(
C,
sum(2**ch for ch in CH),
sum(s * 2**ch for s, ch in zip(S, CH))
)
for C, CH, S in zip(connectors, channels, states)
]
return state_args
def set_digital_state(state_args: list[tuple[int, int, int]]):
for connector, mask, state in state_args:
MAIN.default(EventType.Digital, c=connector, m=mask, s=state)
def parse_analog_state(arg: str):
items = arg.split(' ')
while '' in items:
items.remove('')
assert len(items) == 2, \
"Command accepts exactly two arguments"
channels = [int(ch) for ch in items[0].split(',')]
assert all(ch in CHANNEL_A_RANGE for ch in channels), \
"Invalid channel specified"
states = [float(s) for s in items[1].split(',')]
assert len(states) == len(channels), \
"Channel state specification does not match channel specification"
assert all(s >= STATE_A_RANGE[0] and s <= STATE_A_RANGE[1] for s in states), \
"Invalid channel state specified"
state_args = list(zip(channels, states))
return state_args
def set_analog_state(state_args: list[tuple[int, float]]):
for channel, state in state_args:
MAIN.default(EventType.Analog, ch=channel, s=state)
def parse_zero(arg: str):
items = arg.split(' ')
while '' in items:
items.remove('')
assert len(items) == 1, \
"Command accepts exactly one argument"
if items[0].lower() == "digital":
return (True, False)
elif items[0].lower() == "analog":
return (False, True)
elif items[0].lower() == "all":
return (True, True)
def set_zero(zero_type: tuple[bool, bool]):
if zero_type[0]:
MAIN.zero(EventType.Digital)
if zero_type[1]:
MAIN.zero(EventType.Analog)
helptext = """
Simple script to set the output state managed by the EntangleWare backend.
Usage:
rtcontrol [ options ]
rtcontrol [ command ]
Options:
-i, --interactive
Run the script in interactive mode. See the `help` command in this mode
for more information.
-h, --help
Print this text and exit.
Commands:
help [ command [ ... ] ]
Print usage information for the supplied command(s) or this text if none
are supplied, and exit.
digital <args>
Set the digital output state of the computer. See `help digital` for
more information.
analog <args>
Set the analog output state of the computer. See `help analog` for more
information.
zero <args>
Set all outputs of the given type(s) to be zero. See `help zero` for
more information.
"""[1:-1]
def print_help(arg: str):
cmds = arg.split(" ")
if cmds[0] == "":
print(helptext)
else:
for cmd in cmds:
if cmd == "digital":
print("Command `digital`")
print("=================")
print(RTControl.do_digital.__doc__[1:-1])
elif cmd == "analog":
print("Command `analog`")
print("================")
print(RTControl.do_analog.__doc__[1:-1])
elif cmd == "zero":
print("Command `zero`")
print("==============")
print(RTControl.do_zero.__doc__[1:-1])
class RTControl(cmd.Cmd):
intro = """
Welcome to the real-time EntangleWare control interface.
Type 'help' or '?' list available commands.
"""[1:-1]
prompt = "<EW> "
def do_digital(self, arg):
"""
Set the digital output state.
Usage:
digital <connector> <channel> <state>
Args:
connector : <int>[/<int>...]
Number(s) of the connector(s) whose state is to be set. To specify
multiple connectors, separate numbers by a slash ('/'). Connector
numbers must be 0-3.
channel : <int>[,<int>][/<int>,...]
Number(s) of the channel(s) whose state is to be set. To specify
multiple channels, separate channel numbers on the same connector by a
comma (',') and those on other connectors by a slash ('/'). The number
of slashes must equal that in the previous argument. Channel numbers
must be 0-31.
state : <0|1>[,<0|1>][/<0|1>,...]
HIGH/LOW state of the channel(s) to be set. To specify the states of
multiple channels, follow the same rules as those for <channel>. A state
must be specified for every channel number in the previous arg. States
must be 0 (LOW) or 1 (HIGH).
"""
try:
state_args = parse_digital_state(arg)
except Exception as err:
print(err)
set_digital_state(state_args)
def do_analog(self, arg):
"""
Set the analog output state.
Usage:
analog <channel> <state>
Args:
channel : <int>[,<int>...]
Number(s) of the channel(s) whose state is to be set. To specify
multiple channels, separate channel numbers by a comma (','). Channel
numbers must be 0-31.
state : <float>[,<float>...]
Output states of the channel(s) to be set. To specify the states of
multiple channels, separate numbers by a comma (','). States must be in
the range [-10.0, +10.0].
"""
try:
state_args = parse_analog_state(arg)
except Exception as err:
print(err)
set_analog_state(state_args)
def do_zero(self, arg):
"""
Set all channels of the given type to be zero.
Usage:
zero <type>
Args:
type : <str>
Type of the channels whose states are to be set to zero. Must be one of
{'digital', 'analog', 'all'}.
"""
try:
zero_type = parse_zero(arg)
except Exception as err:
print(err)
set_zero(zero_type)
def do_quit(self, arg):
"""
Disconnect and quit.
"""
if MAIN._connected:
MAIN.disconnect()
return True
if __name__ == "__main__":
shortopts = "hi"
longopts = [
"help",
"interactive",
]
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], shortopts, longopts)
for opt, optarg in opts:
if opt in {"-h", "--help"}:
print(helptext)
sys.exit(0)
elif opt in {"-i", "--interactive"}:
MAIN.connect()
RTControl().cmdloop()
sys.exit(0)
assert len(args) >= 1, "Must provide a command"
cmd_args = " ".join(args[1:])
if args[0] == "help":
print_help(cmd_args)
elif args[0] == "digital":
MAIN.connect()
set_digital_state(parse_digital_state(cmd_args))
MAIN.disconnect()
elif args[0] == "analog":
MAIN.connect()
set_analog_state(parse_analog_state(cmd_args))
MAIN.disconnect()
elif args[0] == "zero":
MAIN.connect()
set_zero(parse_zero(cmd_args))
MAIN.disconnect()
elif args[0] == "alldefaults":
system.set_defaults()
else:
print(helptext)
sys.exit(1)
sys.exit(0)
except Exception as ERR:
print(ERR)
if MAIN._connected:
MAIN.disconnect()
sys.exit(1)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment