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: dda5c167b893
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: de4a15c31503
Choose a head ref
  • 4 commits
  • 4 files changed
  • 2 contributors

Commits on Feb 18, 2015

  1. pyon: bytes support

    fallen authored and sbourdeauducq committed Feb 18, 2015
    Copy the full SHA
    3c50610 View commit details
  2. lda: fixes

    fallen authored and sbourdeauducq committed Feb 18, 2015
    Copy the full SHA
    dc132bd View commit details
  3. lda: style

    sbourdeauducq committed Feb 18, 2015
    Copy the full SHA
    05824fd View commit details
  4. lda: add unit tests

    sbourdeauducq committed Feb 18, 2015
    Copy the full SHA
    de4a15c View commit details
Showing with 101 additions and 30 deletions.
  1. +55 −30 artiq/devices/lda/driver.py
  2. +1 −0 artiq/devices/lda/hidapi.py
  3. +5 −0 artiq/protocols/pyon.py
  4. +40 −0 artiq/test/lda.py
85 changes: 55 additions & 30 deletions artiq/devices/lda/driver.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import logging
import ctypes
import struct

from artiq.language.units import dB, check_unit, Quantity


logger = logging.getLogger("lda")


@@ -19,6 +21,12 @@ def __init__(self):
self._att_max = 63*dB
self._att_step_size = 0.25*dB

def get_att_max(self):
return self._att_max

def get_att_step_size(self):
return self._att_step_size

def get_attenuation(self):
"""Reads last attenuation value set to the simulated device.
@@ -33,25 +41,26 @@ def set_attenuation(self, attenuation):
"""Stores the new attenuation value and prints it to console.
:param attenuation: The attenuation value in dB.
:type attenuation: int, float or Fraction
"""

step = self.get_att_step_size()

if isinstance(attenuation, Quantity):
check_unit(attenuation, 'dB')
check_unit(attenuation, "dB")
att = attenuation
else:
att = attenuation*dB

if att > self._att_max:
raise ValueError('Cannot set attenuation {} > {}'
.format(att, self._att_max))
att = round(att/step)*step

if att > self.get_att_max():
raise ValueError("Cannot set attenuation {} > {}"
.format(att, self.get_att_max()))
elif att < 0*dB:
raise ValueError('Cannot set attenuation {} < 0'.format(att))
elif att % self._att_step_size != 0*dB:
raise ValueError('Cannot set attenuation {} with step size {}'
.format(att, self._att_step_size))
raise ValueError("Cannot set attenuation {} < 0".format(att))
else:
att = round(att.amount*4)/4. * dB
print("[LDA-sim] setting attenuation to {}".format(att))
print("setting attenuation to {}".format(att))
self._attenuation = att


@@ -65,8 +74,8 @@ class Lda:
/lib, /usr/local/lib). This can be done either from hidapi sources
or by installing the libhidapi-libusb0 binary package on Debian-like OS.
On Windows you should put hidapi.dll shared library in the same directory
as the controller.
On Windows you should put hidapi.dll shared library in the
artiq\devices\lda folder.
"""
_vendor_id = 0x041f
@@ -75,7 +84,7 @@ class Lda:
"LDA-602": 0x1208,
"LDA-302P-1": 0x120E,
}
_max_att = {
_att_max = {
"LDA-102": 63*dB,
"LDA-602": 63*dB,
"LDA-302P-1": 63*dB
@@ -95,11 +104,26 @@ def __init__(self, serial=None, product="LDA-102"):
from artiq.devices.lda.hidapi import hidapi
self.hidapi = hidapi
self.product = product
if serial is None:
serial = next(self.enumerate(product))
self.serial = serial

if self.serial is None:
self.serial = next(self.enumerate(self.product))
self._dev = self.hidapi.hid_open(self._vendor_id,
self._product_ids[product], serial)
assert self._dev
self._product_ids[self.product],
self.serial)
if not self._dev:
raise IOError

def close(self):
"""Close the device.
"""
self.hidapi.hid_close(self._dev)

def get_att_step_size(self):
return self._att_step_size[self.product]

def get_att_max(self):
return self._att_max[self.product]

@classmethod
def enumerate(cls, product):
@@ -148,9 +172,9 @@ def set(self, command, data):
def get(self, command, length, timeout=1000):
"""Sends a GET command to read back some value of the Lab Brick device.
:param int command: Command ID, most significant bit must be cleared.
:param int length: Length of the command, "count" in the datasheet.
:param int timeout: Timeout of the HID read in ms.
:param command: Command ID, most significant bit must be cleared.
:param length: Length of the command, "count" in the datasheet.
:param timeout: Timeout of the HID read in ms.
:return: Returns the value read from the device.
:rtype: bytes
"""
@@ -181,21 +205,22 @@ def set_attenuation(self, attenuation):
"""Sets attenuation value of the Lab Brick device.
:param attenuation: Attenuation value in dB.
:type attenuation: int, float or Fraction
"""

step = self.get_att_step_size()

if isinstance(attenuation, Quantity):
check_unit(attenuation, 'dB')
check_unit(attenuation, "dB")
att = attenuation
else:
att = attenuation*dB

if att > self._max_att[self.product]:
raise ValueError('Cannot set attenuation {} > {}'
.format(att, self._max_att[self.product]))
elif att < 0:
raise ValueError('Cannot set attenuation {} < 0'.format(att))
elif att % self._att_step_size[self.product] != 0:
raise ValueError('Cannot set attenuation {} with {} step size'
.format(att, self._att_step_size[self.product]))
att = round(att/step)*step

if att > self.get_att_max():
raise ValueError("Cannot set attenuation {} > {}"
.format(att, self.get_att_max()))
elif att < 0*dB:
raise ValueError("Cannot set attenuation {} < 0".format(att))
else:
self.set(0x8d, bytes([int(round(att.amount*4))]))
1 change: 1 addition & 0 deletions artiq/devices/lda/hidapi.py
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@ class HidDeviceInfo(ctypes.Structure):
hidapi.hid_open.argtypes = [ctypes.c_ushort, ctypes.c_ushort,
ctypes.c_wchar_p]
hidapi.hid_open.restype = ctypes.c_void_p
hidapi.hid_close.argtypes = [ctypes.c_void_p]
hidapi.hid_read_timeout.argtypes = [ctypes.c_void_p, ctypes.c_char_p,
ctypes.c_size_t, ctypes.c_int]
hidapi.hid_read.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t]
5 changes: 5 additions & 0 deletions artiq/protocols/pyon.py
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@
int: "number",
float: "number",
str: "str",
bytes: "bytes",
tuple: "tuple",
list: "list",
dict: "dict",
@@ -61,9 +62,13 @@ def encode_number(self, x):
return str(x)

