Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 8f54a1e61947
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: abac5284a924
Choose a head ref
  • 5 commits
  • 7 files changed
  • 1 contributor

Commits on Mar 22, 2016

  1. Copy the full SHA
    2cbe47e View commit details
  2. Copy the full SHA
    7657b67 View commit details
  3. Copy the full SHA
    b5441fd View commit details
  4. depend on asyncserial

    sbourdeauducq committed Mar 22, 2016
    Copy the full SHA
    d9e9b66 View commit details
  5. Copy the full SHA
    abac528 View commit details
Showing with 354 additions and 331 deletions.
  1. +55 −53 artiq/devices/novatech409b/driver.py
  2. +225 −227 artiq/devices/thorlabs_tcube/driver.py
  3. +1 −1 artiq/frontend/artiq_master.py
  4. +2 −0 artiq/frontend/novatech409b_controller.py
  5. +69 −48 artiq/protocols/pc_rpc.py
  6. +1 −1 conda/artiq/meta.yaml
  7. +1 −1 setup.py
108 changes: 55 additions & 53 deletions artiq/devices/novatech409b/driver.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Written by Joe Britton, 2015

import time
import math
import logging
import asyncio

import serial
import asyncserial


logger = logging.getLogger(__name__)
@@ -41,22 +41,28 @@ def __init__(self, serial_dev):
self.simulation = True
else:
self.simulation = False
self.port = serial.serial_for_url(
self.port = asyncserial.AsyncSerial(
serial_dev,
baudrate=19200,
bytesize=8,
parity="N",
stopbits=1,
xonxoff=0,
timeout=1.0)
self.setup()
xonxoff=0)

def close(self):
"""Close the serial port."""
if not self.simulation:
self.port.close()

def _ser_send(self, cmd, get_response=True):
async def _ser_readline(self):
c = await self.port.read(1)
r = c
while c != b"\n":
c = await self.port.read(1)
r += c
return r

async def _ser_send(self, cmd, get_response=True):
"""Send a string to the serial port."""

# Low-level routine for sending serial commands to device. It sends
@@ -67,48 +73,42 @@ def _ser_send(self, cmd, get_response=True):
if self.simulation:
logger.info("simulation _ser_send(\"%s\")", cmd)
else:
self.port.flushInput()
self.port.write((cmd + "\r\n").encode())
result = self.port.readline().rstrip().decode()
logger.debug("_ser_send(\"%s\")", cmd)
self.port.ser.reset_input_buffer()
await self.port.write((cmd + "\r\n").encode())
if get_response:
result = (await self._ser_readline()).rstrip().decode()
logger.debug("got response from device: %s", result)
if result == "OK":
pass
elif result == "":
raise UnexpectedResponse("Response from device timed out")
else:
try:
errstr = self.error_codes[result]
except KeyError:
errstr = "Unrecognized reply: '{}'".format(result)
s = "Error Code = {ec}, {ecs}".format(
if result != "OK":
errstr = self.error_codes.get(result, "Unrecognized reply")
s = "Erroneous reply from device: {ec}, {ecs}".format(
ec=result, ecs=errstr)
raise UnexpectedResponse(s)
raise ValueError(s)
else:
pass

def reset(self):
async def reset(self):
"""Hardware reset of 409B."""
self._ser_send("R", get_response=False)
time.sleep(1)
self.setup()
await self._ser_send("R", get_response=False)
await asyncio.sleep(1)
await self.setup()

def setup(self):
async def setup(self):
"""Initial setup of 409B."""

# Setup the Novatech 409B with the following defaults:
# * command echo off ("E d")
# * external clock ("") 10 MHz sinusoid -1 to +7 dBm

self._ser_send("E d", get_response=False)
self.set_phase_continuous(True)
self.set_simultaneous_update(False)
await self._ser_send("E d", get_response=False)
await self.set_phase_continuous(True)
await self.set_simultaneous_update(False)

def save_state_to_eeprom(self):
async def save_state_to_eeprom(self):
"""Save current state to EEPROM."""
self._ser_send("S")
await self._ser_send("S")

def set_phase_continuous(self, is_continuous):
async def set_phase_continuous(self, is_continuous):
"""Toggle phase continuous mode.
Sends the "M n" command. This turns off the automatic
@@ -120,11 +120,11 @@ def set_phase_continuous(self, is_continuous):
:param is_continuous: True or False
"""
if is_continuous:
self._ser_send("M n")
await self._ser_send("M n")
else:
self._ser_send("M a")
await self._ser_send("M a")

def set_simultaneous_update(self, simultaneous):
async def set_simultaneous_update(self, simultaneous):
"""Set simultaneous update mode.
Sends the "I m" command. In this mode an update
@@ -134,29 +134,29 @@ def set_simultaneous_update(self, simultaneous):
simultaneously.
"""
if simultaneous:
self._ser_send("I m")
await self._ser_send("I m")
else:
self._ser_send("I a")
await self._ser_send("I a")

def do_simultaneous_update(self):
async def do_simultaneous_update(self):
"""Apply update in simultaneous update mode."""
self._ser_send("I p")
await self._ser_send("I p")

def set_freq(self, ch_no, freq):
async def set_freq(self, ch_no, freq):
"""Set frequency of one channel."""
# Novatech expects MHz
self._ser_send("F{:d} {:f}".format(ch_no, freq/1e6))
await self._ser_send("F{:d} {:f}".format(ch_no, freq/1e6))

def set_phase(self, ch_no, phase):
async def set_phase(self, ch_no, phase):
"""Set phase of one channel."""
# phase word is required by device
# N is an integer from 0 to 16383. Phase is set to
# N*360/16384 deg; in ARTIQ represent phase in cycles [0, 1]
phase_word = round(phase*16383)
cmd = "P{:d} {:d}".format(ch_no, phase_word)
self._ser_send(cmd)
await self._ser_send(cmd)

def set_gain(self, ch_no, volts):
async def set_gain(self, ch_no, volts):
"""Set amplitude of one channel."""

# due to error in Novatech it doesn't generate an error for
@@ -167,27 +167,29 @@ def set_gain(self, ch_no, volts):
raise ValueError(s)

s = "V{:d} {:d}".format(ch_no, dac_value)
self._ser_send(s)
await self._ser_send(s)

def get_status(self):
async def get_status(self):
if self.simulation:
return ["00989680 2000 01F5 0000 00000000 00000000 000301",
"00989680 2000 01F5 0000 00000000 00000000 000301",
"00989680 2000 01F5 0000 00000000 00000000 000301",
"00989680 2000 01F5 0000 00000000 00000000 000301",
"80 BC0000 0000 0102 21"]
else:
# status message is multi-line
self.port.flushInput()
self.port.write(("QUE" + "\r\n").encode())
result = self.port.readlines()
result = [r.rstrip().decode() for r in result]
self.port.reset_input_buffer()
await self.port.write(("QUE" + "\r\n").encode())
for i in range(5):
m = (await self._ser_readline()).rstrip().decode()
result.append(m)
logger.debug("got device status: %s", result)
return result

def ping(self):
async def ping(self):
try:
stat = self.get_status()
stat = await self.get_status()
except asyncio.CancelledError:
raise
except:
return False
# check that version number matches is "21"
Loading