mirror of https://github.com/m-labs/artiq.git
Merge commit '9d1903a' into rtiobusy
* commit '9d1903a': coredevice/i2c,ttl,spi: consistent device get examples/device_db: remove --no-localhost-bind Monkey-patch asyncio create_server (fixes #253). pipistrello: drop ttls on pmod, add leds back in pipistrello: try with fewer leds/pmod ttl
This commit is contained in:
commit
446dcfbfbc
|
@ -34,8 +34,8 @@ class PCA9548:
|
||||||
On the KC705, this chip is used for selecting the I2C buses on the two FMC
|
On the KC705, this chip is used for selecting the I2C buses on the two FMC
|
||||||
connectors. HPC=1, LPC=2.
|
connectors. HPC=1, LPC=2.
|
||||||
"""
|
"""
|
||||||
def __init__(self, dmgr, busno=0, address=0xe8):
|
def __init__(self, dmgr, busno=0, address=0xe8, core_device="core"):
|
||||||
self.core = dmgr.get("core")
|
self.core = dmgr.get(core_device)
|
||||||
self.busno = busno
|
self.busno = busno
|
||||||
self.address = address
|
self.address = address
|
||||||
|
|
||||||
|
@ -77,8 +77,8 @@ class TCA6424A:
|
||||||
|
|
||||||
On the NIST QC2 hardware, this chip is used for switching the directions
|
On the NIST QC2 hardware, this chip is used for switching the directions
|
||||||
of TTL buffers."""
|
of TTL buffers."""
|
||||||
def __init__(self, dmgr, busno=0, address=0x44):
|
def __init__(self, dmgr, busno=0, address=0x44, core_device="core"):
|
||||||
self.core = dmgr.get("core")
|
self.core = dmgr.get(core_device)
|
||||||
self.busno = busno
|
self.busno = busno
|
||||||
self.address = address
|
self.address = address
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,8 @@ class SPIMaster:
|
||||||
|
|
||||||
:param channel: RTIO channel number of the SPI bus to control.
|
:param channel: RTIO channel number of the SPI bus to control.
|
||||||
"""
|
"""
|
||||||
def __init__(self, dmgr, channel):
|
def __init__(self, dmgr, channel, core_device="core"):
|
||||||
self.core = dmgr.get("core")
|
self.core = dmgr.get(core_device)
|
||||||
self.ref_period_mu = seconds_to_mu(self.core.coarse_ref_period,
|
self.ref_period_mu = seconds_to_mu(self.core.coarse_ref_period,
|
||||||
self.core)
|
self.core)
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
|
|
|
@ -10,8 +10,8 @@ class TTLOut:
|
||||||
|
|
||||||
:param channel: channel number
|
:param channel: channel number
|
||||||
"""
|
"""
|
||||||
def __init__(self, dmgr, channel):
|
def __init__(self, dmgr, channel, core_device="core"):
|
||||||
self.core = dmgr.get("core")
|
self.core = dmgr.get(core_device)
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
|
|
||||||
# in RTIO cycles
|
# in RTIO cycles
|
||||||
|
@ -82,8 +82,8 @@ class TTLInOut:
|
||||||
|
|
||||||
:param channel: channel number
|
:param channel: channel number
|
||||||
"""
|
"""
|
||||||
def __init__(self, dmgr, channel):
|
def __init__(self, dmgr, channel, core_device="core"):
|
||||||
self.core = dmgr.get("core")
|
self.core = dmgr.get(core_device)
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
|
|
||||||
# in RTIO cycles
|
# in RTIO cycles
|
||||||
|
@ -232,8 +232,8 @@ class TTLClockGen:
|
||||||
|
|
||||||
:param channel: channel number
|
:param channel: channel number
|
||||||
"""
|
"""
|
||||||
def __init__(self, dmgr, channel):
|
def __init__(self, dmgr, channel, core_device="core"):
|
||||||
self.core = dmgr.get("core")
|
self.core = dmgr.get(core_device)
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
|
|
||||||
# in RTIO cycles
|
# in RTIO cycles
|
||||||
|
|
|
@ -203,13 +203,6 @@ trce -v 12 -fastpaths -tsi {build_name}.tsi -o {build_name}.twr {build_name}.ncd
|
||||||
|
|
||||||
spi_pins = self.platform.request("pmod_extended_spi", 0)
|
spi_pins = self.platform.request("pmod_extended_spi", 0)
|
||||||
|
|
||||||
for i, p in enumerate((spi_pins.int, spi_pins.rst,
|
|
||||||
spi_pins.d0, spi_pins.d1)):
|
|
||||||
phy = ttl_simple.Inout(p)
|
|
||||||
self.submodules += phy
|
|
||||||
rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4,
|
|
||||||
ofifo_depth=4))
|
|
||||||
|
|
||||||
self.config["RTIO_REGULAR_TTL_COUNT"] = len(rtio_channels)
|
self.config["RTIO_REGULAR_TTL_COUNT"] = len(rtio_channels)
|
||||||
|
|
||||||
phy = ttl_simple.ClockGen(platform.request("ttl", 15))
|
phy = ttl_simple.ClockGen(platform.request("ttl", 15))
|
||||||
|
@ -220,7 +213,7 @@ trce -v 12 -fastpaths -tsi {build_name}.tsi -o {build_name}.twr {build_name}.ncd
|
||||||
self.submodules += phy
|
self.submodules += phy
|
||||||
self.config["RTIO_FIRST_SPI_CHANNEL"] = len(rtio_channels)
|
self.config["RTIO_FIRST_SPI_CHANNEL"] = len(rtio_channels)
|
||||||
rtio_channels.append(rtio.Channel.from_phy(
|
rtio_channels.append(rtio.Channel.from_phy(
|
||||||
phy, ofifo_depth=64, ififo_depth=64))
|
phy, ofifo_depth=256, ififo_depth=256))
|
||||||
|
|
||||||
self.config["RTIO_DDS_CHANNEL"] = len(rtio_channels)
|
self.config["RTIO_DDS_CHANNEL"] = len(rtio_channels)
|
||||||
self.config["DDS_CHANNEL_COUNT"] = 8
|
self.config["DDS_CHANNEL_COUNT"] = 8
|
||||||
|
|
108
artiq/tools.py
108
artiq/tools.py
|
@ -7,6 +7,8 @@ import asyncio
|
||||||
import time
|
import time
|
||||||
import collections
|
import collections
|
||||||
import os
|
import os
|
||||||
|
import socket
|
||||||
|
import itertools
|
||||||
import atexit
|
import atexit
|
||||||
import string
|
import string
|
||||||
|
|
||||||
|
@ -243,3 +245,109 @@ def get_windows_drives():
|
||||||
drives.append(letter)
|
drives.append(letter)
|
||||||
bitmask >>= 1
|
bitmask >>= 1
|
||||||
return drives
|
return drives
|
||||||
|
|
||||||
|
if sys.version_info[:3] == (3, 5, 1):
|
||||||
|
# See https://github.com/m-labs/artiq/issues/253
|
||||||
|
@asyncio.coroutines.coroutine
|
||||||
|
def create_server(self, protocol_factory, host=None, port=None,
|
||||||
|
*,
|
||||||
|
family=socket.AF_UNSPEC,
|
||||||
|
flags=socket.AI_PASSIVE,
|
||||||
|
sock=None,
|
||||||
|
backlog=100,
|
||||||
|
ssl=None,
|
||||||
|
reuse_address=None,
|
||||||
|
reuse_port=None):
|
||||||
|
"""Create a TCP server.
|
||||||
|
The host parameter can be a string, in that case the TCP server is bound
|
||||||
|
to host and port.
|
||||||
|
The host parameter can also be a sequence of strings and in that case
|
||||||
|
the TCP server is bound to all hosts of the sequence. If a host
|
||||||
|
appears multiple times (possibly indirectly e.g. when hostnames
|
||||||
|
resolve to the same IP address), the server is only bound once to that
|
||||||
|
host.
|
||||||
|
Return a Server object which can be used to stop the service.
|
||||||
|
This method is a coroutine.
|
||||||
|
"""
|
||||||
|
if isinstance(ssl, bool):
|
||||||
|
raise TypeError('ssl argument must be an SSLContext or None')
|
||||||
|
if host is not None or port is not None:
|
||||||
|
if sock is not None:
|
||||||
|
raise ValueError(
|
||||||
|
'host/port and sock can not be specified at the same time')
|
||||||
|
|
||||||
|
AF_INET6 = getattr(socket, 'AF_INET6', 0)
|
||||||
|
if reuse_address is None:
|
||||||
|
reuse_address = os.name == 'posix' and sys.platform != 'cygwin'
|
||||||
|
sockets = []
|
||||||
|
if host == '':
|
||||||
|
hosts = [None]
|
||||||
|
elif (isinstance(host, str) or
|
||||||
|
not isinstance(host, collections.Iterable)):
|
||||||
|
hosts = [host]
|
||||||
|
else:
|
||||||
|
hosts = host
|
||||||
|
|
||||||
|
fs = [self._create_server_getaddrinfo(host, port, family=family,
|
||||||
|
flags=flags)
|
||||||
|
for host in hosts]
|
||||||
|
infos = yield from asyncio.tasks.gather(*fs, loop=self)
|
||||||
|
infos = set(itertools.chain.from_iterable(infos))
|
||||||
|
|
||||||
|
completed = False
|
||||||
|
try:
|
||||||
|
for res in infos:
|
||||||
|
af, socktype, proto, canonname, sa = res
|
||||||
|
try:
|
||||||
|
sock = socket.socket(af, socktype, proto)
|
||||||
|
except socket.error:
|
||||||
|
# Assume it's a bad family/type/protocol combination.
|
||||||
|
if self._debug:
|
||||||
|
asyncio.log.logger.warning('create_server() failed to create '
|
||||||
|
'socket.socket(%r, %r, %r)',
|
||||||
|
af, socktype, proto, exc_info=True)
|
||||||
|
continue
|
||||||
|
sockets.append(sock)
|
||||||
|
if reuse_address:
|
||||||
|
sock.setsockopt(
|
||||||
|
socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
|
||||||
|
if reuse_port:
|
||||||
|
if not hasattr(socket, 'SO_REUSEPORT'):
|
||||||
|
raise ValueError(
|
||||||
|
'reuse_port not supported by socket module')
|
||||||
|
else:
|
||||||
|
sock.setsockopt(
|
||||||
|
socket.SOL_SOCKET, socket.SO_REUSEPORT, True)
|
||||||
|
# Disable IPv4/IPv6 dual stack support (enabled by
|
||||||
|
# default on Linux) which makes a single socket
|
||||||
|
# listen on both address families.
|
||||||
|
if af == AF_INET6 and hasattr(socket, 'IPPROTO_IPV6'):
|
||||||
|
sock.setsockopt(socket.IPPROTO_IPV6,
|
||||||
|
socket.IPV6_V6ONLY,
|
||||||
|
True)
|
||||||
|
try:
|
||||||
|
sock.bind(sa)
|
||||||
|
except OSError as err:
|
||||||
|
raise OSError(err.errno, 'error while attempting '
|
||||||
|
'to bind on address %r: %s'
|
||||||
|
% (sa, err.strerror.lower()))
|
||||||
|
completed = True
|
||||||
|
finally:
|
||||||
|
if not completed:
|
||||||
|
for sock in sockets:
|
||||||
|
sock.close()
|
||||||
|
else:
|
||||||
|
if sock is None:
|
||||||
|
raise ValueError('Neither host/port nor sock were specified')
|
||||||
|
sockets = [sock]
|
||||||
|
|
||||||
|
server = asyncio.base_events.Server(self, sockets)
|
||||||
|
for sock in sockets:
|
||||||
|
sock.listen(backlog)
|
||||||
|
sock.setblocking(False)
|
||||||
|
self._start_serving(protocol_factory, sock, ssl, server)
|
||||||
|
if self._debug:
|
||||||
|
asyncio.log.logger.info("%r is serving", server)
|
||||||
|
return server
|
||||||
|
|
||||||
|
asyncio.base_events.BaseEventLoop.create_server = create_server
|
||||||
|
|
|
@ -132,15 +132,7 @@ When plugged to an adapter, the NIST QC1 hardware can be used. The TTL lines are
|
||||||
+--------------+------------+--------------+
|
+--------------+------------+--------------+
|
||||||
| 21 | USER_LED_4 | Output |
|
| 21 | USER_LED_4 | Output |
|
||||||
+--------------+------------+--------------+
|
+--------------+------------+--------------+
|
||||||
| 22 | PMOD_4 | Input+Output |
|
| 22 | TTL15 | Clock |
|
||||||
+--------------+------------+--------------+
|
|
||||||
| 23 | PMOD_5 | Input+Output |
|
|
||||||
+--------------+------------+--------------+
|
|
||||||
| 24 | PMOD_6 | Input+Output |
|
|
||||||
+--------------+------------+--------------+
|
|
||||||
| 25 | PMOD_7 | Input+Output |
|
|
||||||
+--------------+------------+--------------+
|
|
||||||
| 26 | TTL15 | Clock |
|
|
||||||
+--------------+------------+--------------+
|
+--------------+------------+--------------+
|
||||||
|
|
||||||
The input only limitation on channels 0 and 1 comes from the QC-DAQ adapter. When the adapter is not used (and physically unplugged from the Pipistrello board), the corresponding pins on the Pipistrello can be used as outputs. Do not configure these channels as outputs when the adapter is plugged, as this would cause electrical contention.
|
The input only limitation on channels 0 and 1 comes from the QC-DAQ adapter. When the adapter is not used (and physically unplugged from the Pipistrello board), the corresponding pins on the Pipistrello can be used as outputs. Do not configure these channels as outputs when the adapter is plugged, as this would cause electrical contention.
|
||||||
|
@ -153,5 +145,5 @@ Interface Type 2 (SPI) and 2A (expanded SPI):
|
||||||
+--------------+--------+--------+--------+--------+
|
+--------------+--------+--------+--------+--------+
|
||||||
| RTIO channel | CS_N | MOSI | MISO | CLK |
|
| RTIO channel | CS_N | MOSI | MISO | CLK |
|
||||||
+==============+========+========+========+========+
|
+==============+========+========+========+========+
|
||||||
| 27 | PMOD_0 | PMOD_1 | PMOD_2 | PMOD_3 |
|
| 23 | PMOD_0 | PMOD_1 | PMOD_2 | PMOD_3 |
|
||||||
+--------------+--------+--------+--------+--------+
|
+--------------+--------+--------+--------+--------+
|
||||||
|
|
|
@ -154,25 +154,25 @@
|
||||||
# that it always resolves to a network-visible IP address (see documentation).
|
# that it always resolves to a network-visible IP address (see documentation).
|
||||||
"host": "::1",
|
"host": "::1",
|
||||||
"port": 4000,
|
"port": 4000,
|
||||||
"command": "pdq2_controller --no-localhost-bind -p {port} --bind {bind} --simulation --dump qc_q1_0.bin"
|
"command": "pdq2_controller -p {port} --bind {bind} --simulation --dump qc_q1_0.bin"
|
||||||
},
|
},
|
||||||
"qc_q1_1": {
|
"qc_q1_1": {
|
||||||
"type": "controller",
|
"type": "controller",
|
||||||
"host": "::1",
|
"host": "::1",
|
||||||
"port": 4001,
|
"port": 4001,
|
||||||
"command": "pdq2_controller --no-localhost-bind -p {port} --bind {bind} --simulation --dump qc_q1_1.bin"
|
"command": "pdq2_controller -p {port} --bind {bind} --simulation --dump qc_q1_1.bin"
|
||||||
},
|
},
|
||||||
"qc_q1_2": {
|
"qc_q1_2": {
|
||||||
"type": "controller",
|
"type": "controller",
|
||||||
"host": "::1",
|
"host": "::1",
|
||||||
"port": 4002,
|
"port": 4002,
|
||||||
"command": "pdq2_controller --no-localhost-bind -p {port} --bind {bind} --simulation --dump qc_q1_2.bin"
|
"command": "pdq2_controller -p {port} --bind {bind} --simulation --dump qc_q1_2.bin"
|
||||||
},
|
},
|
||||||
"qc_q1_3": {
|
"qc_q1_3": {
|
||||||
"type": "controller",
|
"type": "controller",
|
||||||
"host": "::1",
|
"host": "::1",
|
||||||
"port": 4003,
|
"port": 4003,
|
||||||
"command": "pdq2_controller --no-localhost-bind -p {port} --bind {bind} --simulation --dump qc_q1_3.bin"
|
"command": "pdq2_controller -p {port} --bind {bind} --simulation --dump qc_q1_3.bin"
|
||||||
},
|
},
|
||||||
"electrodes": {
|
"electrodes": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
|
|
Loading…
Reference in New Issue