def encode_str(self, x):
# Do not use repr() for JSON compatibility.
tt = {ord("\""): "\\\"", ord("\\"): "\\\\", ord("\n"): "\\n"}
return "\"" + x.translate(tt) + "\""

def encode_bytes(self, x):
return repr(x)

def encode_tuple(self, x):
if len(x) == 1:
return "(" + self.encode(x[0]) + ", )"
40 changes: 40 additions & 0 deletions artiq/test/lda.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import unittest
import os
from artiq.devices.lda.driver import Lda, Ldasim
from artiq.language.units import dB


no_hardware = bool(os.getenv("ARTIQ_NO_HARDWARE"))


class GenericLdaTest:
def test_attenuation(self):
step = self.cont.get_att_step_size().amount
max = self.cont.get_att_max().amount
test_vector = [i*step*dB for i in range(0, int(max*int(1/step)+1))]
for i in test_vector:
with self.subTest(i=i):
self.cont.set_attenuation(i)
self.assertEqual(i, self.cont.get_attenuation())


@unittest.skipIf(no_hardware, "no hardware")
class TestLda(GenericLdaTest, unittest.TestCase):
def setUp(self):
device = os.getenv("ARTIQ_LDA_DEVICE")
serial = os.getenv("ARTIQ_LDA_SERIAL")
args = dict()
if device is not None:
args["product"] = device
if serial is not None:
args["serial"] = serial

self.cont = Lda(**args)


class TestLdaSim(GenericLdaTest, unittest.TestCase):
def setUp(self):
self.cont = Ldasim()

if __name__ == "__main__":
unittest.main()