Skip to content

Commit

Permalink
Test suite and BFs for Tektronix TDS5xx
Browse files Browse the repository at this point in the history
Test suite with full coverage
- Tests for `get_hardcopy` routine is a bit creative, but couldn't
  find any manual entry for what is done there.

Bug fixes:
- Typos
- map(float, list_of_string) not allowed anymore, switched to directly
  transferring to `np.array` with specific `dtype`.
- `flush_input` in `read_waveform` replaced with reading one character.
  Manual states that newline character is present after binary block.
- Enums called with name instead of value -> fixed, now called properly
- `get_hardcopy` routine tried to unpack read data. However, the
  `read` routine already decodes it using "utf-8" as the default
  encoding already. Thus: need to encode again before using
  `struct.unpack` to unpack them.
- Class had `import time` and `from time import sleep` and used `sleep`
  and `time.sleep`. Used `import time`, which is useful to mock out
  sleep time.
  • Loading branch information
trappitsch committed Sep 11, 2020
1 parent c9ffd6e commit 68f4f16
Show file tree
Hide file tree
Showing 2 changed files with 885 additions and 15 deletions.
31 changes: 16 additions & 15 deletions instruments/tektronix/tektds5xx.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import operator
import struct
import time
from time import sleep

import numpy as np

Expand Down Expand Up @@ -70,7 +69,7 @@ def __init__(self, tek, idx):
def read(self):
"""
Gets the current measurement value of the channel, and returns a dict
of all relevent information
of all relevant information
:rtype: `dict` of measurement parameters
"""
Expand Down Expand Up @@ -126,8 +125,7 @@ def read_waveform(self, bin_format=True):
self._parent.sendcmd('DAT:ENC ASCI')
raw = self._parent.query('CURVE?')
raw = raw.split(',') # Break up comma delimited string
raw = map(float, raw) # Convert each list element to int
raw = np.array(raw) # Convert into numpy array
raw = np.array(raw, dtype=np.float) # Convert into numpy array
else:
# Set encoding to signed, big-endian
self._parent.sendcmd('DAT:ENC RIB')
Expand All @@ -137,7 +135,8 @@ def read_waveform(self, bin_format=True):
raw = self._parent.binblockread(data_width)

# pylint: disable=protected-access
self._parent._file.flush_input() # Flush input buffer
# read line separation character
self._parent._file.read_raw(1)

# Retrieve Y offset
yoffs = self._parent.query('WFMP:{}:YOF?'.format(self.name))
Expand Down Expand Up @@ -244,7 +243,7 @@ def scale(self):
"""
Gets/sets the scale setting for this channel.
:type: `TekTDS5xx.Impedance`
:type: `float`
"""
return float(self._parent.query("CH{}:SCA?".format(self._idx)))

Expand Down Expand Up @@ -401,7 +400,7 @@ def sources(self):
:rtype: `list`
"""
active = []
channels = map(int, self.query('SEL?').split(';')[0:11])
channels = np.array(self.query('SEL?').split(';')[0:11], dtype=np.int)
for idx in range(0, 4):
if channels[idx]:
active.append(_TekTDS5xxChannel(self, idx))
Expand Down Expand Up @@ -432,7 +431,7 @@ def data_source(self):
@data_source.setter
def data_source(self, newval):
if isinstance(newval, _TekTDS5xxDataSource):
newval = TekTDS5xx.Source[newval.name]
newval = TekTDS5xx.Source(newval.name)
if not isinstance(newval, TekTDS5xx.Source):
raise TypeError("Source setting must be a `TekTDS5xx.Source`"
" value, got {} instead.".format(type(newval)))
Expand Down Expand Up @@ -500,7 +499,7 @@ def trigger_coupling(self):
:type: `TekTDS5xx.Coupling`
"""
return TekTDS5xx.Coupling[self.query("TRIG:MAI:EDGE:COUP?")]
return TekTDS5xx.Coupling(self.query("TRIG:MAI:EDGE:COUP?"))

@trigger_coupling.setter
def trigger_coupling(self, newval):
Expand Down Expand Up @@ -539,8 +538,9 @@ def trigger_source(self):
@trigger_source.setter
def trigger_source(self, newval):
if not isinstance(newval, TekTDS5xx.Trigger):
raise TypeError("Trigger source setting must be a"
"`TekTDS5xx.source` value, got {} instead.".format(type(newval)))
raise TypeError("Trigger source setting must be a "
"`TekTDS5xx.Trigger` value, got {} "
"instead.".format(type(newval)))

self.sendcmd("TRIG:MAI:EDGE:SOU {}".format(newval.value))

Expand All @@ -557,7 +557,7 @@ def clock(self):
@clock.setter
def clock(self, newval):
if not isinstance(newval, datetime):
raise ValueError("Expected datetime.datetime"
raise ValueError("Expected datetime.datetime "
"but got {} instead".format(type(newval)))
self.sendcmd(newval.strftime('DATE "%Y-%m-%d";:TIME "%H:%M:%S"'))

Expand All @@ -573,7 +573,7 @@ def display_clock(self):
@display_clock.setter
def display_clock(self, newval):
if not isinstance(newval, bool):
raise ValueError("Expected bool but got"
raise ValueError("Expected bool but got "
"{} instead".format(type(newval)))
self.sendcmd('DISPLAY:CLOCK {}'.format(int(newval)))

Expand All @@ -585,13 +585,14 @@ def get_hardcopy(self):
"""
self.sendcmd('HARDC:PORT GPI;HARDC:LAY PORT;:HARDC:FORM BMP')
self.sendcmd('HARDC START')
sleep(1)
time.sleep(1)
header = self.query("", size=54)
header = header.encode("utf-8")
# Get BMP Length in kilobytes from DIB header, because file header is
# bad
length = reduce(
operator.mul, struct.unpack('<iihh', header[18:30])) / 8
length = int(length) + 8 # Add 8 bytes for our monochrome colour table
data = header + self.query("", size=length)
data = header + self.query("", size=length).encode("utf-8")
self._file.flush_input() # Flush input buffer
return data

0 comments on commit 68f4f16

Please sign in to comment.