From 217e6a81c16d40e8d700f2571c0ca2d96a007d39 Mon Sep 17 00:00:00 2001 From: Jonah Shapiro Date: Thu, 8 Oct 2020 10:29:50 -0700 Subject: [PATCH 1/5] Add find_library to windows dll loading --- picoscope/ps2000.py | 3 ++- picoscope/ps2000a.py | 3 ++- picoscope/ps3000.py | 3 ++- picoscope/ps3000a.py | 3 ++- picoscope/ps4000.py | 3 ++- picoscope/ps4000a.py | 3 ++- picoscope/ps5000.py | 3 ++- picoscope/ps5000a.py | 3 ++- picoscope/ps6000.py | 3 ++- 9 files changed, 18 insertions(+), 9 deletions(-) diff --git a/picoscope/ps2000.py b/picoscope/ps2000.py index 80586fa..f75f1b2 100644 --- a/picoscope/ps2000.py +++ b/picoscope/ps2000.py @@ -142,7 +142,8 @@ def __init__(self, serialNumber=None, connect=True): self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll - self.lib = windll.LoadLibrary(str(self.LIBNAME + ".dll")) + from ctypes.util import find_library + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) super(PS2000, self).__init__(serialNumber, connect) diff --git a/picoscope/ps2000a.py b/picoscope/ps2000a.py index 28bd23b..ce34727 100644 --- a/picoscope/ps2000a.py +++ b/picoscope/ps2000a.py @@ -134,7 +134,8 @@ def __init__(self, serialNumber=None, connect=True): self.lib = self.loadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll - self.lib = windll.LoadLibrary(str(self.LIBNAME + ".dll")) + from ctypes.util import find_library + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) self.resolution = self.ADC_RESOLUTIONS["8"] diff --git a/picoscope/ps3000.py b/picoscope/ps3000.py index 7e78fe0..40cc054 100644 --- a/picoscope/ps3000.py +++ b/picoscope/ps3000.py @@ -129,7 +129,8 @@ def __init__(self, serialNumber=None, connect=True): self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll - self.lib = windll.LoadLibrary(str(self.LIBNAME + ".dll")) + from ctypes.util import find_library + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) super(PS3000, self).__init__(serialNumber, connect) diff --git a/picoscope/ps3000a.py b/picoscope/ps3000a.py index 680807e..31bb888 100644 --- a/picoscope/ps3000a.py +++ b/picoscope/ps3000a.py @@ -142,7 +142,8 @@ def __init__(self, serialNumber=None, connect=True): self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll - self.lib = windll.LoadLibrary(str(self.LIBNAME + ".dll")) + from ctypes.util import find_library + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) self.resolution = self.ADC_RESOLUTIONS["8"] diff --git a/picoscope/ps4000.py b/picoscope/ps4000.py index 9a1a3b9..27cd9de 100644 --- a/picoscope/ps4000.py +++ b/picoscope/ps4000.py @@ -139,7 +139,8 @@ def __init__(self, serialNumber=None, connect=True): self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll - self.lib = windll.LoadLibrary(str(self.LIBNAME + ".dll")) + from ctypes.util import find_library + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) super(PS4000, self).__init__(serialNumber, connect) # check to see which model we have and use special functions if needed diff --git a/picoscope/ps4000a.py b/picoscope/ps4000a.py index 2d55da9..56a7e86 100644 --- a/picoscope/ps4000a.py +++ b/picoscope/ps4000a.py @@ -131,7 +131,8 @@ def __init__(self, serialNumber=None, connect=True): self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll - self.lib = windll.LoadLibrary(str(self.LIBNAME + ".dll")) + from ctypes.util import find_library + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) self.resolution = self.ADC_RESOLUTIONS["12"] diff --git a/picoscope/ps5000.py b/picoscope/ps5000.py index 797dbb7..fdce198 100644 --- a/picoscope/ps5000.py +++ b/picoscope/ps5000.py @@ -146,7 +146,8 @@ def __init__(self, serialNumber=None, connect=True): self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll - self.lib = windll.LoadLibrary(str(self.LIBNAME + ".dll")) + from ctypes.util import find_library + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) super(PS5000, self).__init__(serialNumber, connect) diff --git a/picoscope/ps5000a.py b/picoscope/ps5000a.py index 2ed5350..2417378 100644 --- a/picoscope/ps5000a.py +++ b/picoscope/ps5000a.py @@ -134,7 +134,8 @@ def __init__(self, serialNumber=None, connect=True): self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll - self.lib = windll.LoadLibrary(str(self.LIBNAME + ".dll")) + from ctypes.util import find_library + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) self.resolution = self.ADC_RESOLUTIONS["8"] diff --git a/picoscope/ps6000.py b/picoscope/ps6000.py index 77a6fd1..a0beaf3 100644 --- a/picoscope/ps6000.py +++ b/picoscope/ps6000.py @@ -147,7 +147,8 @@ def __init__(self, serialNumber=None, connect=True): self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll - self.lib = windll.LoadLibrary(str(self.LIBNAME + ".dll")) + from ctypes.util import find_library + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) super(PS6000, self).__init__(serialNumber, connect) From a44c2de8b7718c8cb67c1cd30c1e59f71deacff0 Mon Sep 17 00:00:00 2001 From: Jonah Shapiro Date: Thu, 8 Oct 2020 13:04:56 -0700 Subject: [PATCH 2/5] Fixed PEP8 issues --- picoscope/ps2000.py | 233 +++++++++++++++------ picoscope/ps2000a.py | 453 +++++++++++++++++++++++++++------------- picoscope/ps3000.py | 215 +++++++++++++------ picoscope/ps3000a.py | 400 +++++++++++++++++++++++------------ picoscope/ps4000.py | 440 +++++++++++++++++++++++++-------------- picoscope/ps4000a.py | 471 ++++++++++++++++++++++++++--------------- picoscope/ps5000.py | 477 ++++++++++++++++++++++++++++-------------- picoscope/ps5000a.py | 442 +++++++++++++++++++++++++-------------- picoscope/ps6000.py | 485 +++++++++++++++++++++++++++++-------------- 9 files changed, 2420 insertions(+), 1196 deletions(-) diff --git a/picoscope/ps2000.py b/picoscope/ps2000.py index f75f1b2..d0b7fb7 100644 --- a/picoscope/ps2000.py +++ b/picoscope/ps2000.py @@ -29,8 +29,16 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import byref, POINTER, create_string_buffer, c_float, \ - c_int16, c_int32, c_uint32, c_void_p +from ctypes import ( + byref, + POINTER, + create_string_buffer, + c_float, + c_int16, + c_int32, + c_uint32, + c_void_p, +) from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -76,26 +84,32 @@ class PS2000(_PicoscopeBase): NUM_CHANNELS = 2 CHANNELS = {"A": 0, "B": 1, "MaxChannels": 2} - THRESHOLD_TYPE = {"Rising": 0, - "Falling": 1} + THRESHOLD_TYPE = {"Rising": 0, "Falling": 1} CHANNEL_RANGE = [ - {"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}] + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + ] CHANNEL_COUPLINGS = {"DC": 1, "AC": 0} # has_sig_gen = True - WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, - "RampUp": 3, "RampDown": 4, "DCVoltage": 5} + WAVE_TYPES = { + "Sine": 0, + "Square": 1, + "Triangle": 2, + "RampUp": 3, + "RampDown": 4, + "DCVoltage": 5, + } SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} @@ -106,22 +120,34 @@ class PS2000(_PicoscopeBase): MAX_TIMEBASES = 19 - UNIT_INFO_TYPES = {"DriverVersion": 0x0, - "USBVersion": 0x1, - "HardwareVersion": 0x2, - "VariantInfo": 0x3, - "BatchAndSerial": 0x4, - "CalDate": 0x5, - "ErrorCode": 0x6, - "KernelVersion": 0x7} + UNIT_INFO_TYPES = { + "DriverVersion": 0x0, + "USBVersion": 0x1, + "HardwareVersion": 0x2, + "VariantInfo": 0x3, + "BatchAndSerial": 0x4, + "CalDate": 0x5, + "ErrorCode": 0x6, + "KernelVersion": 0x7, + } channelBuffersPtr = [c_void_p(), c_void_p()] channelBuffersLen = [0, 0] - SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, - "GateHigh": 2, "GateLow": 3} - SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, "AuxIn": 2, - "ExtIn": 3, "SoftTrig": 4, "TriggerRaw": 5} + SIGGEN_TRIGGER_TYPES = { + "Rising": 0, + "Falling": 1, + "GateHigh": 2, + "GateLow": 3, + } + SIGGEN_TRIGGER_SOURCES = { + "None": 0, + "ScopeTrig": 1, + "AuxIn": 2, + "ExtIn": 3, + "SoftTrig": 4, + "TriggerRaw": 5, + } AWG_INDEX_MODES = {"Single": 0, "Dual": 1, "Quad": 2} @@ -134,16 +160,21 @@ class PS2000(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLL etc.""" - if platform.system() == 'Linux': + if platform.system() == "Linux": from ctypes import cdll + self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so") - elif platform.system() == 'Darwin': + elif platform.system() == "Darwin": from picoscope.darwin_utils import LoadLibraryDarwin + self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) super(PS2000, self).__init__(serialNumber, connect) @@ -154,8 +185,10 @@ def _lowLevelOpenUnit(self, sn): m = self.lib.ps2000_open_unit() if m < 0: - raise IOError("Failed to Find PS2000 Unit." + - " Should you be using PS2000a driver?") + raise IOError( + "Failed to Find PS2000 Unit." + + " Should you be using PS2000a driver?" + ) self.handle = m self.suggested_time_units = self.TIME_UNITS["NS"] @@ -164,11 +197,16 @@ def _lowLevelCloseUnit(self): m = self.lib.ps2000_close_unit(c_int16(self.handle)) self.checkResult(m) - def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, - BWLimited): + def _lowLevelSetChannel( + self, chNum, enabled, coupling, VRange, VOffset, BWLimited + ): m = self.lib.ps2000_set_channel( - c_int16(self.handle), c_enum(chNum), c_int16(enabled), - c_enum(coupling), c_enum(VRange)) + c_int16(self.handle), + c_enum(chNum), + c_int16(enabled), + c_enum(coupling), + c_enum(VRange), + ) self.checkResult(m) def _lowLevelStop(self): @@ -179,30 +217,43 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) m = self.lib.ps2000_get_unit_info( - c_int16(self.handle), byref(s), c_int16(len(s)), c_enum(info)) + c_int16(self.handle), byref(s), c_int16(len(s)), c_enum(info) + ) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode('utf-8') + return s.value.decode("utf-8") def _lowLevelFlashLed(self, times): m = self.lib.ps2000_flash_led(c_int16(self.handle)) self.checkResult(m) - def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, - direction, delay, timeout_ms): + def _lowLevelSetSimpleTrigger( + self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms + ): # TODO: # Fix 'auto' which is where trigger occurs in block. Delay is not used m = self.lib.ps2000_set_trigger( - c_int16(self.handle), c_enum(trigsrc), c_int16(threshold_adc), - c_enum(direction), c_int16(delay), c_int16(timeout_ms)) + c_int16(self.handle), + c_enum(trigsrc), + c_int16(threshold_adc), + c_enum(direction), + c_int16(delay), + c_int16(timeout_ms), + ) self.checkResult(m) - def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, - timebase, oversample, segmentIndex): + def _lowLevelRunBlock( + self, + numPreTrigSamples, + numPostTrigSamples, + timebase, + oversample, + segmentIndex, + ): # NOT: Oversample is NOT used! # TODO: Fix 'delay' which is where trigger occurs in block @@ -211,8 +262,12 @@ def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, timeIndisposedMs = c_int32() m = self.lib.ps2000_run_block( - c_int16(self.handle), c_uint32(numPostTrigSamples), - c_uint32(timebase), c_int16(1), byref(timeIndisposedMs)) + c_int16(self.handle), + c_uint32(numPostTrigSamples), + c_uint32(timebase), + c_int16(1), + byref(timeIndisposedMs), + ) self.checkResult(m) return timeIndisposedMs.value @@ -234,15 +289,20 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): time_units = c_int16() m = self.lib.ps2000_get_timebase( - c_int16(self.handle), c_int16(tb), c_uint32(noSamples), - byref(time_interval), byref(time_units), c_int16(1), - byref(maxSamples)) + c_int16(self.handle), + c_int16(tb), + c_uint32(noSamples), + byref(time_interval), + byref(time_units), + c_int16(1), + byref(maxSamples), + ) self.checkResult(m) self.suggested_time_units = time_units.value - return (time_interval.value / 1.0E9, maxSamples.value) + return (time_interval.value / 1.0e9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """ps2000 doesn't seem to have published formula like other scopes.""" @@ -250,20 +310,26 @@ def getTimeBaseNum(self, sampleTimeS): timebases = [None] * self.MAX_TIMEBASES # Convert to nS - sampleTimenS = sampleTimeS * 1E9 + sampleTimenS = sampleTimeS * 1e9 tb = 0 while tb < self.MAX_TIMEBASES: rv = self.lib.ps2000_get_timebase( - c_int16(self.handle), c_int16(tb), c_uint32(512), - byref(time_interval), c_void_p(), c_int16(1), c_void_p()) + c_int16(self.handle), + c_int16(tb), + c_uint32(512), + byref(time_interval), + c_void_p(), + c_int16(1), + c_void_p(), + ) if rv != 0: timebases[tb] = time_interval.value tb += 1 # Figure out closest option - besterror = 1E99 + besterror = 1e99 bestindx = 0 for indx, val in enumerate(timebases): if val is not None: @@ -278,13 +344,20 @@ def getTimestepFromTimebase(self, timebase): """Return timestep from timebase.""" time_interval = c_int32() m = self.lib.ps2000_get_timebase( - c_int16(self.handle), c_int16(timebase), c_uint32(512), - byref(time_interval), c_void_p(), c_int16(1), c_void_p()) + c_int16(self.handle), + c_int16(timebase), + c_uint32(512), + byref(time_interval), + c_void_p(), + c_int16(1), + c_void_p(), + ) self.checkResult(m) - return (time_interval.value / 1.0E9) + return time_interval.value / 1.0e9 - def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, - segmentIndex): + def _lowLevelSetDataBuffer( + self, channel, data, downSampleMode, segmentIndex + ): dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) @@ -295,8 +368,14 @@ def _lowLevelClearDataBuffer(self, channel, segmentIndex): self.channelBuffersPtr[channel] = c_void_p() self.channelBuffersLen[channel] = 0 - def _lowLevelGetValues(self, numSamples, startIndex, - downSampleRatio, downSampleMode, segmentIndex): + def _lowLevelGetValues( + self, + numSamples, + startIndex, + downSampleRatio, + downSampleMode, + segmentIndex, + ): # TODO: Check overflow in channelBuffersLen against numSamples, # but need to not raise error if channelBuffersPtr is void @@ -306,16 +385,30 @@ def _lowLevelGetValues(self, numSamples, startIndex, c_int16(self.handle), self.channelBuffersPtr[0], self.channelBuffersPtr[1], - c_void_p(), c_void_p(), - byref(overflow), c_int32(numSamples)) + c_void_p(), + c_void_p(), + byref(overflow), + c_int32(numSamples), + ) self.checkResult(rv) return (rv, overflow.value) - def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, - frequency, shots, triggerType, - triggerSource, stopFreq, increment, - dwellTime, sweepType, numSweeps): + def _lowLevelSetSigGenBuiltInSimple( + self, + offsetVoltage, + pkToPk, + waveType, + frequency, + shots, + triggerType, + triggerSource, + stopFreq, + increment, + dwellTime, + sweepType, + numSweeps, + ): if stopFreq is None: stopFreq = frequency @@ -324,15 +417,19 @@ def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), c_float(stopFreq), - c_float(increment), c_float(dwellTime), c_enum(sweepType), - c_uint32(numSweeps)) + c_float(frequency), + c_float(stopFreq), + c_float(increment), + c_float(dwellTime), + c_enum(sweepType), + c_uint32(numSweeps), + ) self.checkResult(m) def checkResult(self, ec): """Check result of function calls, raise exception if not 0.""" # PS2000 differs from other drivers in that non-zero is good if ec == 0: - raise IOError('Error calling %s' % (inspect.stack()[1][3])) + raise IOError("Error calling %s" % (inspect.stack()[1][3])) return 0 diff --git a/picoscope/ps2000a.py b/picoscope/ps2000a.py index ce34727..3298c5c 100644 --- a/picoscope/ps2000a.py +++ b/picoscope/ps2000a.py @@ -56,8 +56,17 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import byref, POINTER, create_string_buffer, c_float, \ - c_int16, c_int32, c_uint16, c_uint32, c_void_p +from ctypes import ( + byref, + POINTER, + create_string_buffer, + c_float, + c_int16, + c_int32, + c_uint16, + c_uint32, + c_void_p, +) from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -69,39 +78,65 @@ class PS2000a(_PicoscopeBase): LIBNAME = "ps2000a" NUM_CHANNELS = 4 - CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, - "External": 4, "MaxChannels": 4, "TriggerAux": 5} + CHANNELS = { + "A": 0, + "B": 1, + "C": 2, + "D": 3, + "External": 4, + "MaxChannels": 4, + "TriggerAux": 5, + } ADC_RESOLUTIONS = {"8": 0, "12": 1, "14": 2, "15": 3, "16": 4} - CHANNEL_RANGE = [{"rangeV": 10E-3, "apivalue": 0, "rangeStr": "10 mV"}, - {"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + CHANNEL_RANGE = [ + {"rangeV": 10e-3, "apivalue": 0, "rangeStr": "10 mV"}, + {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] CHANNEL_COUPLINGS = {"DC": 1, "AC": 0} # has_sig_gen = True - WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, - "RampUp": 3, "RampDown": 4, - "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, - "WhiteNoise": 9} + WAVE_TYPES = { + "Sine": 0, + "Square": 1, + "Triangle": 2, + "RampUp": 3, + "RampDown": 4, + "Sinc": 5, + "Gaussian": 6, + "HalfSine": 7, + "DCVoltage": 8, + "WhiteNoise": 9, + } SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} - SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, - "GateHigh": 2, "GateLow": 3} - SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, "AuxIn": 2, - "ExtIn": 3, "SoftTrig": 4, "TriggerRaw": 5} + SIGGEN_TRIGGER_TYPES = { + "Rising": 0, + "Falling": 1, + "GateHigh": 2, + "GateLow": 3, + } + SIGGEN_TRIGGER_SOURCES = { + "None": 0, + "ScopeTrig": 1, + "AuxIn": 2, + "ExtIn": 3, + "SoftTrig": 4, + "TriggerRaw": 5, + } # TIME_UNITS = {'PS2000A_FS':0,'PS2000A_PS':1, # 'PS2000A_NS':2,'PS2000A_US':3,'PS2000A_MS':4, @@ -127,15 +162,19 @@ class PS2000a(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLL etc.""" - if platform.system() == 'Linux': + if platform.system() == "Linux": from ctypes import cdll + self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so") - elif platform.system() == 'Darwin': + elif platform.system() == "Darwin": self.lib = self.loadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) self.resolution = self.ADC_RESOLUTIONS["8"] @@ -155,47 +194,83 @@ def _lowLevelOpenUnit(self, sn): # The scaling factor used in the timebase calculation varies based on # the particular model. See section 2.8 (pg 27) of the 2000a # programmer's guide - self.model = self.getUnitInfo('VariantInfo') - if self.model in ('2205AMSO', '2206', '2206A', '2206B', '2405A'): + self.model = self.getUnitInfo("VariantInfo") + if self.model in ("2205AMSO", "2206", "2206A", "2206B", "2405A"): # 500 MS/s - self._timebase_to_timestep = \ - lambda n: (2**n / 5e8) if n < 3 else ((n - 2) / 625e5) - self._timestep_to_timebase = \ - lambda t: math.log(t * 5e8, 2) if t < 16e-9 else ( - (t * 625e5) + 2) - elif self.model in ('2206BMSO', '2207', '2207A', '2207B', '2207BMSO', - '2208', '2208A', '2208B', '2208BMSO', '2406B', - '2407B', '2408B'): + self._timebase_to_timestep = ( + lambda n: (2 ** n / 5e8) if n < 3 else ((n - 2) / 625e5) + ) + self._timestep_to_timebase = ( + lambda t: math.log(t * 5e8, 2) + if t < 16e-9 + else ((t * 625e5) + 2) + ) + elif self.model in ( + "2206BMSO", + "2207", + "2207A", + "2207B", + "2207BMSO", + "2208", + "2208A", + "2208B", + "2208BMSO", + "2406B", + "2407B", + "2408B", + ): # 1 GS/s - self._timebase_to_timestep = lambda n: (2**n / 1e9) if n < 3 else ( - (n - 2) / 125e6) - self._timestep_to_timebase = \ - lambda t: math.log(t * 1e9, 2) if t < 8e-9 else ( - (t * 125e6) + 2) - elif self.model == '2205MSO': - self._timebase_to_timestep = \ - lambda n: (2**n / 2e8) if n < 1 else (n / 1e8) - self._timestep_to_timebase = \ + self._timebase_to_timestep = ( + lambda n: (2 ** n / 1e9) if n < 3 else ((n - 2) / 125e6) + ) + self._timestep_to_timebase = ( + lambda t: math.log(t * 1e9, 2) + if t < 8e-9 + else ((t * 125e6) + 2) + ) + elif self.model == "2205MSO": + self._timebase_to_timestep = ( + lambda n: (2 ** n / 2e8) if n < 1 else (n / 1e8) + ) + self._timestep_to_timebase = ( lambda t: math.log(t * 2e8, 2) if t < 10e-9 else (t * 1e8) + ) else: raise ValueError("Unrecognised variant {}".format(self.model)) # The AWG parameters vary based on the particular model. See section # 3.51.2 of the 2000a programmer's guide - if self.model in ('2205AMSO', '2206', '2206A', '2207', '2207A', '2208', - '2208A', '2405A'): + if self.model in ( + "2205AMSO", + "2206", + "2206A", + "2207", + "2207A", + "2208", + "2208A", + "2405A", + ): self.AWGBufferAddressWidth = 13 - self.AWGDACInterval = 50E-9 - elif self.model in ('2206B', '2206BMSO', '2207B', '2207BMSO', '2208B', - '2208BMSO', '2406B', '2407B', '2408B'): + self.AWGDACInterval = 50e-9 + elif self.model in ( + "2206B", + "2206BMSO", + "2207B", + "2207BMSO", + "2208B", + "2208BMSO", + "2406B", + "2407B", + "2408B", + ): self.AWGBufferAddressWidth = 15 - self.AWGDACInterval = 50E-9 + self.AWGDACInterval = 50e-9 else: # The programmer's manual indicates that some older models have # these parameters. Just use them as a catch-all for any models # not listed above self.AWGBufferAddressWidth = 13 - self.AWGDACInterval = 20.83E-9 + self.AWGDACInterval = 20.83e-9 self.AWGMaxSamples = 2 ** self.AWGBufferAddressWidth self.AWGDACFrequency = 1 / self.AWGDACInterval @@ -204,11 +279,17 @@ def _lowLevelCloseUnit(self): m = self.lib.ps2000aCloseUnit(c_int16(self.handle)) self.checkResult(m) - def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, - BWLimited): - m = self.lib.ps2000aSetChannel(c_int16(self.handle), c_enum(chNum), - c_int16(enabled), c_enum(coupling), - c_enum(VRange), c_float(VOffset)) + def _lowLevelSetChannel( + self, chNum, enabled, coupling, VRange, VOffset, BWLimited + ): + m = self.lib.ps2000aSetChannel( + c_int16(self.handle), + c_enum(chNum), + c_int16(enabled), + c_enum(coupling), + c_enum(VRange), + c_float(VOffset), + ) self.checkResult(m) def _lowLevelStop(self): @@ -219,63 +300,90 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps2000aGetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), byref(requiredSize), - c_enum(info)) + m = self.lib.ps2000aGetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps2000aGetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), - byref(requiredSize), c_enum(info)) + m = self.lib.ps2000aGetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode('utf-8') + return s.value.decode("utf-8") def _lowLevelFlashLed(self, times): m = self.lib.ps2000aFlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, - direction, delay, auto): + def _lowLevelSetSimpleTrigger( + self, enabled, trigsrc, threshold_adc, direction, delay, auto + ): m = self.lib.ps2000aSetSimpleTrigger( - c_int16(self.handle), c_int16(enabled), - c_enum(trigsrc), c_int16(threshold_adc), - c_enum(direction), c_uint32(delay), c_int16(auto)) + c_int16(self.handle), + c_int16(enabled), + c_enum(trigsrc), + c_int16(threshold_adc), + c_enum(direction), + c_uint32(delay), + c_int16(auto), + ) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, numCaptures): m = self.lib.ps2000aSetNoOfCaptures( - c_int16(self.handle), c_uint16(numCaptures)) + c_int16(self.handle), c_uint16(numCaptures) + ) self.checkResult(m) def _lowLevelMemorySegments(self, numSegments): maxSamples = c_int32() - m = self.lib.ps2000aMemorySegments(c_int16(self.handle), - c_uint16(numSegments), - byref(maxSamples)) + m = self.lib.ps2000aMemorySegments( + c_int16(self.handle), c_uint16(numSegments), byref(maxSamples) + ) self.checkResult(m) return maxSamples.value def _lowLevelGetMaxSegments(self): maxSegments = c_int16() - m = self.lib.ps2000aGetMaxSegments(c_int16(self.handle), - byref(maxSegments)) + m = self.lib.ps2000aGetMaxSegments( + c_int16(self.handle), byref(maxSegments) + ) self.checkResult(m) return maxSegments.value - def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, - timebase, oversample, segmentIndex): + def _lowLevelRunBlock( + self, + numPreTrigSamples, + numPostTrigSamples, + timebase, + oversample, + segmentIndex, + ): # NOT: Oversample is NOT used! timeIndisposedMs = c_int32() m = self.lib.ps2000aRunBlock( - c_int16(self.handle), c_uint32(numPreTrigSamples), - c_uint32(numPostTrigSamples), c_uint32(timebase), - c_int16(oversample), byref(timeIndisposedMs), + c_int16(self.handle), + c_uint32(numPreTrigSamples), + c_uint32(numPostTrigSamples), + c_uint32(timebase), + c_int16(oversample), + byref(timeIndisposedMs), c_uint32(segmentIndex), - c_void_p(), c_void_p()) + c_void_p(), + c_void_p(), + ) self.checkResult(m) return timeIndisposedMs.value @@ -294,17 +402,25 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): intervalNanoSec = c_float() m = self.lib.ps2000aGetTimebase2( - c_int16(self.handle), c_uint32(tb), c_uint32(noSamples), - byref(intervalNanoSec), c_int16(oversample), byref(maxSamples), - c_uint32(segmentIndex)) + c_int16(self.handle), + c_uint32(tb), + c_uint32(noSamples), + byref(intervalNanoSec), + c_int16(oversample), + byref(maxSamples), + c_uint32(segmentIndex), + ) self.checkResult(m) # divide by 1e9 to return interval in seconds return (intervalNanoSec.value * 1e-9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """Convert sample time in S to something to pass to API Call.""" - clipped = np.clip(math.floor(self._timestep_to_timebase(sampleTimeS)), - 0, np.iinfo(np.int32).max) + clipped = np.clip( + math.floor(self._timestep_to_timebase(sampleTimeS)), + 0, + np.iinfo(np.int32).max, + ) return int(clipped) @@ -316,34 +432,44 @@ def getTimestepFromTimebase(self, timebase): """ return self._timebase_to_timestep(timebase) - def _lowLevelSetAWGSimpleDeltaPhase(self, waveform, deltaPhase, - offsetVoltage, pkToPk, indexMode, - shots, triggerType, triggerSource): + def _lowLevelSetAWGSimpleDeltaPhase( + self, + waveform, + deltaPhase, + offsetVoltage, + pkToPk, + indexMode, + shots, + triggerType, + triggerSource, + ): """Waveform should be an array of shorts.""" waveformPtr = waveform.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps2000aSetSigGenArbitrary( c_int16(self.handle), - c_uint32(int(offsetVoltage * 1E6)), # offset voltage in microvolts - c_uint32(int(pkToPk * 1E6)), # pkToPk in microvolts - c_uint32(int(deltaPhase)), # startDeltaPhase - c_uint32(int(deltaPhase)), # stopDeltaPhase - c_uint32(0), # deltaPhaseIncrement - c_uint32(0), # dwellCount - waveformPtr, # arbitraryWaveform - c_int32(len(waveform)), # arbitraryWaveformSize - c_enum(0), # sweepType for deltaPhase - c_enum(0), # operation (adding random noise and whatnot) - c_enum(indexMode), # single, dual, quad + c_uint32(int(offsetVoltage * 1e6)), # offset voltage in microvolts + c_uint32(int(pkToPk * 1e6)), # pkToPk in microvolts + c_uint32(int(deltaPhase)), # startDeltaPhase + c_uint32(int(deltaPhase)), # stopDeltaPhase + c_uint32(0), # deltaPhaseIncrement + c_uint32(0), # dwellCount + waveformPtr, # arbitraryWaveform + c_int32(len(waveform)), # arbitraryWaveformSize + c_enum(0), # sweepType for deltaPhase + c_enum(0), # operation (adding random noise and whatnot) + c_enum(indexMode), # single, dual, quad c_uint32(shots), - c_uint32(0), # sweeps + c_uint32(0), # sweeps c_uint32(triggerType), c_uint32(triggerSource), - c_int16(0)) # extInThreshold + c_int16(0), + ) # extInThreshold self.checkResult(m) - def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, - segmentIndex): + def _lowLevelSetDataBuffer( + self, channel, data, downSampleMode, segmentIndex + ): """Set the buffer for the picoscope. Be sure to call _lowLevelClearDataBuffer @@ -354,47 +480,75 @@ def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, numSamples = len(data) m = self.lib.ps2000aSetDataBuffer( - c_int16(self.handle), c_enum(channel), dataPtr, - c_int32(numSamples), c_uint32(segmentIndex), - c_enum(downSampleMode)) + c_int16(self.handle), + c_enum(channel), + dataPtr, + c_int32(numSamples), + c_uint32(segmentIndex), + c_enum(downSampleMode), + ) self.checkResult(m) def _lowLevelSetMultipleDataBuffers(self, channel, data, downSampleMode): max_segments = self._lowLevelGetMaxSegments() if data.shape[0] < max_segments: raise ValueError( - "data array has fewer rows" + - " than current number of memory segments") + "data array has fewer rows" + + " than current number of memory segments" + ) if data.shape[1] < self.maxSamples: raise ValueError("data array has fewer columns than maxSamples") for i in range(max_segments): - m = self._lowLevelSetDataBuffer(channel, data[i, :], - downSampleMode, i) + m = self._lowLevelSetDataBuffer( + channel, data[i, :], downSampleMode, i + ) self.checkResult(m) def _lowLevelClearDataBuffer(self, channel, segmentIndex): """Clear the data in the picoscope.""" m = self.lib.ps2000aSetDataBuffer( - c_int16(self.handle), c_enum(channel), - c_void_p(), c_uint32(0), c_uint32(segmentIndex), c_enum(0)) + c_int16(self.handle), + c_enum(channel), + c_void_p(), + c_uint32(0), + c_uint32(segmentIndex), + c_enum(0), + ) self.checkResult(m) - def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, - downSampleMode, segmentIndex): + def _lowLevelGetValues( + self, + numSamples, + startIndex, + downSampleRatio, + downSampleMode, + segmentIndex, + ): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps2000aGetValues( - c_int16(self.handle), c_uint32(startIndex), - byref(numSamplesReturned), c_uint32(downSampleRatio), - c_enum(downSampleMode), c_uint32(segmentIndex), - byref(overflow)) + c_int16(self.handle), + c_uint32(startIndex), + byref(numSamplesReturned), + c_uint32(downSampleRatio), + c_enum(downSampleMode), + c_uint32(segmentIndex), + byref(overflow), + ) self.checkResult(m) return (numSamplesReturned.value, overflow.value) - def _lowLevelGetValuesBulk(self, numSamples, fromSegment, toSegment, - downSampleRatio, downSampleMode, overflow): + def _lowLevelGetValuesBulk( + self, + numSamples, + fromSegment, + toSegment, + downSampleRatio, + downSampleMode, + overflow, + ): m = self.lib.ps2000aGetValuesBulk( c_int16(self.handle), byref(c_int16(numSamples)), @@ -402,8 +556,8 @@ def _lowLevelGetValuesBulk(self, numSamples, fromSegment, toSegment, c_int16(toSegment), c_int32(downSampleRatio), c_int16(downSampleMode), - overflow.ctypes.data_as(POINTER(c_int16)) - ) + overflow.ctypes.data_as(POINTER(c_int16)), + ) self.checkResult(m) return overflow, numSamples @@ -417,19 +571,31 @@ def _lowLevelGetTriggerTimeOffset(self, segmentIndex): byref(timeLower), byref(timeUnits), c_uint32(segmentIndex), - ) + ) self.checkResult(m) # timeUpper and timeLower are the upper 4 and lower 4 bytes of a 64-bit # (8-byte) integer which is scaled by timeUnits to get the precise # trigger location - return (((timeUpper.value << 32) + timeLower.value) * - self.TIME_UNITS[timeUnits.value]) - - def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, - frequency, shots, triggerType, - triggerSource, stopFreq, increment, - dwellTime, sweepType, numSweeps): + return ((timeUpper.value << 32) + timeLower.value) * self.TIME_UNITS[ + timeUnits.value + ] + + def _lowLevelSetSigGenBuiltInSimple( + self, + offsetVoltage, + pkToPk, + waveType, + frequency, + shots, + triggerType, + triggerSource, + stopFreq, + increment, + dwellTime, + sweepType, + numSweeps, + ): # TODO, I just noticed that V2 exists # Maybe change to V2 in the future @@ -441,15 +607,22 @@ def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), c_float(stopFreq), - c_float(increment), c_float(dwellTime), - c_enum(sweepType), c_enum(0), - c_uint32(shots), c_uint32(numSweeps), - c_enum(triggerType), c_enum(triggerSource), - c_int16(0)) + c_float(frequency), + c_float(stopFreq), + c_float(increment), + c_float(dwellTime), + c_enum(sweepType), + c_enum(0), + c_uint32(shots), + c_uint32(numSweeps), + c_enum(triggerType), + c_enum(triggerSource), + c_int16(0), + ) self.checkResult(m) def _lowLevelSigGenSoftwareControl(self, triggerType): m = self.lib.ps2000aSigGenSoftwareControl( - c_int16(self.handle), c_enum(triggerType)) + c_int16(self.handle), c_enum(triggerType) + ) self.checkResult(m) diff --git a/picoscope/ps3000.py b/picoscope/ps3000.py index 40cc054..9293bc9 100644 --- a/picoscope/ps3000.py +++ b/picoscope/ps3000.py @@ -56,8 +56,16 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import byref, POINTER, create_string_buffer, c_float, \ - c_int16, c_int32, c_uint32, c_void_p +from ctypes import ( + byref, + POINTER, + create_string_buffer, + c_float, + c_int16, + c_int32, + c_uint32, + c_void_p, +) from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -71,27 +79,32 @@ class PS3000(_PicoscopeBase): NUM_CHANNELS = 2 CHANNELS = {"A": 0, "B": 1, "MaxChannels": 2} - THRESHOLD_TYPE = {"Rising": 0, - "Falling": 1} + THRESHOLD_TYPE = {"Rising": 0, "Falling": 1} CHANNEL_RANGE = [ - {"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - ] + ] CHANNEL_COUPLINGS = {"DC": 1, "AC": 0} # has_sig_gen = True - WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, - "RampUp": 3, "RampDown": 4, "DCVoltage": 5} + WAVE_TYPES = { + "Sine": 0, + "Square": 1, + "Triangle": 2, + "RampUp": 3, + "RampDown": 4, + "DCVoltage": 5, + } SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} @@ -102,14 +115,16 @@ class PS3000(_PicoscopeBase): MAX_TIMEBASES = 19 - UNIT_INFO_TYPES = {"DriverVersion": 0x0, - "USBVersion": 0x1, - "HardwareVersion": 0x2, - "VariantInfo": 0x3, - "BatchAndSerial": 0x4, - "CalDate": 0x5, - "ErrorCode": 0x6, - "KernelVersion": 0x7} + UNIT_INFO_TYPES = { + "DriverVersion": 0x0, + "USBVersion": 0x1, + "HardwareVersion": 0x2, + "VariantInfo": 0x3, + "BatchAndSerial": 0x4, + "CalDate": 0x5, + "ErrorCode": 0x6, + "KernelVersion": 0x7, + } channelBuffersPtr = [c_void_p(), c_void_p()] channelBuffersLen = [0, 0] @@ -121,16 +136,21 @@ class PS3000(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLL etc.""" - if platform.system() == 'Linux': + if platform.system() == "Linux": from ctypes import cdll + self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so") - elif platform.system() == 'Darwin': + elif platform.system() == "Darwin": from picoscope.darwin_utils import LoadLibraryDarwin + self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) super(PS3000, self).__init__(serialNumber, connect) @@ -141,8 +161,10 @@ def _lowLevelOpenUnit(self, sn): m = self.lib.ps3000_open_unit() if m < 0: - raise IOError("Failed to Find PS3000 Unit. " + - "Should you be using PS3000a driver?") + raise IOError( + "Failed to Find PS3000 Unit. " + + "Should you be using PS3000a driver?" + ) self.handle = m self.suggested_time_units = self.TIME_UNITS["NS"] @@ -151,12 +173,16 @@ def _lowLevelCloseUnit(self): m = self.lib.ps3000_close_unit(c_int16(self.handle)) self.checkResult(m) - def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, - BWLimited): + def _lowLevelSetChannel( + self, chNum, enabled, coupling, VRange, VOffset, BWLimited + ): m = self.lib.ps3000_set_channel( - c_int16(self.handle), c_enum(chNum), - c_int16(enabled), c_enum(coupling), - c_enum(VRange)) + c_int16(self.handle), + c_enum(chNum), + c_int16(enabled), + c_enum(coupling), + c_enum(VRange), + ) self.checkResult(m) def _lowLevelStop(self): @@ -167,29 +193,42 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) m = self.lib.ps3000_get_unit_info( - c_int16(self.handle), byref(s), c_int16(len(s)), c_enum(info)) + c_int16(self.handle), byref(s), c_int16(len(s)), c_enum(info) + ) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode('utf-8') + return s.value.decode("utf-8") def _lowLevelFlashLed(self, times): m = self.lib.ps3000_flash_led(c_int16(self.handle)) self.checkResult(m) - def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, - direction, delay, timeout_ms): + def _lowLevelSetSimpleTrigger( + self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms + ): # TODO: Fix 'auto' which is where trigger occurs in block. # Delay is not used m = self.lib.ps3000_set_trigger( - c_int16(self.handle), c_enum(trigsrc), c_int16(threshold_adc), - c_enum(direction), c_int16(delay), c_int16(timeout_ms)) + c_int16(self.handle), + c_enum(trigsrc), + c_int16(threshold_adc), + c_enum(direction), + c_int16(delay), + c_int16(timeout_ms), + ) self.checkResult(m) - def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, - timebase, oversample, segmentIndex): + def _lowLevelRunBlock( + self, + numPreTrigSamples, + numPostTrigSamples, + timebase, + oversample, + segmentIndex, + ): # NOT: Oversample is NOT used! # TODO: Fix 'delay' which is where trigger occurs in block @@ -198,8 +237,12 @@ def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, timeIndisposedMs = c_int32() m = self.lib.ps3000_run_block( - c_int16(self.handle), c_uint32(numPostTrigSamples), - c_uint32(timebase), c_int16(1), byref(timeIndisposedMs)) + c_int16(self.handle), + c_uint32(numPostTrigSamples), + c_uint32(timebase), + c_int16(1), + byref(timeIndisposedMs), + ) self.checkResult(m) return timeIndisposedMs.value @@ -221,15 +264,20 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): time_units = c_int16() m = self.lib.ps3000_get_timebase( - c_int16(self.handle), c_int16(tb), c_uint32(noSamples), - byref(time_interval), byref(time_units), c_int16(1), - byref(maxSamples)) + c_int16(self.handle), + c_int16(tb), + c_uint32(noSamples), + byref(time_interval), + byref(time_units), + c_int16(1), + byref(maxSamples), + ) self.checkResult(m) self.suggested_time_units = time_units.value - return (time_interval.value / 1.0E9, maxSamples.value) + return (time_interval.value / 1.0e9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """ps3000 doesn't seem to have published formula like other scopes.""" @@ -237,20 +285,26 @@ def getTimeBaseNum(self, sampleTimeS): timebases = [None] * self.MAX_TIMEBASES # Convert to nS - sampleTimenS = sampleTimeS * 1E9 + sampleTimenS = sampleTimeS * 1e9 tb = 0 while tb < self.MAX_TIMEBASES: rv = self.lib.ps3000_get_timebase( - c_int16(self.handle), c_int16(tb), c_uint32(512), - byref(time_interval), c_void_p(), c_int16(1), c_void_p()) + c_int16(self.handle), + c_int16(tb), + c_uint32(512), + byref(time_interval), + c_void_p(), + c_int16(1), + c_void_p(), + ) if rv != 0: timebases[tb] = time_interval.value tb += 1 # Figure out closest option - besterror = 1E99 + besterror = 1e99 bestindx = 0 for indx, val in enumerate(timebases): if val is not None: @@ -265,13 +319,20 @@ def getTimestepFromTimebase(self, timebase): """Return timestep from Timebase.""" time_interval = c_int32() m = self.lib.ps3000_get_timebase( - c_int16(self.handle), c_int16(timebase), c_uint32(512), - byref(time_interval), c_void_p(), c_int16(1), c_void_p()) + c_int16(self.handle), + c_int16(timebase), + c_uint32(512), + byref(time_interval), + c_void_p(), + c_int16(1), + c_void_p(), + ) self.checkResult(m) - return (time_interval.value / 1.0E9) + return time_interval.value / 1.0e9 - def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, - segmentIndex): + def _lowLevelSetDataBuffer( + self, channel, data, downSampleMode, segmentIndex + ): dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) @@ -282,8 +343,14 @@ def _lowLevelClearDataBuffer(self, channel, segmentIndex): self.channelBuffersPtr[channel] = c_void_p() self.channelBuffersLen[channel] = 0 - def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, - downSampleMode, segmentIndex): + def _lowLevelGetValues( + self, + numSamples, + startIndex, + downSampleRatio, + downSampleMode, + segmentIndex, + ): # TODO: # Check overflow in channelBuffersLen against numSamples, # but need to not raise error if channelBuffersPtr is void @@ -293,16 +360,30 @@ def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, c_int16(self.handle), self.channelBuffersPtr[0], self.channelBuffersPtr[1], - c_void_p(), c_void_p(), - byref(overflow), c_int32(numSamples)) + c_void_p(), + c_void_p(), + byref(overflow), + c_int32(numSamples), + ) self.checkResult(rv) return (rv, overflow.value) - def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, - frequency, shots, triggerType, - triggerSource, stopFreq, increment, - dwellTime, sweepType, numSweeps): + def _lowLevelSetSigGenBuiltInSimple( + self, + offsetVoltage, + pkToPk, + waveType, + frequency, + shots, + triggerType, + triggerSource, + stopFreq, + increment, + dwellTime, + sweepType, + numSweeps, + ): if stopFreq is None: stopFreq = frequency @@ -311,15 +392,19 @@ def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), c_float(stopFreq), - c_float(increment), c_float(dwellTime), c_enum(sweepType), - c_uint32(numSweeps)) + c_float(frequency), + c_float(stopFreq), + c_float(increment), + c_float(dwellTime), + c_enum(sweepType), + c_uint32(numSweeps), + ) self.checkResult(m) def checkResult(self, ec): """Check result of function calls, raise exception if not 0.""" # PS3000 differs from other drivers in that non-zero is good if ec == 0: - raise IOError('Error calling %s' % (inspect.stack()[1][3])) + raise IOError("Error calling %s" % (inspect.stack()[1][3])) return 0 diff --git a/picoscope/ps3000a.py b/picoscope/ps3000a.py index 31bb888..803175b 100644 --- a/picoscope/ps3000a.py +++ b/picoscope/ps3000a.py @@ -54,8 +54,17 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import byref, POINTER, create_string_buffer, c_float, \ - c_int16, c_int32, c_uint16, c_uint32, c_void_p +from ctypes import ( + byref, + POINTER, + create_string_buffer, + c_float, + c_int16, + c_int32, + c_uint16, + c_uint32, + c_void_p, +) from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -67,39 +76,65 @@ class PS3000a(_PicoscopeBase): LIBNAME = "ps3000a" NUM_CHANNELS = 4 - CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, - "External": 4, "MaxChannels": 4, "TriggerAux": 5} + CHANNELS = { + "A": 0, + "B": 1, + "C": 2, + "D": 3, + "External": 4, + "MaxChannels": 4, + "TriggerAux": 5, + } ADC_RESOLUTIONS = {"8": 0, "12": 1, "14": 2, "15": 3, "16": 4} - CHANNEL_RANGE = [{"rangeV": 10E-3, "apivalue": 0, "rangeStr": "10 mV"}, - {"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + CHANNEL_RANGE = [ + {"rangeV": 10e-3, "apivalue": 0, "rangeStr": "10 mV"}, + {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] CHANNEL_COUPLINGS = {"DC": 1, "AC": 0} # has_sig_gen = True - WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, - "RampUp": 3, "RampDown": 4, - "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, - "WhiteNoise": 9} + WAVE_TYPES = { + "Sine": 0, + "Square": 1, + "Triangle": 2, + "RampUp": 3, + "RampDown": 4, + "Sinc": 5, + "Gaussian": 6, + "HalfSine": 7, + "DCVoltage": 8, + "WhiteNoise": 9, + } SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} - SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, - "GateHigh": 2, "GateLow": 3} - SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, "AuxIn": 2, - "ExtIn": 3, "SoftTrig": 4, "TriggerRaw": 5} + SIGGEN_TRIGGER_TYPES = { + "Rising": 0, + "Falling": 1, + "GateHigh": 2, + "GateLow": 3, + } + SIGGEN_TRIGGER_SOURCES = { + "None": 0, + "ScopeTrig": 1, + "AuxIn": 2, + "ExtIn": 3, + "SoftTrig": 4, + "TriggerRaw": 5, + } # This is actually different depending on the AB/CD models # I wonder how we could detect the difference between the oscilloscopes @@ -113,7 +148,7 @@ class PS3000a(_PicoscopeBase): AWGBufferAddressWidth = 14 AWGMaxSamples = 2 ** AWGBufferAddressWidth - AWGDACInterval = 5E-9 # in seconds + AWGDACInterval = 5e-9 # in seconds AWGDACFrequency = 1 / AWGDACInterval # Note this is NOT what is written in the Programming guide as of version @@ -134,16 +169,21 @@ class PS3000a(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLL etc.""" - if platform.system() == 'Linux': + if platform.system() == "Linux": from ctypes import cdll + self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so") - elif platform.system() == 'Darwin': + elif platform.system() == "Darwin": from picoscope.darwin_utils import LoadLibraryDarwin + self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) self.resolution = self.ADC_RESOLUTIONS["8"] @@ -186,26 +226,33 @@ def _lowLevelEnumerateUnits(self): serialLth = c_int16(count.value * (8 + 2)) serials = create_string_buffer(serialLth.value + 1) - m = self.lib.ps3000aEnumerateUnits(byref(count), serials, - byref(serialLth)) + m = self.lib.ps3000aEnumerateUnits( + byref(count), serials, byref(serialLth) + ) self.checkResult(m) - serialList = str(serials.value.decode('utf-8')).split(',') + serialList = str(serials.value.decode("utf-8")).split(",") serialList = [x.strip() for x in serialList] return serialList - def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, - BWLimited): - m = self.lib.ps3000aSetChannel(c_int16(self.handle), c_enum(chNum), - c_int16(enabled), c_enum(coupling), - c_enum(VRange), c_float(VOffset)) + def _lowLevelSetChannel( + self, chNum, enabled, coupling, VRange, VOffset, BWLimited + ): + m = self.lib.ps3000aSetChannel( + c_int16(self.handle), + c_enum(chNum), + c_int16(enabled), + c_enum(coupling), + c_enum(VRange), + c_float(VOffset), + ) self.checkResult(m) - m = self.lib.ps3000aSetBandwidthFilter(c_int16(self.handle), - c_enum(chNum), - c_enum(BWLimited)) + m = self.lib.ps3000aSetBandwidthFilter( + c_int16(self.handle), c_enum(chNum), c_enum(BWLimited) + ) self.checkResult(m) def _lowLevelStop(self): @@ -216,63 +263,90 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps3000aGetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), byref(requiredSize), - c_enum(info)) + m = self.lib.ps3000aGetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps3000aGetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), - byref(requiredSize), c_enum(info)) + m = self.lib.ps3000aGetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode('utf-8') + return s.value.decode("utf-8") def _lowLevelFlashLed(self, times): m = self.lib.ps3000aFlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, - direction, delay, auto): + def _lowLevelSetSimpleTrigger( + self, enabled, trigsrc, threshold_adc, direction, delay, auto + ): m = self.lib.ps3000aSetSimpleTrigger( - c_int16(self.handle), c_int16(enabled), - c_enum(trigsrc), c_int16(threshold_adc), - c_enum(direction), c_uint32(delay), c_int16(auto)) + c_int16(self.handle), + c_int16(enabled), + c_enum(trigsrc), + c_int16(threshold_adc), + c_enum(direction), + c_uint32(delay), + c_int16(auto), + ) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, numCaptures): - m = self.lib.ps3000aSetNoOfCaptures(c_int16(self.handle), - c_uint16(numCaptures)) + m = self.lib.ps3000aSetNoOfCaptures( + c_int16(self.handle), c_uint16(numCaptures) + ) self.checkResult(m) def _lowLevelMemorySegments(self, numSegments): maxSamples = c_int32() - m = self.lib.ps3000aMemorySegments(c_int16(self.handle), - c_uint16(numSegments), - byref(maxSamples)) + m = self.lib.ps3000aMemorySegments( + c_int16(self.handle), c_uint16(numSegments), byref(maxSamples) + ) self.checkResult(m) return maxSamples.value def _lowLevelGetMaxSegments(self): maxSegments = c_int16() - m = self.lib.ps3000aGetMaxSegments(c_int16(self.handle), - byref(maxSegments)) + m = self.lib.ps3000aGetMaxSegments( + c_int16(self.handle), byref(maxSegments) + ) self.checkResult(m) return maxSegments.value - def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, - timebase, oversample, segmentIndex): + def _lowLevelRunBlock( + self, + numPreTrigSamples, + numPostTrigSamples, + timebase, + oversample, + segmentIndex, + ): # NOT: Oversample is NOT used! timeIndisposedMs = c_int32() m = self.lib.ps3000aRunBlock( - c_int16(self.handle), c_uint32(numPreTrigSamples), - c_uint32(numPostTrigSamples), c_uint32(timebase), - c_int16(oversample), byref(timeIndisposedMs), + c_int16(self.handle), + c_uint32(numPreTrigSamples), + c_uint32(numPostTrigSamples), + c_uint32(timebase), + c_int16(oversample), + byref(timeIndisposedMs), c_uint32(segmentIndex), - c_void_p(), c_void_p()) + c_void_p(), + c_void_p(), + ) self.checkResult(m) return timeIndisposedMs.value @@ -294,21 +368,24 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): maxSamples = c_int32() intervalNanoSec = c_float() - m = self.lib.ps3000aGetTimebase2(c_int16(self.handle), c_uint32(tb), - c_uint32(noSamples), - byref(intervalNanoSec), - c_int16(oversample), - byref(maxSamples), - c_uint32(segmentIndex)) + m = self.lib.ps3000aGetTimebase2( + c_int16(self.handle), + c_uint32(tb), + c_uint32(noSamples), + byref(intervalNanoSec), + c_int16(oversample), + byref(maxSamples), + c_uint32(segmentIndex), + ) self.checkResult(m) # divide by 1e9 to return interval in seconds return (intervalNanoSec.value * 1e-9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """Convert sample time in S to something to pass to API Call.""" - maxSampleTime = (((2 ** 32 - 1) - 2) / 125000000) - if sampleTimeS < 8.0E-9: - st = math.floor(math.log(sampleTimeS * 1E9, 2)) + maxSampleTime = ((2 ** 32 - 1) - 2) / 125000000 + if sampleTimeS < 8.0e-9: + st = math.floor(math.log(sampleTimeS * 1e9, 2)) st = max(st, 0) else: if sampleTimeS > maxSampleTime: @@ -325,39 +402,49 @@ def getTimestepFromTimebase(self, timebase): API timestep is an integer from 0-32 """ if timebase < 3: - dt = 2. ** timebase / 1.0E9 + dt = 2.0 ** timebase / 1.0e9 else: - dt = (timebase - 2.0) / 125000000. + dt = (timebase - 2.0) / 125000000.0 return dt - def _lowLevelSetAWGSimpleDeltaPhase(self, waveform, deltaPhase, - offsetVoltage, pkToPk, indexMode, - shots, triggerType, triggerSource): + def _lowLevelSetAWGSimpleDeltaPhase( + self, + waveform, + deltaPhase, + offsetVoltage, + pkToPk, + indexMode, + shots, + triggerType, + triggerSource, + ): """Waveform should be an array of shorts.""" waveformPtr = waveform.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps3000aSetSigGenArbitrary( c_int16(self.handle), - c_uint32(int(offsetVoltage * 1E6)), # offset voltage in microvolts - c_uint32(int(pkToPk * 1E6)), # pkToPk in microvolts - c_uint32(int(deltaPhase)), # startDeltaPhase - c_uint32(int(deltaPhase)), # stopDeltaPhase - c_uint32(0), # deltaPhaseIncrement - c_uint32(0), # dwellCount - waveformPtr, # arbitraryWaveform - c_int32(len(waveform)), # arbitraryWaveformSize - c_enum(0), # sweepType for deltaPhase - c_enum(0), # operation (adding random noise and whatnot) - c_enum(indexMode), # single, dual, quad + c_uint32(int(offsetVoltage * 1e6)), # offset voltage in microvolts + c_uint32(int(pkToPk * 1e6)), # pkToPk in microvolts + c_uint32(int(deltaPhase)), # startDeltaPhase + c_uint32(int(deltaPhase)), # stopDeltaPhase + c_uint32(0), # deltaPhaseIncrement + c_uint32(0), # dwellCount + waveformPtr, # arbitraryWaveform + c_int32(len(waveform)), # arbitraryWaveformSize + c_enum(0), # sweepType for deltaPhase + c_enum(0), # operation (adding random noise and whatnot) + c_enum(indexMode), # single, dual, quad c_uint32(shots), - c_uint32(0), # sweeps + c_uint32(0), # sweeps c_uint32(triggerType), c_uint32(triggerSource), - c_int16(0)) # extInThreshold + c_int16(0), + ) # extInThreshold self.checkResult(m) - def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, - segmentIndex): + def _lowLevelSetDataBuffer( + self, channel, data, downSampleMode, segmentIndex + ): """Set the data buffer. Be sure to call _lowLevelClearDataBuffer @@ -368,14 +455,18 @@ def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, numSamples = len(data) m = self.lib.ps3000aSetDataBuffer( - c_int16(self.handle), c_enum(channel), - dataPtr, c_int32(numSamples), + c_int16(self.handle), + c_enum(channel), + dataPtr, + c_int32(numSamples), c_uint32(segmentIndex), - c_enum(downSampleMode)) + c_enum(downSampleMode), + ) self.checkResult(m) - def _lowLevelSetDataBufferBulk(self, channel, data, segmentIndex, - downSampleMode): + def _lowLevelSetDataBufferBulk( + self, channel, data, segmentIndex, downSampleMode + ): """Set the bulk data buffer. In ps3000a, ps3000aSetDataBuffer combines the functionality of @@ -384,45 +475,69 @@ def _lowLevelSetDataBufferBulk(self, channel, data, segmentIndex, needed. Note that the order of segmentIndex and downSampleMode is reversed. """ - self._lowLevelSetDataBuffer(channel, data, downSampleMode, - segmentIndex) + self._lowLevelSetDataBuffer( + channel, data, downSampleMode, segmentIndex + ) def _lowLevelSetMultipleDataBuffers(self, channel, data, downSampleMode): max_segments = self._lowLevelGetMaxSegments() if data.shape[0] < max_segments: - raise ValueError("data array has fewer rows than current number " + - "of memory segments") + raise ValueError( + "data array has fewer rows than current number " + + "of memory segments" + ) if data.shape[1] < self.maxSamples: raise ValueError("data array has fewer columns than maxSamples") for i in range(max_segments): - m = self._lowLevelSetDataBuffer(channel, data[i, :], - downSampleMode, i) + m = self._lowLevelSetDataBuffer( + channel, data[i, :], downSampleMode, i + ) self.checkResult(m) def _lowLevelClearDataBuffer(self, channel, segmentIndex): - m = self.lib.ps3000aSetDataBuffer(c_int16(self.handle), - c_enum(channel), - c_void_p(), c_uint32(0), - c_uint32(segmentIndex), - c_enum(0)) + m = self.lib.ps3000aSetDataBuffer( + c_int16(self.handle), + c_enum(channel), + c_void_p(), + c_uint32(0), + c_uint32(segmentIndex), + c_enum(0), + ) self.checkResult(m) - def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, - downSampleMode, segmentIndex): + def _lowLevelGetValues( + self, + numSamples, + startIndex, + downSampleRatio, + downSampleMode, + segmentIndex, + ): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps3000aGetValues( - c_int16(self.handle), c_uint32(startIndex), - byref(numSamplesReturned), c_uint32(downSampleRatio), - c_enum(downSampleMode), c_uint32(segmentIndex), - byref(overflow)) + c_int16(self.handle), + c_uint32(startIndex), + byref(numSamplesReturned), + c_uint32(downSampleRatio), + c_enum(downSampleMode), + c_uint32(segmentIndex), + byref(overflow), + ) self.checkResult(m) return (numSamplesReturned.value, overflow.value) - def _lowLevelGetValuesBulk(self, numSamples, fromSegment, toSegment, - downSampleRatio, downSampleMode, overflow): + def _lowLevelGetValuesBulk( + self, + numSamples, + fromSegment, + toSegment, + downSampleRatio, + downSampleMode, + overflow, + ): m = self.lib.ps3000aGetValuesBulk( c_int16(self.handle), byref(c_uint32(numSamples)), @@ -430,15 +545,26 @@ def _lowLevelGetValuesBulk(self, numSamples, fromSegment, toSegment, c_uint32(toSegment), c_uint32(downSampleRatio), c_int16(downSampleMode), - overflow.ctypes.data_as(POINTER(c_int16)) - ) + overflow.ctypes.data_as(POINTER(c_int16)), + ) self.checkResult(m) return overflow, numSamples - def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, - frequency, shots, triggerType, - triggerSource, stopFreq, increment, - dwellTime, sweepType, numSweeps): + def _lowLevelSetSigGenBuiltInSimple( + self, + offsetVoltage, + pkToPk, + waveType, + frequency, + shots, + triggerType, + triggerSource, + stopFreq, + increment, + dwellTime, + sweepType, + numSweeps, + ): # TODO, I just noticed that V2 exists # Maybe change to V2 in the future if stopFreq is None: @@ -449,22 +575,28 @@ def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), c_float(stopFreq), - c_float(increment), c_float(dwellTime), - c_enum(sweepType), c_enum(0), - c_uint32(shots), c_uint32(numSweeps), - c_enum(triggerType), c_enum(triggerSource), - c_int16(0)) + c_float(frequency), + c_float(stopFreq), + c_float(increment), + c_float(dwellTime), + c_enum(sweepType), + c_enum(0), + c_uint32(shots), + c_uint32(numSweeps), + c_enum(triggerType), + c_enum(triggerSource), + c_int16(0), + ) self.checkResult(m) def _lowLevelChangePowerSource(self, powerstate): m = self.lib.ps3000aChangePowerSource( - c_int16(self.handle), - c_enum(powerstate)) + c_int16(self.handle), c_enum(powerstate) + ) self.checkResult(m) def _lowLevelSigGenSoftwareControl(self, triggerType): m = self.lib.ps3000aSigGenSoftwareControl( - c_int16(self.handle), - c_enum(triggerType)) + c_int16(self.handle), c_enum(triggerType) + ) self.checkResult(m) diff --git a/picoscope/ps4000.py b/picoscope/ps4000.py index 27cd9de..0afe93e 100644 --- a/picoscope/ps4000.py +++ b/picoscope/ps4000.py @@ -58,8 +58,18 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import byref, POINTER, create_string_buffer, c_float, \ - c_int16, c_uint16, c_int32, c_uint32, c_uint64, c_void_p +from ctypes import ( + byref, + POINTER, + create_string_buffer, + c_float, + c_int16, + c_uint16, + c_int32, + c_uint32, + c_uint64, + c_void_p, +) from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -88,11 +98,20 @@ class PS4000(_PicoscopeBase): AWGBufferAddressWidth = 12 AWGMaxSamples = 2 ** AWGBufferAddressWidth - SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, - "GateHigh": 2, "GateLow": 3} - - SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, - "AuxIn": 2, "ExtIn": 3, "SoftTrig": 4} + SIGGEN_TRIGGER_TYPES = { + "Rising": 0, + "Falling": 1, + "GateHigh": 2, + "GateLow": 3, + } + + SIGGEN_TRIGGER_SOURCES = { + "None": 0, + "ScopeTrig": 1, + "AuxIn": 2, + "ExtIn": 3, + "SoftTrig": 4, + } # EXT/AUX seems to have an imput impedence of 50 ohm (PS6403B) EXT_MAX_VALUE = 32767 @@ -101,60 +120,76 @@ class PS4000(_PicoscopeBase): # I don't think that the 50V range is allowed, but I left it there anyway # The 10V and 20V ranges are only allowed in high impedence modes - CHANNEL_RANGE = [{"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + CHANNEL_RANGE = [ + {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] NUM_CHANNELS = 4 CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, "EXT": 4} CHANNEL_COUPLINGS = {"DC50": 2, "DC": 1, "AC": 0} - WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, - "RampUp": 3, "RampDown": 4, - "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, - "WhiteNoise": 9} + WAVE_TYPES = { + "Sine": 0, + "Square": 1, + "Triangle": 2, + "RampUp": 3, + "RampDown": 4, + "Sinc": 5, + "Gaussian": 6, + "HalfSine": 7, + "DCVoltage": 8, + "WhiteNoise": 9, + } SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} def __init__(self, serialNumber=None, connect=True): """Load DLLs.""" self.handle = None - if platform.system() == 'Linux': + if platform.system() == "Linux": from ctypes import cdll + # ok I don't know what is wrong with my installer, # but I need to include .so.2 self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so.2") - elif platform.system() == 'Darwin': + elif platform.system() == "Darwin": from picoscope.darwin_utils import LoadLibraryDarwin + self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) super(PS4000, self).__init__(serialNumber, connect) # check to see which model we have and use special functions if needed - unit_number = self.getUnitInfo('VariantInfo') - if unit_number == '4262': + unit_number = self.getUnitInfo("VariantInfo") + if unit_number == "4262": self.getTimestepFromTimebase = self._getTimestepFromTimebase4262 self.getTimeBaseNum = self._getTimeBaseNum4262 - elif unit_number in {'4223', '4224', '4423', '4424'}: + elif unit_number in {"4223", "4224", "4423", "4424"}: self.getTimestepFromTimebase = self._getTimestepFromTimebase4223 self.getTimeBaseNum = self._getTimeBaseNum4223 else: - raise NotImplementedError('Timebase functions have not been ' - 'written for the ' + unit_number) + raise NotImplementedError( + "Timebase functions have not been " + "written for the " + unit_number + ) def _lowLevelOpenUnit(self, sn): c_handle = c_int16() @@ -185,9 +220,9 @@ def _lowLevelOpenUnitProgress(self): progressPercent = c_int16() handle = c_int16() - m = self.lib.ps4000OpenUnitProgress(byref(handle), - byref(progressPercent), - byref(complete)) + m = self.lib.ps4000OpenUnitProgress( + byref(handle), byref(progressPercent), byref(complete) + ) self.checkResult(m) if complete.value != 0: @@ -212,22 +247,29 @@ def _lowLevelEnumerateUnits(self): serialLth = c_int16(count.value * (8 + 2)) serials = create_string_buffer(serialLth.value + 1) - m = self.lib.ps4000EnumerateUnits(byref(count), serials, - byref(serialLth)) + m = self.lib.ps4000EnumerateUnits( + byref(count), serials, byref(serialLth) + ) self.checkResult(m) - serialList = str(serials.value.decode('utf-8')).split(',') + serialList = str(serials.value.decode("utf-8")).split(",") serialList = [x.strip() for x in serialList] return serialList - def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, - BWLimited): - m = self.lib.ps4000SetChannel(c_int16(self.handle), c_enum(chNum), - c_int16(enabled), c_enum(coupling), - c_enum(VRange), c_float(VOffset), - c_enum(BWLimited)) + def _lowLevelSetChannel( + self, chNum, enabled, coupling, VRange, VOffset, BWLimited + ): + m = self.lib.ps4000SetChannel( + c_int16(self.handle), + c_enum(chNum), + c_int16(enabled), + c_enum(coupling), + c_enum(VRange), + c_float(VOffset), + c_enum(BWLimited), + ) self.checkResult(m) def _lowLevelStop(self): @@ -238,41 +280,67 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps4000GetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), byref(requiredSize), - c_enum(info)) + m = self.lib.ps4000GetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps4000GetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), - byref(requiredSize), c_enum(info)) + m = self.lib.ps4000GetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode('utf-8') + return s.value.decode("utf-8") def _lowLevelFlashLed(self, times): m = self.lib.ps4000FlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, - direction, delay, timeout_ms): + def _lowLevelSetSimpleTrigger( + self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms + ): m = self.lib.ps4000SetSimpleTrigger( - c_int16(self.handle), c_int16(enabled), - c_enum(trigsrc), c_int16(threshold_adc), - c_enum(direction), c_uint32(delay), c_int16(timeout_ms)) + c_int16(self.handle), + c_int16(enabled), + c_enum(trigsrc), + c_int16(threshold_adc), + c_enum(direction), + c_uint32(delay), + c_int16(timeout_ms), + ) self.checkResult(m) - def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, - timebase, oversample, segmentIndex): + def _lowLevelRunBlock( + self, + numPreTrigSamples, + numPostTrigSamples, + timebase, + oversample, + segmentIndex, + ): timeIndisposedMs = c_int32() m = self.lib.ps4000RunBlock( - c_int16(self.handle), c_uint32(numPreTrigSamples), - c_uint32(numPostTrigSamples), c_uint32(timebase), - c_int16(oversample), byref(timeIndisposedMs), - c_uint16(segmentIndex), c_void_p(), c_void_p()) + c_int16(self.handle), + c_uint32(numPreTrigSamples), + c_uint32(numPostTrigSamples), + c_uint32(timebase), + c_int16(oversample), + byref(timeIndisposedMs), + c_uint16(segmentIndex), + c_void_p(), + c_void_p(), + ) self.checkResult(m) return timeIndisposedMs.value @@ -290,30 +358,37 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): maxSamples = c_int32() sampleRate = c_float() - m = self.lib.ps4000GetTimebase2(c_int16(self.handle), c_uint32(tb), - c_uint32(noSamples), byref(sampleRate), - c_int16(oversample), byref(maxSamples), - c_uint16(segmentIndex)) + m = self.lib.ps4000GetTimebase2( + c_int16(self.handle), + c_uint32(tb), + c_uint32(noSamples), + byref(sampleRate), + c_int16(oversample), + byref(maxSamples), + c_uint16(segmentIndex), + ) self.checkResult(m) - return (sampleRate.value / 1.0E9, maxSamples.value) + return (sampleRate.value / 1.0e9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """Return sample time in seconds to timebase as int for API calls.""" - raise NotImplementedError('Timebase functions have not been ' - 'written for the scope.') + raise NotImplementedError( + "Timebase functions have not been " "written for the scope." + ) def getTimestepFromTimebase(self, timebase): """Return timebase to sampletime as seconds.""" - raise NotImplementedError('Timebase functions have not been ' - 'written for the scope.') + raise NotImplementedError( + "Timebase functions have not been " "written for the scope." + ) def _getTimeBaseNum4223(self, sampleTimeS): """Return sample time in seconds to timebase as int for API calls.""" - maxSampleTime = (((2 ** 32 - 1) - 4) / 2e7) + maxSampleTime = ((2 ** 32 - 1) - 4) / 2e7 - if sampleTimeS <= 12.5E-9: - timebase = math.floor(math.log(sampleTimeS * 8E7, 2)) + if sampleTimeS <= 12.5e-9: + timebase = math.floor(math.log(sampleTimeS * 8e7, 2)) timebase = max(timebase, 0) else: # Otherwise in range 2^32-1 @@ -329,7 +404,7 @@ def _getTimeBaseNum4223(self, sampleTimeS): def _getTimestepFromTimebase4223(self, timebase): """Return timebase to sampletime as seconds.""" if timebase < 3: - dt = 2. ** timebase / 8e7 + dt = 2.0 ** timebase / 8e7 else: dt = (timebase - 1) / 2e7 return dt @@ -337,7 +412,7 @@ def _getTimestepFromTimebase4223(self, timebase): def _getTimestepFromTimebase4262(self, timebase): """Return timebase to sampletime as seconds for ps4262.""" someConstant = 10000000.0 - return (timebase+1) / someConstant + return (timebase + 1) / someConstant def _getTimeBaseNum4262(self, sampleTimeS): """Return timebase for the ps4262. @@ -346,13 +421,13 @@ def _getTimeBaseNum4262(self, sampleTimeS): int for API calls for ps4262. """ someConstant = 10000000.0 - maxSampleTime = ((2 ** 30) / someConstant) + maxSampleTime = (2 ** 30) / someConstant minSampleTime = 1 / someConstant if sampleTimeS <= minSampleTime: timebase = 0 elif sampleTimeS >= maxSampleTime: - timebase = (2 ** 30) + timebase = 2 ** 30 else: timebase = round(sampleTimeS * someConstant) - 1 @@ -360,8 +435,9 @@ def _getTimeBaseNum4262(self, sampleTimeS): timebase = int(timebase) return timebase - def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, - segmentIndex): + def _lowLevelSetDataBuffer( + self, channel, data, downSampleMode, segmentIndex + ): """Set the data buffer. Be sure to call _lowLevelClearDataBuffer @@ -374,58 +450,97 @@ def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) - m = self.lib.ps4000SetDataBuffer(c_int16(self.handle), c_enum(channel), - dataPtr, c_uint32(numSamples)) + m = self.lib.ps4000SetDataBuffer( + c_int16(self.handle), + c_enum(channel), + dataPtr, + c_uint32(numSamples), + ) self.checkResult(m) def _lowLevelClearDataBuffer(self, channel, segmentIndex): - m = self.lib.ps4000SetDataBuffer(c_int16(self.handle), c_enum(channel), - c_void_p(), c_uint32(0), c_enum(0)) + m = self.lib.ps4000SetDataBuffer( + c_int16(self.handle), + c_enum(channel), + c_void_p(), + c_uint32(0), + c_enum(0), + ) self.checkResult(m) - def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, - downSampleMode, segmentIndex): + def _lowLevelGetValues( + self, + numSamples, + startIndex, + downSampleRatio, + downSampleMode, + segmentIndex, + ): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps4000GetValues( - c_int16(self.handle), c_uint32(startIndex), - byref(numSamplesReturned), c_uint32(downSampleRatio), - c_enum(downSampleMode), c_uint16(segmentIndex), - byref(overflow)) + c_int16(self.handle), + c_uint32(startIndex), + byref(numSamplesReturned), + c_uint32(downSampleRatio), + c_enum(downSampleMode), + c_uint16(segmentIndex), + byref(overflow), + ) self.checkResult(m) return (numSamplesReturned.value, overflow.value) - def _lowLevelSetAWGSimpleDeltaPhase(self, waveform, deltaPhase, - offsetVoltage, pkToPk, indexMode, - shots, triggerType, triggerSource): + def _lowLevelSetAWGSimpleDeltaPhase( + self, + waveform, + deltaPhase, + offsetVoltage, + pkToPk, + indexMode, + shots, + triggerType, + triggerSource, + ): """Waveform should be an array of shorts.""" waveformPtr = waveform.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps4000SetSigGenArbitrary( c_int16(self.handle), - c_uint32(int(offsetVoltage * 1E6)), # offset voltage in microvolts - c_uint32(int(pkToPk * 1E6)), # pkToPk in microvolts - c_uint32(int(deltaPhase)), # startDeltaPhase - c_uint32(int(deltaPhase)), # stopDeltaPhase - c_uint32(0), # deltaPhaseIncrement - c_uint32(0), # dwellCount - waveformPtr, # arbitraryWaveform - c_int32(len(waveform)), # arbitraryWaveformSize - c_enum(0), # sweepType for deltaPhase - c_enum(0), # operation (adding random noise and whatnot) - c_enum(indexMode), # single, dual, quad + c_uint32(int(offsetVoltage * 1e6)), # offset voltage in microvolts + c_uint32(int(pkToPk * 1e6)), # pkToPk in microvolts + c_uint32(int(deltaPhase)), # startDeltaPhase + c_uint32(int(deltaPhase)), # stopDeltaPhase + c_uint32(0), # deltaPhaseIncrement + c_uint32(0), # dwellCount + waveformPtr, # arbitraryWaveform + c_int32(len(waveform)), # arbitraryWaveformSize + c_enum(0), # sweepType for deltaPhase + c_enum(0), # operation (adding random noise and whatnot) + c_enum(indexMode), # single, dual, quad c_uint32(shots), - c_uint32(0), # sweeps + c_uint32(0), # sweeps c_uint32(triggerType), c_uint32(triggerSource), - c_int16(0)) # extInThreshold + c_int16(0), + ) # extInThreshold self.checkResult(m) - def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, - frequency, shots, triggerType, - triggerSource, stopFreq, increment, - dwellTime, sweepType, numSweeps): + def _lowLevelSetSigGenBuiltInSimple( + self, + offsetVoltage, + pkToPk, + waveType, + frequency, + shots, + triggerType, + triggerSource, + stopFreq, + increment, + dwellTime, + sweepType, + numSweeps, + ): if stopFreq is None: stopFreq = frequency @@ -434,18 +549,25 @@ def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), c_float(stopFreq), - c_float(increment), c_float(dwellTime), - c_enum(sweepType), c_enum(0), - c_uint32(shots), c_uint32(numSweeps), - c_enum(triggerType), c_enum(triggerSource), - c_int16(0)) + c_float(frequency), + c_float(stopFreq), + c_float(increment), + c_float(dwellTime), + c_enum(sweepType), + c_enum(0), + c_uint32(shots), + c_uint32(numSweeps), + c_enum(triggerType), + c_enum(triggerSource), + c_int16(0), + ) self.checkResult(m) def _lowLevelSigGenSoftwareControl(self, triggerType): m = self.lib.ps4000SigGenSoftwareControl( - c_int16(self.handle), c_enum(triggerType)) + c_int16(self.handle), c_enum(triggerType) + ) self.checkResult(m) # use VRange=5 for +/- 500mV signal range @@ -453,8 +575,8 @@ def _lowLevelSigGenSoftwareControl(self, triggerType): # VRange=8 for +/- 5V range def _lowLevelSetExtTriggerRange(self, VRange): m = self.lib.ps4000SetExtTriggerRange( - c_int16(self.handle), - c_enum(VRange)) + c_int16(self.handle), c_enum(VRange) + ) self.checkResult(m) #################################################################### @@ -462,8 +584,9 @@ def _lowLevelSetExtTriggerRange(self, VRange): # # #################################################################### - def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, - downSampleRatioMode, segmentIndex): + def _lowLevelGetMaxDownSampleRatio( + self, noOfUnaggregatedSamples, downSampleRatioMode, segmentIndex + ): maxDownSampleRatio = c_uint32() m = self.lib.ps4000GetMaxDownSampleRatio( @@ -471,7 +594,8 @@ def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, c_uint32(noOfUnaggregatedSamples), byref(maxDownSampleRatio), c_enum(downSampleRatioMode), - c_uint16(segmentIndex)) + c_uint16(segmentIndex), + ) self.checkResult(m) return maxDownSampleRatio.value @@ -480,7 +604,8 @@ def _lowLevelGetNoOfCaptures(self): nCaptures = c_uint32() m = self.lib.ps4000GetNoOfCaptures( - c_int16(self.handle), byref(nCaptures)) + c_int16(self.handle), byref(nCaptures) + ) self.checkResult(m) return nCaptures.value @@ -493,37 +618,39 @@ def _lowLevelGetTriggerTimeOffset(self, segmentIndex): c_int16(self.handle), byref(time), byref(timeUnits), - c_uint16(segmentIndex)) + c_uint16(segmentIndex), + ) self.checkResult(m) - if timeUnits.value == 0: # PS4000_FS - return time.value * 1E-15 + if timeUnits.value == 0: # PS4000_FS + return time.value * 1e-15 elif timeUnits.value == 1: # PS4000_PS - return time.value * 1E-12 + return time.value * 1e-12 elif timeUnits.value == 2: # PS4000_NS - return time.value * 1E-9 + return time.value * 1e-9 elif timeUnits.value == 3: # PS4000_US - return time.value * 1E-6 + return time.value * 1e-6 elif timeUnits.value == 4: # PS4000_MS - return time.value * 1E-3 + return time.value * 1e-3 elif timeUnits.value == 5: # PS4000_S - return time.value * 1E0 + return time.value * 1e0 else: raise TypeError("Unknown timeUnits %d" % timeUnits.value) def _lowLevelMemorySegments(self, nSegments): nMaxSamples = c_uint32() - m = self.lib.ps4000MemorySegments(c_int16(self.handle), - c_uint16(nSegments), - byref(nMaxSamples)) + m = self.lib.ps4000MemorySegments( + c_int16(self.handle), c_uint16(nSegments), byref(nMaxSamples) + ) self.checkResult(m) return nMaxSamples.value - def _lowLevelSetDataBuffers(self, channel, bufferMax, bufferMin, - downSampleRatioMode): + def _lowLevelSetDataBuffers( + self, channel, bufferMax, bufferMin, downSampleRatioMode + ): bufferMaxPtr = bufferMax.ctypes.data_as(POINTER(c_int16)) bufferMinPtr = bufferMin.ctypes.data_as(POINTER(c_int16)) bufferLth = len(bufferMax) @@ -533,7 +660,8 @@ def _lowLevelSetDataBuffers(self, channel, bufferMax, bufferMin, c_enum(channel), bufferMaxPtr, bufferMinPtr, - c_uint32(bufferLth)) + c_uint32(bufferLth), + ) self.checkResult(m) def _lowLevelClearDataBuffers(self, channel): @@ -542,32 +670,38 @@ def _lowLevelClearDataBuffers(self, channel): c_enum(channel), c_void_p(), c_void_p(), - c_uint32(0)) + c_uint32(0), + ) self.checkResult(m) # Bulk values. # These would be nice, but the user would have to provide us # with an array. # we would have to make sure that it is contiguous amonts other things - def _lowLevelGetValuesBulk(self, - numSamples, - fromSegmentIndex, - toSegmentIndex, - downSampleRatio, - downSampleMode, - overflow): + def _lowLevelGetValuesBulk( + self, + numSamples, + fromSegmentIndex, + toSegmentIndex, + downSampleRatio, + downSampleMode, + overflow, + ): noOfSamples = c_uint32(numSamples) m = self.lib.ps4000GetValuesBulk( c_int16(self.handle), byref(noOfSamples), - c_uint16(fromSegmentIndex), c_uint16(toSegmentIndex), - overflow.ctypes.data_as(POINTER(c_int16))) + c_uint16(fromSegmentIndex), + c_uint16(toSegmentIndex), + overflow.ctypes.data_as(POINTER(c_int16)), + ) self.checkResult(m) return noOfSamples.value - def _lowLevelSetDataBufferBulk(self, channel, buffer, waveform, - downSampleRatioMode): + def _lowLevelSetDataBufferBulk( + self, channel, buffer, waveform, downSampleRatioMode + ): bufferPtr = buffer.ctypes.data_as(POINTER(c_int16)) bufferLth = len(buffer) @@ -576,13 +710,14 @@ def _lowLevelSetDataBufferBulk(self, channel, buffer, waveform, c_enum(channel), bufferPtr, c_uint32(bufferLth), - c_uint16(waveform)) + c_uint16(waveform), + ) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, nCaptures): m = self.lib.ps4000SetNoOfCaptures( - c_int16(self.handle), - c_uint16(nCaptures)) + c_int16(self.handle), c_uint16(nCaptures) + ) self.checkResult(m) # ETS Functions @@ -644,7 +779,8 @@ def _lowLevelNoOfStreamingValues(self): noOfValues = c_uint32() m = self.lib.ps4000NoOfStreamingValues( - c_int16(self.handle), byref(noOfValues)) + c_int16(self.handle), byref(noOfValues) + ) self.checkResult(m) return noOfValues.value diff --git a/picoscope/ps4000a.py b/picoscope/ps4000a.py index 56a7e86..3c92800 100644 --- a/picoscope/ps4000a.py +++ b/picoscope/ps4000a.py @@ -58,8 +58,19 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import byref, POINTER, create_string_buffer, c_float, \ - c_int16, c_uint16, c_int32, c_uint32, c_uint64, c_void_p, c_int8 +from ctypes import ( + byref, + POINTER, + create_string_buffer, + c_float, + c_int16, + c_uint16, + c_int32, + c_uint32, + c_uint64, + c_void_p, + c_int8, +) from ctypes import c_int32 as c_enum import warnings @@ -82,57 +93,82 @@ class PS4000a(_PicoscopeBase): # I don't think that the 50V range is allowed, but I left it there anyway # The 10V and 20V ranges are only allowed in high impedence modes - CHANNEL_RANGE = [{"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + CHANNEL_RANGE = [ + {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] NUM_CHANNELS = 8 - CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, "E": 4, "F": 5, "G": 6, - "H": 7, "MaxChannels": 8} + CHANNELS = { + "A": 0, + "B": 1, + "C": 2, + "D": 3, + "E": 4, + "F": 5, + "G": 6, + "H": 7, + "MaxChannels": 8, + } ADC_RESOLUTIONS = {"8": 0, "12": 1, "14": 2, "15": 3, "16": 4} CHANNEL_COUPLINGS = {"DC50": 2, "DC": 1, "AC": 0} - WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, - "RampUp": 3, "RampDown": 4, - "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, - "WhiteNoise": 9} + WAVE_TYPES = { + "Sine": 0, + "Square": 1, + "Triangle": 2, + "RampUp": 3, + "RampDown": 4, + "Sinc": 5, + "Gaussian": 6, + "HalfSine": 7, + "DCVoltage": 8, + "WhiteNoise": 9, + } SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} - TIME_UNITS = {"femtoseconds": 0, - "picoseconds": 1, - "nanoseconds": 2, - "microseconds": 3, - "milliseconds": 4, - "seconds": 5} + TIME_UNITS = { + "femtoseconds": 0, + "picoseconds": 1, + "nanoseconds": 2, + "microseconds": 3, + "milliseconds": 4, + "seconds": 5, + } def __init__(self, serialNumber=None, connect=True): """Load DLLs.""" self.handle = None - if platform.system() == 'Linux': + if platform.system() == "Linux": from ctypes import cdll + # ok I don't know what is wrong with my installer, # but I need to include .so.2 self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so.2") - elif platform.system() == 'Darwin': + elif platform.system() == "Darwin": from picoscope.darwin_utils import LoadLibraryDarwin + self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) self.resolution = self.ADC_RESOLUTIONS["12"] @@ -159,7 +195,7 @@ def _lowLevelOpenUnit(self, sn): else: self.checkResult(m) - self.model = self.getUnitInfo('VariantInfo') + self.model = self.getUnitInfo("VariantInfo") def _lowLevelOpenUnitAsync(self, sn): c_status = c_int16() @@ -179,9 +215,9 @@ def _lowLevelOpenUnitProgress(self): progressPercent = c_int16() handle = c_int16() - m = self.lib.ps4000aOpenUnitProgress(byref(handle), - byref(progressPercent), - byref(complete)) + m = self.lib.ps4000aOpenUnitProgress( + byref(handle), byref(progressPercent), byref(complete) + ) self.checkResult(m) if complete.value != 0: @@ -200,8 +236,9 @@ def _lowLevelEnumerateUnits(self): serials = c_int8(0) serialLth = c_int16(0) - m = self.lib.ps4000aEnumerateUnits(byref(count), byref(serials), - byref(serialLth)) + m = self.lib.ps4000aEnumerateUnits( + byref(count), byref(serials), byref(serialLth) + ) self.checkResult(m) # a serial number is rouhgly 8 characters # an extra character for the comma @@ -210,26 +247,33 @@ def _lowLevelEnumerateUnits(self): serialLth = c_int16(count.value * (8 + 2)) serials = create_string_buffer(serialLth.value + 1) - m = self.lib.ps4000aEnumerateUnits(byref(count), serials, - byref(serialLth)) + m = self.lib.ps4000aEnumerateUnits( + byref(count), serials, byref(serialLth) + ) self.checkResult(m) - serialList = str(serials.value.decode('utf-8')).split(',') + serialList = str(serials.value.decode("utf-8")).split(",") serialList = [x.strip() for x in serialList] return serialList - def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, - BWLimited): - m = self.lib.ps4000aSetChannel(c_int16(self.handle), c_enum(chNum), - c_int16(enabled), c_enum(coupling), - c_enum(VRange), c_float(VOffset)) + def _lowLevelSetChannel( + self, chNum, enabled, coupling, VRange, VOffset, BWLimited + ): + m = self.lib.ps4000aSetChannel( + c_int16(self.handle), + c_enum(chNum), + c_int16(enabled), + c_enum(coupling), + c_enum(VRange), + c_float(VOffset), + ) self.checkResult(m) - m = self.lib.ps4000aSetBandwidthFilter(c_int16(self.handle), - c_enum(chNum), - c_enum(BWLimited)) + m = self.lib.ps4000aSetBandwidthFilter( + c_int16(self.handle), c_enum(chNum), c_enum(BWLimited) + ) self.checkResult(m) def _lowLevelStop(self): @@ -240,41 +284,66 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps4000aGetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), byref(requiredSize), - c_enum(info)) + m = self.lib.ps4000aGetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps4000aGetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), - byref(requiredSize), c_enum(info)) + m = self.lib.ps4000aGetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode('utf-8') + return s.value.decode("utf-8") def _lowLevelFlashLed(self, times): m = self.lib.ps4000aFlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, - direction, delay, timeout_ms): + def _lowLevelSetSimpleTrigger( + self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms + ): m = self.lib.ps4000aSetSimpleTrigger( - c_int16(self.handle), c_int16(enabled), - c_enum(trigsrc), c_int16(threshold_adc), - c_enum(direction), c_uint32(delay), c_int16(timeout_ms)) + c_int16(self.handle), + c_int16(enabled), + c_enum(trigsrc), + c_int16(threshold_adc), + c_enum(direction), + c_uint32(delay), + c_int16(timeout_ms), + ) self.checkResult(m) - def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, - timebase, oversample, segmentIndex): + def _lowLevelRunBlock( + self, + numPreTrigSamples, + numPostTrigSamples, + timebase, + oversample, + segmentIndex, + ): timeIndisposedMs = c_int32() m = self.lib.ps4000aRunBlock( - c_int16(self.handle), c_int32(numPreTrigSamples), - c_int32(numPostTrigSamples), c_uint32(timebase), + c_int16(self.handle), + c_int32(numPreTrigSamples), + c_int32(numPostTrigSamples), + c_uint32(timebase), byref(timeIndisposedMs), - c_uint32(segmentIndex), c_void_p(), c_void_p()) + c_uint32(segmentIndex), + c_void_p(), + c_void_p(), + ) self.checkResult(m) return timeIndisposedMs.value @@ -292,25 +361,29 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): maxSamples = c_int32() sampleRate = c_float() - m = self.lib.ps4000aGetTimebase2(c_int16(self.handle), c_uint32(tb), - c_int32(noSamples), byref(sampleRate), - byref(maxSamples), - c_uint32(segmentIndex)) + m = self.lib.ps4000aGetTimebase2( + c_int16(self.handle), + c_uint32(tb), + c_int32(noSamples), + byref(sampleRate), + byref(maxSamples), + c_uint32(segmentIndex), + ) self.checkResult(m) - return (sampleRate.value / 1.0E9, maxSamples.value) + return (sampleRate.value / 1.0e9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): - """ Convert the sample interval (float of seconds) to the + """Convert the sample interval (float of seconds) to the corresponding integer timebase value as defined by the API. See "Timebases" section of the PS4000a programmers guide for more information. """ - if self.model == '4828': - maxSampleTime = (((2 ** 32 - 1) + 1) / 8E7) + if self.model == "4828": + maxSampleTime = ((2 ** 32 - 1) + 1) / 8e7 - if sampleTimeS <= 12.5E-9: + if sampleTimeS <= 12.5e-9: timebase = 0 else: # Otherwise in range 2^32-1 @@ -319,29 +392,36 @@ def getTimeBaseNum(self, sampleTimeS): timebase = math.floor((sampleTimeS * 2e7) + 1) - elif self.model == '4444': - maxSampleTime = (((2 ** 32 - 1) - 2) / 5.0E7) + elif self.model == "4444": + maxSampleTime = ((2 ** 32 - 1) - 2) / 5.0e7 - if (sampleTimeS <= 2.5E-9 and - self.resolution == self.ADC_RESOLUTIONS["12"]): + if ( + sampleTimeS <= 2.5e-9 + and self.resolution == self.ADC_RESOLUTIONS["12"] + ): timebase = 0 - elif (sampleTimeS <= 20E-9 and - self.resolution == self.ADC_RESOLUTIONS["14"]): + elif ( + sampleTimeS <= 20e-9 + and self.resolution == self.ADC_RESOLUTIONS["14"] + ): timebase = 3 else: # Otherwise in range 2^32-1 if sampleTimeS > maxSampleTime: sampleTimeS = maxSampleTime - timebase = math.floor((sampleTimeS * 5.0E7) + 2) + timebase = math.floor((sampleTimeS * 5.0e7) + 2) else: # The original case from non "A" series - warnings.warn("The model PS4000a you are using may not be " - "fully supported", stacklevel=2) - maxSampleTime = (((2 ** 32 - 1) - 4) / 2e7) - - if sampleTimeS <= 12.5E-9: - timebase = math.floor(math.log(sampleTimeS * 8E7, 2)) + warnings.warn( + "The model PS4000a you are using may not be " + "fully supported", + stacklevel=2, + ) + maxSampleTime = ((2 ** 32 - 1) - 4) / 2e7 + + if sampleTimeS <= 12.5e-9: + timebase = math.floor(math.log(sampleTimeS * 8e7, 2)) timebase = max(timebase, 0) else: # Otherwise in range 2^32-1 @@ -356,26 +436,30 @@ def getTimeBaseNum(self, sampleTimeS): def getTimestepFromTimebase(self, timebase): """Return timebase to sampletime as seconds.""" - if self.model == '4828': - dt = (timebase + 1) / 8.0E7 - elif self.model == '4444': + if self.model == "4828": + dt = (timebase + 1) / 8.0e7 + elif self.model == "4444": if timebase < 3: - dt = 2.5 ** timebase / 4.0E8 + dt = 2.5 ** timebase / 4.0e8 else: - dt = (timebase - 2) / 5.0E7 + dt = (timebase - 2) / 5.0e7 else: # The original case from non "A" series - warnings.warn("The model PS4000a you are using may not be " - "fully supported", stacklevel=2) + warnings.warn( + "The model PS4000a you are using may not be " + "fully supported", + stacklevel=2, + ) if timebase < 3: - dt = 2. ** timebase / 8e7 + dt = 2.0 ** timebase / 8e7 else: dt = (timebase - 1) / 2e7 return dt return dt - def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, - segmentIndex): + def _lowLevelSetDataBuffer( + self, channel, data, downSampleMode, segmentIndex + ): """Set the data buffer. Be sure to call _lowLevelClearDataBuffer @@ -388,48 +472,72 @@ def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) - m = self.lib.ps4000aSetDataBuffer(c_int16(self.handle), - c_enum(channel), - dataPtr, c_uint32(numSamples), - c_uint32(segmentIndex), - c_uint32(downSampleMode)) + m = self.lib.ps4000aSetDataBuffer( + c_int16(self.handle), + c_enum(channel), + dataPtr, + c_uint32(numSamples), + c_uint32(segmentIndex), + c_uint32(downSampleMode), + ) self.checkResult(m) def _lowLevelClearDataBuffer(self, channel, segmentIndex): - m = self.lib.ps4000aSetDataBuffer(c_int16(self.handle), - c_enum(channel), - c_void_p(), c_uint32(0), c_uint32(0), - c_enum(0)) + m = self.lib.ps4000aSetDataBuffer( + c_int16(self.handle), + c_enum(channel), + c_void_p(), + c_uint32(0), + c_uint32(0), + c_enum(0), + ) self.checkResult(m) - def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, - downSampleMode, segmentIndex): + def _lowLevelGetValues( + self, + numSamples, + startIndex, + downSampleRatio, + downSampleMode, + segmentIndex, + ): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps4000aGetValues( - c_int16(self.handle), c_uint32(startIndex), - byref(numSamplesReturned), c_uint32(downSampleRatio), - c_enum(downSampleMode), c_uint16(segmentIndex), - byref(overflow)) + c_int16(self.handle), + c_uint32(startIndex), + byref(numSamplesReturned), + c_uint32(downSampleRatio), + c_enum(downSampleMode), + c_uint16(segmentIndex), + byref(overflow), + ) self.checkResult(m) return (numSamplesReturned.value, overflow.value) def _lowLevelSetDeviceResolution(self, resolution): self.resolution = resolution m = self.lib.ps4000aSetDeviceResolution( - c_int16(self.handle), - c_enum(resolution)) + c_int16(self.handle), c_enum(resolution) + ) self.checkResult(m) def _lowLevelChangePowerSource(self, powerstate): m = self.lib.ps4000aChangePowerSource( - c_int16(self.handle), - c_enum(powerstate)) + c_int16(self.handle), c_enum(powerstate) + ) self.checkResult(m) - def _lowLevelGetValuesBulk(self, numSamples, fromSegment, toSegment, - downSampleRatio, downSampleMode, overflow): + def _lowLevelGetValuesBulk( + self, + numSamples, + fromSegment, + toSegment, + downSampleRatio, + downSampleMode, + overflow, + ): """Copy data from several memory segments at once.""" overflowPoint = overflow.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps4000aGetValuesBulk( @@ -439,27 +547,40 @@ def _lowLevelGetValuesBulk(self, numSamples, fromSegment, toSegment, c_int32(toSegment), c_int32(downSampleRatio), c_enum(downSampleMode), - overflowPoint + overflowPoint, ) self.checkResult(m) - def _lowLevelSetDataBufferBulk(self, channel, data, segmentIndex, - downSampleMode): + def _lowLevelSetDataBufferBulk( + self, channel, data, segmentIndex, downSampleMode + ): """Just calls setDataBuffer with argument order changed. For compatibility with current picobase.py. """ - self._lowLevelSetDataBuffer(channel, data, downSampleMode, - segmentIndex) + self._lowLevelSetDataBuffer( + channel, data, downSampleMode, segmentIndex + ) #################################################################### # Untested functions below # # # #################################################################### - def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, - frequency, shots, triggerType, - triggerSource, stopFreq, increment, - dwellTime, sweepType, numSweeps): + def _lowLevelSetSigGenBuiltInSimple( + self, + offsetVoltage, + pkToPk, + waveType, + frequency, + shots, + triggerType, + triggerSource, + stopFreq, + increment, + dwellTime, + sweepType, + numSweeps, + ): if stopFreq is None: stopFreq = frequency @@ -468,16 +589,23 @@ def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), c_float(stopFreq), - c_float(increment), c_float(dwellTime), - c_enum(sweepType), c_enum(0), - c_uint32(shots), c_uint32(numSweeps), - c_enum(triggerType), c_enum(triggerSource), - c_int16(0)) + c_float(frequency), + c_float(stopFreq), + c_float(increment), + c_float(dwellTime), + c_enum(sweepType), + c_enum(0), + c_uint32(shots), + c_uint32(numSweeps), + c_enum(triggerType), + c_enum(triggerSource), + c_int16(0), + ) self.checkResult(m) - def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, - downSampleRatioMode, segmentIndex): + def _lowLevelGetMaxDownSampleRatio( + self, noOfUnaggregatedSamples, downSampleRatioMode, segmentIndex + ): maxDownSampleRatio = c_uint32() m = self.lib.ps4000aGetMaxDownSampleRatio( @@ -485,7 +613,8 @@ def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, c_uint32(noOfUnaggregatedSamples), byref(maxDownSampleRatio), c_enum(downSampleRatioMode), - c_uint16(segmentIndex)) + c_uint16(segmentIndex), + ) self.checkResult(m) return maxDownSampleRatio.value @@ -493,8 +622,9 @@ def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, def _lowLevelGetNoOfCaptures(self): nCaptures = c_uint32() - m = self.lib.ps4000aGetNoOfCaptures(c_int16(self.handle), - byref(nCaptures)) + m = self.lib.ps4000aGetNoOfCaptures( + c_int16(self.handle), byref(nCaptures) + ) self.checkResult(m) return nCaptures.value @@ -507,37 +637,39 @@ def _lowLevelGetTriggerTimeOffset(self, segmentIndex): c_int16(self.handle), byref(time), byref(timeUnits), - c_uint16(segmentIndex)) + c_uint16(segmentIndex), + ) self.checkResult(m) if timeUnits.value == 0: # PS4000a_FS - return time.value * 1E-15 + return time.value * 1e-15 elif timeUnits.value == 1: # PS4000a_PS - return time.value * 1E-12 + return time.value * 1e-12 elif timeUnits.value == 2: # PS4000a_NS - return time.value * 1E-9 + return time.value * 1e-9 elif timeUnits.value == 3: # PS4000a_US - return time.value * 1E-6 + return time.value * 1e-6 elif timeUnits.value == 4: # PS4000a_MS - return time.value * 1E-3 + return time.value * 1e-3 elif timeUnits.value == 5: # PS4000a_S - return time.value * 1E0 + return time.value * 1e0 else: raise TypeError("Unknown timeUnits %d" % timeUnits.value) def _lowLevelMemorySegments(self, nSegments): nMaxSamples = c_uint32() - m = self.lib.ps4000aMemorySegments(c_int16(self.handle), - c_uint16(nSegments), - byref(nMaxSamples)) + m = self.lib.ps4000aMemorySegments( + c_int16(self.handle), c_uint16(nSegments), byref(nMaxSamples) + ) self.checkResult(m) return nMaxSamples.value - def _lowLevelSetDataBuffers(self, channel, bufferMax, bufferMin, - downSampleRatioMode): + def _lowLevelSetDataBuffers( + self, channel, bufferMax, bufferMin, downSampleRatioMode + ): bufferMaxPtr = bufferMax.ctypes.data_as(POINTER(c_int16)) bufferMinPtr = bufferMin.ctypes.data_as(POINTER(c_int16)) bufferLth = len(bufferMax) @@ -547,7 +679,8 @@ def _lowLevelSetDataBuffers(self, channel, bufferMax, bufferMin, c_enum(channel), bufferMaxPtr, bufferMinPtr, - c_uint32(bufferLth)) + c_uint32(bufferLth), + ) self.checkResult(m) def _lowLevelClearDataBuffers(self, channel): @@ -556,13 +689,14 @@ def _lowLevelClearDataBuffers(self, channel): c_enum(channel), c_void_p(), c_void_p(), - c_uint32(0)) + c_uint32(0), + ) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, nCaptures): m = self.lib.ps4000aSetNoOfCaptures( - c_int16(self.handle), - c_uint16(nCaptures)) + c_int16(self.handle), c_uint16(nCaptures) + ) self.checkResult(m) # ETS Functions @@ -617,27 +751,35 @@ def _lowLevelGetValuesOverlappedBulk(self): pass # Streaming related functions - def _lowLevelGetStreamingLatestValues(self, lpPs4000Ready, - pParameter=c_void_p()): + def _lowLevelGetStreamingLatestValues( + self, lpPs4000Ready, pParameter=c_void_p() + ): m = self.lib.ps4000aGetStreamingLatestValues( - c_uint16(self.handle), - lpPs4000Ready, - pParameter) + c_uint16(self.handle), lpPs4000Ready, pParameter + ) self.checkResult(m) def _lowLevelNoOfStreamingValues(self): noOfValues = c_uint32() - m = self.lib.ps4000aNoOfStreamingValues(c_int16(self.handle), - byref(noOfValues)) + m = self.lib.ps4000aNoOfStreamingValues( + c_int16(self.handle), byref(noOfValues) + ) self.checkResult(m) return noOfValues.value - def _lowLevelRunStreaming(self, sampleInterval, sampleIntervalTimeUnits, - maxPreTriggerSamples, maxPostTriggerSamples, - autoStop, downSampleRatio, downSampleRatioMode, - overviewBufferSize): + def _lowLevelRunStreaming( + self, + sampleInterval, + sampleIntervalTimeUnits, + maxPreTriggerSamples, + maxPostTriggerSamples, + autoStop, + downSampleRatio, + downSampleRatioMode, + overviewBufferSize, + ): m = self.lib.ps4000aRunStreaming( c_int16(self.handle), byref(c_uint32(sampleInterval)), @@ -647,7 +789,8 @@ def _lowLevelRunStreaming(self, sampleInterval, sampleIntervalTimeUnits, c_int16(autoStop), c_uint32(downSampleRatio), c_enum(downSampleRatioMode), - c_uint32(overviewBufferSize)) + c_uint32(overviewBufferSize), + ) self.checkResult(m) diff --git a/picoscope/ps5000.py b/picoscope/ps5000.py index fdce198..6ceee36 100644 --- a/picoscope/ps5000.py +++ b/picoscope/ps5000.py @@ -58,8 +58,17 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import byref, POINTER, create_string_buffer, c_float, \ - c_int16, c_int32, c_uint32, c_uint64, c_void_p +from ctypes import ( + byref, + POINTER, + create_string_buffer, + c_float, + c_int16, + c_int32, + c_uint32, + c_uint64, + c_void_p, +) from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -80,35 +89,61 @@ class PS5000(_PicoscopeBase): # The 10V and 20V ranges are only allowed in high impedence modes CHANNEL_RANGE = [ - {"rangeV": 10E-3, "apivalue": 1, "rangeStr": "10 mV"}, - {"rangeV": 20E-3, "apivalue": 2, "rangeStr": "20 mV"}, - {"rangeV": 50E-3, "apivalue": 3, "rangeStr": "50 mV"}, - {"rangeV": 100E-3, "apivalue": 4, "rangeStr": "100 mV"}, - {"rangeV": 200E-3, "apivalue": 5, "rangeStr": "200 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}] + {"rangeV": 10e-3, "apivalue": 1, "rangeStr": "10 mV"}, + {"rangeV": 20e-3, "apivalue": 2, "rangeStr": "20 mV"}, + {"rangeV": 50e-3, "apivalue": 3, "rangeStr": "50 mV"}, + {"rangeV": 100e-3, "apivalue": 4, "rangeStr": "100 mV"}, + {"rangeV": 200e-3, "apivalue": 5, "rangeStr": "200 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] NUM_CHANNELS = 4 - CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, - "External": 4, "MaxChannels": 4, "TriggerAux": 5} + CHANNELS = { + "A": 0, + "B": 1, + "C": 2, + "D": 3, + "External": 4, + "MaxChannels": 4, + "TriggerAux": 5, + } CHANNEL_COUPLINGS = {"DC": 1, "AC": 0} - WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, - "RampUp": 3, "RampDown": 4, - "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, - "WhiteNoise": 9} + WAVE_TYPES = { + "Sine": 0, + "Square": 1, + "Triangle": 2, + "RampUp": 3, + "RampDown": 4, + "Sinc": 5, + "Gaussian": 6, + "HalfSine": 7, + "DCVoltage": 8, + "WhiteNoise": 9, + } SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} - SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, - "GateHigh": 2, "GateLow": 3} - SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, "AuxIn": 2, - "ExtIn": 3, "SoftTrig": 4, "TriggerRaw": 5} + SIGGEN_TRIGGER_TYPES = { + "Rising": 0, + "Falling": 1, + "GateHigh": 2, + "GateLow": 3, + } + SIGGEN_TRIGGER_SOURCES = { + "None": 0, + "ScopeTrig": 1, + "AuxIn": 2, + "ExtIn": 3, + "SoftTrig": 4, + "TriggerRaw": 5, + } # This is actually different depending on the AB/CD models # I wonder how we could detect the difference between the oscilloscopes @@ -122,7 +157,7 @@ class PS5000(_PicoscopeBase): AWGBufferAddressWidth = 14 AWGMaxSamples = 2 ** AWGBufferAddressWidth - AWGDACInterval = 5E-9 # in seconds + AWGDACInterval = 5e-9 # in seconds AWGDACFrequency = 1 / AWGDACInterval # Note this is NOT what is written in the Programming guide as of version @@ -136,18 +171,23 @@ class PS5000(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLLs.""" - if platform.system() == 'Linux': + if platform.system() == "Linux": from ctypes import cdll + # ok I don't know what is wrong with my installer, # but I need to include .so.2 self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so.2") - elif platform.system() == 'Darwin': + elif platform.system() == "Darwin": from picoscope.darwin_utils import LoadLibraryDarwin + self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) super(PS5000, self).__init__(serialNumber, connect) @@ -180,9 +220,9 @@ def _lowLevelOpenUnitProgress(self): progressPercent = c_int16() handle = c_int16() - m = self.lib.ps5000OpenUnitProgress(byref(handle), - byref(progressPercent), - byref(complete)) + m = self.lib.ps5000OpenUnitProgress( + byref(handle), byref(progressPercent), byref(complete) + ) self.checkResult(m) if complete.value != 0: @@ -207,22 +247,29 @@ def _lowLevelEnumerateUnits(self): serialLth = c_int16(count.value * (8 + 2)) serials = create_string_buffer(serialLth.value + 1) - m = self.lib.ps5000EnumerateUnits(byref(count), serials, - byref(serialLth)) + m = self.lib.ps5000EnumerateUnits( + byref(count), serials, byref(serialLth) + ) self.checkResult(m) - serialList = str(serials.value.decode('utf-8')).split(',') + serialList = str(serials.value.decode("utf-8")).split(",") serialList = [x.strip() for x in serialList] return serialList - def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, - BWLimited): - m = self.lib.ps5000SetChannel(c_int16(self.handle), c_enum(chNum), - c_int16(enabled), c_enum(coupling), - c_enum(VRange), c_float(VOffset), - c_enum(BWLimited)) # 2 for PS6404 + def _lowLevelSetChannel( + self, chNum, enabled, coupling, VRange, VOffset, BWLimited + ): + m = self.lib.ps5000SetChannel( + c_int16(self.handle), + c_enum(chNum), + c_int16(enabled), + c_enum(coupling), + c_enum(VRange), + c_float(VOffset), + c_enum(BWLimited), + ) # 2 for PS6404 self.checkResult(m) def _lowLevelStop(self): @@ -233,41 +280,67 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps6000GetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), byref(requiredSize), - c_enum(info)) + m = self.lib.ps6000GetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps5000GetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), - byref(requiredSize), c_enum(info)) + m = self.lib.ps5000GetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode('utf-8') + return s.value.decode("utf-8") def _lowLevelFlashLed(self, times): m = self.lib.ps5000FlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, - direction, delay, timeout_ms): + def _lowLevelSetSimpleTrigger( + self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms + ): m = self.lib.ps5000SetSimpleTrigger( - c_int16(self.handle), c_int16(enabled), - c_enum(trigsrc), c_int16(threshold_adc), - c_enum(direction), c_uint32(delay), c_int16(timeout_ms)) + c_int16(self.handle), + c_int16(enabled), + c_enum(trigsrc), + c_int16(threshold_adc), + c_enum(direction), + c_uint32(delay), + c_int16(timeout_ms), + ) self.checkResult(m) - def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, - timebase, oversample, segmentIndex): + def _lowLevelRunBlock( + self, + numPreTrigSamples, + numPostTrigSamples, + timebase, + oversample, + segmentIndex, + ): timeIndisposedMs = c_int32() m = self.lib.ps5000RunBlock( - c_int16(self.handle), c_uint32(numPreTrigSamples), - c_uint32(numPostTrigSamples), c_uint32(timebase), - c_int16(oversample), byref(timeIndisposedMs), - c_uint32(segmentIndex), c_void_p(), c_void_p()) + c_int16(self.handle), + c_uint32(numPreTrigSamples), + c_uint32(numPostTrigSamples), + c_uint32(timebase), + c_int16(oversample), + byref(timeIndisposedMs), + c_uint32(segmentIndex), + c_void_p(), + c_void_p(), + ) self.checkResult(m) return timeIndisposedMs.value @@ -285,20 +358,25 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): maxSamples = c_int32() sampleRate = c_float() - m = self.lib.ps5000GetTimebase2(c_int16(self.handle), c_uint32(tb), - c_uint32(noSamples), byref(sampleRate), - c_int16(oversample), byref(maxSamples), - c_uint32(segmentIndex)) + m = self.lib.ps5000GetTimebase2( + c_int16(self.handle), + c_uint32(tb), + c_uint32(noSamples), + byref(sampleRate), + c_int16(oversample), + byref(maxSamples), + c_uint32(segmentIndex), + ) self.checkResult(m) - return (sampleRate.value / 1.0E9, maxSamples.value) + return (sampleRate.value / 1.0e9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """Return sample time in seconds to timebase as int for API calls.""" - maxSampleTime = (((2 ** 32 - 1) - 2) / 125000000) + maxSampleTime = ((2 ** 32 - 1) - 2) / 125000000 - if sampleTimeS < 8E-9: - timebase = math.floor(math.log(sampleTimeS * 1E9, 2)) + if sampleTimeS < 8e-9: + timebase = math.floor(math.log(sampleTimeS * 1e9, 2)) timebase = max(timebase, 0) else: # Otherwise in range 2^32-1 @@ -314,13 +392,14 @@ def getTimeBaseNum(self, sampleTimeS): def getTimestepFromTimebase(self, timebase): """Return timebase to sampletime as seconds.""" if timebase < 3: - dt = 2. ** timebase / 1E9 + dt = 2.0 ** timebase / 1e9 else: - dt = (timebase - 2) / 125000000. + dt = (timebase - 2) / 125000000.0 return dt - def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, - segmentIndex): + def _lowLevelSetDataBuffer( + self, channel, data, downSampleMode, segmentIndex + ): """Set the data buffer. Be sure to call _lowLevelClearDataBuffer @@ -333,26 +412,45 @@ def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) - m = self.lib.ps5000SetDataBuffer(c_int16(self.handle), c_enum(channel), - dataPtr, c_uint32(numSamples), - c_enum(downSampleMode)) + m = self.lib.ps5000SetDataBuffer( + c_int16(self.handle), + c_enum(channel), + dataPtr, + c_uint32(numSamples), + c_enum(downSampleMode), + ) self.checkResult(m) def _lowLevelClearDataBuffer(self, channel, segmentIndex): - m = self.lib.ps5000SetDataBuffer(c_int16(self.handle), c_enum(channel), - c_void_p(), c_uint32(0), c_enum(0)) + m = self.lib.ps5000SetDataBuffer( + c_int16(self.handle), + c_enum(channel), + c_void_p(), + c_uint32(0), + c_enum(0), + ) self.checkResult(m) - def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, - downSampleMode, segmentIndex): + def _lowLevelGetValues( + self, + numSamples, + startIndex, + downSampleRatio, + downSampleMode, + segmentIndex, + ): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps5000GetValues( - c_int16(self.handle), c_uint32(startIndex), - byref(numSamplesReturned), c_uint32(downSampleRatio), - c_enum(downSampleMode), c_uint32(segmentIndex), - byref(overflow)) + c_int16(self.handle), + c_uint32(startIndex), + byref(numSamplesReturned), + c_uint32(downSampleRatio), + c_enum(downSampleMode), + c_uint32(segmentIndex), + byref(overflow), + ) self.checkResult(m) return (numSamplesReturned.value, overflow.value) @@ -360,36 +458,56 @@ def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, # Untested functions below # # # #################################################################### - def _lowLevelSetAWGSimpleDeltaPhase(self, waveform, deltaPhase, - offsetVoltage, pkToPk, indexMode, - shots, triggerType, triggerSource): + def _lowLevelSetAWGSimpleDeltaPhase( + self, + waveform, + deltaPhase, + offsetVoltage, + pkToPk, + indexMode, + shots, + triggerType, + triggerSource, + ): """Waveform should be an array of shorts.""" waveformPtr = waveform.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps5000SetSigGenArbitrary( c_int16(self.handle), - c_uint32(int(offsetVoltage * 1E6)), # offset voltage in microvolts - c_uint32(int(pkToPk * 1E6)), # pkToPk in microvolts - c_uint32(int(deltaPhase)), # startDeltaPhase - c_uint32(int(deltaPhase)), # stopDeltaPhase - c_uint32(0), # deltaPhaseIncrement - c_uint32(0), # dwellCount - waveformPtr, # arbitraryWaveform - c_int32(len(waveform)), # arbitraryWaveformSize - c_enum(0), # sweepType for deltaPhase - c_enum(0), # operation (adding random noise and whatnot) - c_enum(indexMode), # single, dual, quad + c_uint32(int(offsetVoltage * 1e6)), # offset voltage in microvolts + c_uint32(int(pkToPk * 1e6)), # pkToPk in microvolts + c_uint32(int(deltaPhase)), # startDeltaPhase + c_uint32(int(deltaPhase)), # stopDeltaPhase + c_uint32(0), # deltaPhaseIncrement + c_uint32(0), # dwellCount + waveformPtr, # arbitraryWaveform + c_int32(len(waveform)), # arbitraryWaveformSize + c_enum(0), # sweepType for deltaPhase + c_enum(0), # operation (adding random noise and whatnot) + c_enum(indexMode), # single, dual, quad c_uint32(shots), - c_uint32(0), # sweeps + c_uint32(0), # sweeps c_uint32(triggerType), c_uint32(triggerSource), - c_int16(0)) # extInThreshold + c_int16(0), + ) # extInThreshold self.checkResult(m) - def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, - frequency, shots, triggerType, - triggerSource, stopFreq, increment, - dwellTime, sweepType, numSweeps): + def _lowLevelSetSigGenBuiltInSimple( + self, + offsetVoltage, + pkToPk, + waveType, + frequency, + shots, + triggerType, + triggerSource, + stopFreq, + increment, + dwellTime, + sweepType, + numSweeps, + ): # TODO, I just noticed that V2 exists # Maybe change to V2 in the future @@ -401,12 +519,18 @@ def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), c_float(stopFreq), - c_float(increment), c_float(dwellTime), - c_enum(sweepType), c_enum(0), - c_uint32(shots), c_uint32(numSweeps), - c_enum(triggerType), c_enum(triggerSource), - c_int16(0)) + c_float(frequency), + c_float(stopFreq), + c_float(increment), + c_float(dwellTime), + c_enum(sweepType), + c_enum(0), + c_uint32(shots), + c_uint32(numSweeps), + c_enum(triggerType), + c_enum(triggerSource), + c_int16(0), + ) self.checkResult(m) def _lowLevelGetAnalogueOffset(self, range, coupling): @@ -415,20 +539,28 @@ def _lowLevelGetAnalogueOffset(self, range, coupling): minimumVoltage = c_float() m = self.lib.ps5000GetAnalogueOffset( - c_int16(self.handle), c_enum(range), c_enum(coupling), - byref(maximumVoltage), byref(minimumVoltage)) + c_int16(self.handle), + c_enum(range), + c_enum(coupling), + byref(maximumVoltage), + byref(minimumVoltage), + ) self.checkResult(m) return (maximumVoltage.value, minimumVoltage.value) - def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, - downSampleRatioMode, segmentIndex): + def _lowLevelGetMaxDownSampleRatio( + self, noOfUnaggregatedSamples, downSampleRatioMode, segmentIndex + ): maxDownSampleRatio = c_uint32() m = self.lib.ps5000GetMaxDownSampleRatio( - c_int16(self.handle), c_uint32(noOfUnaggregatedSamples), + c_int16(self.handle), + c_uint32(noOfUnaggregatedSamples), byref(maxDownSampleRatio), - c_enum(downSampleRatioMode), c_uint32(segmentIndex)) + c_enum(downSampleRatioMode), + c_uint32(segmentIndex), + ) self.checkResult(m) return maxDownSampleRatio.value @@ -436,8 +568,9 @@ def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, def _lowLevelGetNoOfCaptures(self): nCaptures = c_uint32() - m = self.lib.ps5000GetNoOfCaptures(c_int16(self.handle), - byref(nCaptures)) + m = self.lib.ps5000GetNoOfCaptures( + c_int16(self.handle), byref(nCaptures) + ) self.checkResult(m) return nCaptures.value @@ -447,101 +580,132 @@ def _lowLevelGetTriggerTimeOffset(self, segmentIndex): timeUnits = c_enum() m = self.lib.ps5000GetTriggerTimeOffset64( - c_int16(self.handle), byref(time), - byref(timeUnits), c_uint32(segmentIndex)) + c_int16(self.handle), + byref(time), + byref(timeUnits), + c_uint32(segmentIndex), + ) self.checkResult(m) - if timeUnits.value == 0: # PS5000_FS - return time.value * 1E-15 + if timeUnits.value == 0: # PS5000_FS + return time.value * 1e-15 elif timeUnits.value == 1: # PS5000_PS - return time.value * 1E-12 + return time.value * 1e-12 elif timeUnits.value == 2: # PS5000_NS - return time.value * 1E-9 + return time.value * 1e-9 elif timeUnits.value == 3: # PS5000_US - return time.value * 1E-6 + return time.value * 1e-6 elif timeUnits.value == 4: # PS5000_MS - return time.value * 1E-3 + return time.value * 1e-3 elif timeUnits.value == 5: # PS5000_S - return time.value * 1E0 + return time.value * 1e0 else: raise TypeError("Unknown timeUnits %d" % timeUnits.value) def _lowLevelMemorySegments(self, nSegments): nMaxSamples = c_uint32() - m = self.lib.ps5000MemorySegments(c_int16(self.handle), - c_uint32(nSegments), - byref(nMaxSamples)) + m = self.lib.ps5000MemorySegments( + c_int16(self.handle), c_uint32(nSegments), byref(nMaxSamples) + ) self.checkResult(m) return nMaxSamples.value - def _lowLevelSetDataBuffers(self, channel, bufferMax, bufferMin, - downSampleRatioMode): + def _lowLevelSetDataBuffers( + self, channel, bufferMax, bufferMin, downSampleRatioMode + ): bufferMaxPtr = bufferMax.ctypes.data_as(POINTER(c_int16)) bufferMinPtr = bufferMin.ctypes.data_as(POINTER(c_int16)) bufferLth = len(bufferMax) - m = self.lib.ps5000SetDataBuffers(c_int16(self.handle), - c_enum(channel), - bufferMaxPtr, bufferMinPtr, - c_uint32(bufferLth), - c_enum(downSampleRatioMode)) + m = self.lib.ps5000SetDataBuffers( + c_int16(self.handle), + c_enum(channel), + bufferMaxPtr, + bufferMinPtr, + c_uint32(bufferLth), + c_enum(downSampleRatioMode), + ) self.checkResult(m) def _lowLevelClearDataBuffers(self, channel): m = self.lib.ps5000SetDataBuffers( - c_int16(self.handle), c_enum(channel), - c_void_p(), c_void_p(), c_uint32(0), c_enum(0)) + c_int16(self.handle), + c_enum(channel), + c_void_p(), + c_void_p(), + c_uint32(0), + c_enum(0), + ) self.checkResult(m) # Bulk values. # These would be nice, but the user would have to provide us # with an array. # we would have to make sure that it is contiguous amonts other things - def _lowLevelGetValuesBulk(self, - numSamples, fromSegmentIndex, toSegmentIndex, - downSampleRatio, downSampleRatioMode, - overflow): + def _lowLevelGetValuesBulk( + self, + numSamples, + fromSegmentIndex, + toSegmentIndex, + downSampleRatio, + downSampleRatioMode, + overflow, + ): noOfSamples = c_uint32(numSamples) m = self.lib.ps5000GetValuesBulk( c_int16(self.handle), byref(noOfSamples), - c_uint32(fromSegmentIndex), c_uint32(toSegmentIndex), - c_uint32(downSampleRatio), c_enum(downSampleRatioMode), - overflow.ctypes.data_as(POINTER(c_int16)) - ) + c_uint32(fromSegmentIndex), + c_uint32(toSegmentIndex), + c_uint32(downSampleRatio), + c_enum(downSampleRatioMode), + overflow.ctypes.data_as(POINTER(c_int16)), + ) self.checkResult(m) return noOfSamples.value - def _lowLevelSetDataBufferBulk(self, channel, buffer, waveform, - downSampleRatioMode): + def _lowLevelSetDataBufferBulk( + self, channel, buffer, waveform, downSampleRatioMode + ): bufferPtr = buffer.ctypes.data_as(POINTER(c_int16)) bufferLth = len(buffer) m = self.lib.ps5000SetDataBufferBulk( c_int16(self.handle), - c_enum(channel), bufferPtr, c_uint32(bufferLth), - c_uint32(waveform), c_enum(downSampleRatioMode)) + c_enum(channel), + bufferPtr, + c_uint32(bufferLth), + c_uint32(waveform), + c_enum(downSampleRatioMode), + ) self.checkResult(m) - def _lowLevelSetDataBuffersBulk(self, channel, bufferMax, bufferMin, - waveform, downSampleRatioMode): + def _lowLevelSetDataBuffersBulk( + self, channel, bufferMax, bufferMin, waveform, downSampleRatioMode + ): bufferMaxPtr = bufferMax.ctypes.data_as(POINTER(c_int16)) bufferMinPtr = bufferMin.ctypes.data_as(POINTER(c_int16)) bufferLth = len(bufferMax) m = self.lib.ps5000SetDataBuffersBulk( - c_int16(self.handle), c_enum(channel), - bufferMaxPtr, bufferMinPtr, c_uint32(bufferLth), - c_uint32(waveform), c_enum(downSampleRatioMode)) + c_int16(self.handle), + c_enum(channel), + bufferMaxPtr, + bufferMinPtr, + c_uint32(bufferLth), + c_uint32(waveform), + c_enum(downSampleRatioMode), + ) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, nCaptures): - m = self.lib.ps5000SetNoOfCaptures(c_int16(self.handle), - c_uint32(nCaptures)) + m = self.lib.ps5000SetNoOfCaptures( + c_int16(self.handle), c_uint32(nCaptures) + ) self.checkResult(m) # ETS Functions @@ -602,8 +766,9 @@ def _lowLevelGetStreamingLatestValues(): def _lowLevelNoOfStreamingValues(self): noOfValues = c_uint32() - m = self.lib.ps5000NoOfStreamingValues(c_int16(self.handle), - byref(noOfValues)) + m = self.lib.ps5000NoOfStreamingValues( + c_int16(self.handle), byref(noOfValues) + ) self.checkResult(m) return noOfValues.value diff --git a/picoscope/ps5000a.py b/picoscope/ps5000a.py index 2417378..b426ebe 100644 --- a/picoscope/ps5000a.py +++ b/picoscope/ps5000a.py @@ -55,8 +55,17 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import byref, POINTER, create_string_buffer, c_float, \ - c_int16, c_int32, c_uint32, c_void_p, c_int64 +from ctypes import ( + byref, + POINTER, + create_string_buffer, + c_float, + c_int16, + c_int32, + c_uint32, + c_void_p, + c_int64, +) from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -68,39 +77,65 @@ class PS5000a(_PicoscopeBase): LIBNAME = "ps5000a" NUM_CHANNELS = 4 - CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, - "External": 4, "MaxChannels": 4, "TriggerAux": 5} + CHANNELS = { + "A": 0, + "B": 1, + "C": 2, + "D": 3, + "External": 4, + "MaxChannels": 4, + "TriggerAux": 5, + } ADC_RESOLUTIONS = {"8": 0, "12": 1, "14": 2, "15": 3, "16": 4} - CHANNEL_RANGE = [{"rangeV": 10E-3, "apivalue": 0, "rangeStr": "10 mV"}, - {"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + CHANNEL_RANGE = [ + {"rangeV": 10e-3, "apivalue": 0, "rangeStr": "10 mV"}, + {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] CHANNEL_COUPLINGS = {"DC": 1, "AC": 0} # has_sig_gen = True - WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, - "RampUp": 3, "RampDown": 4, - "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, - "WhiteNoise": 9} + WAVE_TYPES = { + "Sine": 0, + "Square": 1, + "Triangle": 2, + "RampUp": 3, + "RampDown": 4, + "Sinc": 5, + "Gaussian": 6, + "HalfSine": 7, + "DCVoltage": 8, + "WhiteNoise": 9, + } SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} - SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, - "GateHigh": 2, "GateLow": 3} - SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, "AuxIn": 2, - "ExtIn": 3, "SoftTrig": 4, "TriggerRaw": 5} + SIGGEN_TRIGGER_TYPES = { + "Rising": 0, + "Falling": 1, + "GateHigh": 2, + "GateLow": 3, + } + SIGGEN_TRIGGER_SOURCES = { + "None": 0, + "ScopeTrig": 1, + "AuxIn": 2, + "ExtIn": 3, + "SoftTrig": 4, + "TriggerRaw": 5, + } # This is actually different depending on the AB/CD models # I wonder how we could detect the difference between the oscilloscopes @@ -112,7 +147,7 @@ class PS5000a(_PicoscopeBase): AWGPhaseAccumulatorSize = 32 - AWGDACInterval = 5E-9 # in seconds + AWGDACInterval = 5e-9 # in seconds AWGDACFrequency = 1 / AWGDACInterval AWG_INDEX_MODES = {"Single": 0, "Dual": 1, "Quad": 2} @@ -126,16 +161,21 @@ class PS5000a(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLL etc.""" - if platform.system() == 'Linux': + if platform.system() == "Linux": from ctypes import cdll + self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so") - elif platform.system() == 'Darwin': + elif platform.system() == "Darwin": from picoscope.darwin_utils import LoadLibraryDarwin + self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) self.resolution = self.ADC_RESOLUTIONS["8"] @@ -148,8 +188,9 @@ def _lowLevelOpenUnit(self, sn): else: serialNullTermStr = None # Passing None is the same as passing NULL - m = self.lib.ps5000aOpenUnit(byref(c_handle), serialNullTermStr, - self.resolution) + m = self.lib.ps5000aOpenUnit( + byref(c_handle), serialNullTermStr, self.resolution + ) self.handle = c_handle.value # This will check if the power supply is not connected @@ -170,18 +211,18 @@ def _lowLevelOpenUnit(self, sn): # Model 5444B identifies itself properly in VariantInfo, I will assume # the others do as well. - self.model = self.getUnitInfo('VariantInfo') + self.model = self.getUnitInfo("VariantInfo") # print("Checking variant, found: " + str(self.model)) - if self.model in ('5244B', '5444B'): - self.AWGBufferAddressWidth = math.log(3 * 2**14, 2) + if self.model in ("5244B", "5444B"): + self.AWGBufferAddressWidth = math.log(3 * 2 ** 14, 2) self.AWGMaxVal = 32767 self.AWGMinVal = -32768 self.AWGMaxSamples = 49152 - elif self.model in ('5243B', '5443B', '5243D', '5443D'): + elif self.model in ("5243B", "5443B", "5243D", "5443D"): self.AWGBufferAddressWidth = 15 self.AWGMaxVal = 32767 self.AWGMinVal = -32768 - self.AWGMaxSamples = 2**self.AWGBufferAddressWidth + self.AWGMaxSamples = 2 ** self.AWGBufferAddressWidth else: # This is what the previous PS5000a used for all scopes. # I am leaving it the same, although I think the AWGMaxVal and @@ -194,17 +235,23 @@ def _lowLevelOpenUnit(self, sn): # http://www.picotech.com/support/topic13217.html self.AWGMaxVal = 0x0FFF self.AWGMinVal = 0x0000 - self.AWGMaxSamples = 2**self.AWGBufferAddressWidth + self.AWGMaxSamples = 2 ** self.AWGBufferAddressWidth def _lowLevelCloseUnit(self): m = self.lib.ps5000aCloseUnit(c_int16(self.handle)) self.checkResult(m) - def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, - bandwidth): - m = self.lib.ps5000aSetChannel(c_int16(self.handle), c_enum(chNum), - c_int16(enabled), c_enum(coupling), - c_enum(VRange), c_float(VOffset)) + def _lowLevelSetChannel( + self, chNum, enabled, coupling, VRange, VOffset, bandwidth + ): + m = self.lib.ps5000aSetChannel( + c_int16(self.handle), + c_enum(chNum), + c_int16(enabled), + c_enum(coupling), + c_enum(VRange), + c_float(VOffset), + ) self.checkResult(m) # The error this might through are @@ -222,17 +269,19 @@ def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, # change the bandwidth separately # changing the bandwidth would be it's own function (implemented below) if bandwidth: - m = self.lib.ps5000aSetBandwidthFilter(c_int16(self.handle), - c_enum(chNum), c_enum(1)) + m = self.lib.ps5000aSetBandwidthFilter( + c_int16(self.handle), c_enum(chNum), c_enum(1) + ) else: - m = self.lib.ps5000aSetBandwidthFilter(c_int16(self.handle), - c_enum(chNum), c_enum(0)) + m = self.lib.ps5000aSetBandwidthFilter( + c_int16(self.handle), c_enum(chNum), c_enum(0) + ) self.checkResult(m) def _lowLevelSetBandwidthFilter(self, channel, bandwidth): - m = self.lib.ps5000aSetBandwidthFilter(c_int16(self.handle), - c_enum(channel), - c_enum(bandwidth)) + m = self.lib.ps5000aSetBandwidthFilter( + c_int16(self.handle), c_enum(channel), c_enum(bandwidth) + ) self.checkResult(m) def _lowLevelStop(self): @@ -243,42 +292,67 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps5000aGetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), byref(requiredSize), - c_enum(info)) + m = self.lib.ps5000aGetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps5000aGetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), - byref(requiredSize), c_enum(info)) + m = self.lib.ps5000aGetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode('utf-8') + return s.value.decode("utf-8") def _lowLevelFlashLed(self, times): m = self.lib.ps5000aFlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, - direction, delay, timeout_ms): + def _lowLevelSetSimpleTrigger( + self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms + ): m = self.lib.ps5000aSetSimpleTrigger( - c_int16(self.handle), c_int16(enabled), - c_enum(trigsrc), c_int16(threshold_adc), - c_enum(direction), c_uint32(delay), c_int16(timeout_ms)) + c_int16(self.handle), + c_int16(enabled), + c_enum(trigsrc), + c_int16(threshold_adc), + c_enum(direction), + c_uint32(delay), + c_int16(timeout_ms), + ) self.checkResult(m) - def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, - timebase, oversample, segmentIndex): + def _lowLevelRunBlock( + self, + numPreTrigSamples, + numPostTrigSamples, + timebase, + oversample, + segmentIndex, + ): # Oversample is NOT used! timeIndisposedMs = c_int32() m = self.lib.ps5000aRunBlock( - c_int16(self.handle), c_uint32(numPreTrigSamples), - c_uint32(numPostTrigSamples), c_uint32(timebase), - byref(timeIndisposedMs), c_uint32(segmentIndex), - c_void_p(), c_void_p()) + c_int16(self.handle), + c_uint32(numPreTrigSamples), + c_uint32(numPostTrigSamples), + c_uint32(timebase), + byref(timeIndisposedMs), + c_uint32(segmentIndex), + c_void_p(), + c_void_p(), + ) self.checkResult(m) return timeIndisposedMs.value @@ -300,21 +374,24 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): maxSamples = c_int32() sampleRate = c_float() - m = self.lib.ps5000aGetTimebase2(c_int16(self.handle), c_uint32(tb), - c_uint32(noSamples), - byref(sampleRate), - byref(maxSamples), - c_uint32(segmentIndex)) + m = self.lib.ps5000aGetTimebase2( + c_int16(self.handle), + c_uint32(tb), + c_uint32(noSamples), + byref(sampleRate), + byref(maxSamples), + c_uint32(segmentIndex), + ) self.checkResult(m) - return (sampleRate.value / 1.0E9, maxSamples.value) + return (sampleRate.value / 1.0e9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """Convert sample time in S to something to pass to API Call.""" if self.resolution == self.ADC_RESOLUTIONS["8"]: - maxSampleTime = (((2 ** 32 - 1) - 2) / 125000000) - if sampleTimeS < 8.0E-9: - st = math.floor(math.log(sampleTimeS * 1E9, 2)) + maxSampleTime = ((2 ** 32 - 1) - 2) / 125000000 + if sampleTimeS < 8.0e-9: + st = math.floor(math.log(sampleTimeS * 1e9, 2)) st = max(st, 0) else: if sampleTimeS > maxSampleTime: @@ -322,9 +399,9 @@ def getTimeBaseNum(self, sampleTimeS): st = math.floor((sampleTimeS * 125000000) + 2) elif self.resolution == self.ADC_RESOLUTIONS["12"]: - maxSampleTime = (((2 ** 32 - 1) - 3) / 62500000) - if sampleTimeS < 16.0E-9: - st = math.floor(math.log(sampleTimeS * 5E8, 2)) + 1 + maxSampleTime = ((2 ** 32 - 1) - 3) / 62500000 + if sampleTimeS < 16.0e-9: + st = math.floor(math.log(sampleTimeS * 5e8, 2)) + 1 st = max(st, 1) else: if sampleTimeS > maxSampleTime: @@ -332,15 +409,16 @@ def getTimeBaseNum(self, sampleTimeS): st = math.floor((sampleTimeS * 62500000) + 3) elif (self.resolution == self.ADC_RESOLUTIONS["14"]) or ( - self.resolution == self.ADC_RESOLUTIONS["15"]): - maxSampleTime = (((2 ** 32 - 1) - 2) / 125000000) + self.resolution == self.ADC_RESOLUTIONS["15"] + ): + maxSampleTime = ((2 ** 32 - 1) - 2) / 125000000 if sampleTimeS > maxSampleTime: sampleTimeS = maxSampleTime st = math.floor((sampleTimeS * 125000000) + 2) st = max(st, 3) elif self.resolution == self.ADC_RESOLUTIONS["16"]: - maxSampleTime = (((2 ** 32 - 1) - 3) / 62500000) + maxSampleTime = ((2 ** 32 - 1) - 3) / 62500000 if sampleTimeS > maxSampleTime: sampleTimeS = maxSampleTime st = math.floor((sampleTimeS * 62500000) + 3) @@ -357,49 +435,60 @@ def getTimestepFromTimebase(self, timebase): """Return Timestep from timebase.""" if self.resolution == self.ADC_RESOLUTIONS["8"]: if timebase < 3: - dt = 2. ** timebase / 1.0E9 + dt = 2.0 ** timebase / 1.0e9 else: - dt = (timebase - 2.0) / 125000000. + dt = (timebase - 2.0) / 125000000.0 elif self.resolution == self.ADC_RESOLUTIONS["12"]: if timebase < 4: - dt = 2. ** (timebase - 1) / 5.0E8 + dt = 2.0 ** (timebase - 1) / 5.0e8 else: - dt = (timebase - 3.0) / 62500000. + dt = (timebase - 3.0) / 62500000.0 elif (self.resolution == self.ADC_RESOLUTIONS["14"]) or ( - self.resolution == self.ADC_RESOLUTIONS["15"]): - dt = (timebase - 2.0) / 125000000. + self.resolution == self.ADC_RESOLUTIONS["15"] + ): + dt = (timebase - 2.0) / 125000000.0 elif self.resolution == self.ADC_RESOLUTIONS["16"]: - dt = (timebase - 3.0) / 62500000. + dt = (timebase - 3.0) / 62500000.0 return dt - def _lowLevelSetAWGSimpleDeltaPhase(self, waveform, deltaPhase, - offsetVoltage, pkToPk, indexMode, - shots, triggerType, triggerSource): + def _lowLevelSetAWGSimpleDeltaPhase( + self, + waveform, + deltaPhase, + offsetVoltage, + pkToPk, + indexMode, + shots, + triggerType, + triggerSource, + ): """Waveform should be an array of shorts.""" waveformPtr = waveform.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps5000aSetSigGenArbitrary( c_int16(self.handle), - c_uint32(int(offsetVoltage * 1E6)), # offset voltage in microvolts - c_uint32(int(pkToPk * 1E6)), # pkToPk in microvolts - c_uint32(int(deltaPhase)), # startDeltaPhase - c_uint32(int(deltaPhase)), # stopDeltaPhase - c_uint32(0), # deltaPhaseIncrement - c_uint32(0), # dwellCount - waveformPtr, # arbitraryWaveform - c_int32(len(waveform)), # arbitraryWaveformSize - c_enum(0), # sweepType for deltaPhase - c_enum(0), # operation (adding random noise and whatnot) - c_enum(indexMode), # single, dual, quad + c_uint32(int(offsetVoltage * 1e6)), # offset voltage in microvolts + c_uint32(int(pkToPk * 1e6)), # pkToPk in microvolts + c_uint32(int(deltaPhase)), # startDeltaPhase + c_uint32(int(deltaPhase)), # stopDeltaPhase + c_uint32(0), # deltaPhaseIncrement + c_uint32(0), # dwellCount + waveformPtr, # arbitraryWaveform + c_int32(len(waveform)), # arbitraryWaveformSize + c_enum(0), # sweepType for deltaPhase + c_enum(0), # operation (adding random noise and whatnot) + c_enum(indexMode), # single, dual, quad c_uint32(shots), - c_uint32(0), # sweeps + c_uint32(0), # sweeps c_uint32(triggerType), c_uint32(triggerSource), - c_int16(0)) # extInThreshold + c_int16(0), + ) # extInThreshold self.checkResult(m) - def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, - segmentIndex): + def _lowLevelSetDataBuffer( + self, channel, data, downSampleMode, segmentIndex + ): """Set the data buffer. Be sure to call _lowLevelClearDataBuffer @@ -409,49 +498,76 @@ def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) - m = self.lib.ps5000aSetDataBuffer(c_int16(self.handle), - c_enum(channel), - dataPtr, c_int32(numSamples), - c_uint32(segmentIndex), - c_enum(downSampleMode)) + m = self.lib.ps5000aSetDataBuffer( + c_int16(self.handle), + c_enum(channel), + dataPtr, + c_int32(numSamples), + c_uint32(segmentIndex), + c_enum(downSampleMode), + ) self.checkResult(m) - def _lowLevelSetDataBufferBulk(self, channel, data, segmentIndex, - downSampleMode): + def _lowLevelSetDataBufferBulk( + self, channel, data, segmentIndex, downSampleMode + ): """Just calls setDataBuffer with argument order changed. For compatibility with current picobase.py. """ - self._lowLevelSetDataBuffer(channel, - data, - downSampleMode, - segmentIndex) + self._lowLevelSetDataBuffer( + channel, data, downSampleMode, segmentIndex + ) def _lowLevelClearDataBuffer(self, channel, segmentIndex): - m = self.lib.ps5000aSetDataBuffer(c_int16(self.handle), - c_enum(channel), - c_void_p(), c_uint32(0), - c_uint32(segmentIndex), - c_enum(0)) + m = self.lib.ps5000aSetDataBuffer( + c_int16(self.handle), + c_enum(channel), + c_void_p(), + c_uint32(0), + c_uint32(segmentIndex), + c_enum(0), + ) self.checkResult(m) - def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, - downSampleMode, segmentIndex): + def _lowLevelGetValues( + self, + numSamples, + startIndex, + downSampleRatio, + downSampleMode, + segmentIndex, + ): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps5000aGetValues( - c_int16(self.handle), c_uint32(startIndex), - byref(numSamplesReturned), c_uint32(downSampleRatio), - c_enum(downSampleMode), c_uint32(segmentIndex), - byref(overflow)) + c_int16(self.handle), + c_uint32(startIndex), + byref(numSamplesReturned), + c_uint32(downSampleRatio), + c_enum(downSampleMode), + c_uint32(segmentIndex), + byref(overflow), + ) self.checkResult(m) return (numSamplesReturned.value, overflow.value) - def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, - frequency, shots, triggerType, - triggerSource, stopFreq, increment, - dwellTime, sweepType, numSweeps): + def _lowLevelSetSigGenBuiltInSimple( + self, + offsetVoltage, + pkToPk, + waveType, + frequency, + shots, + triggerType, + triggerSource, + stopFreq, + increment, + dwellTime, + sweepType, + numSweeps, + ): # TODO, I just noticed that V2 exists # Maybe change to V2 in the future @@ -463,30 +579,43 @@ def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), c_float(stopFreq), - c_float(increment), c_float(dwellTime), - c_enum(sweepType), c_enum(0), - c_uint32(shots), c_uint32(numSweeps), - c_enum(triggerType), c_enum(triggerSource), - c_int16(0)) + c_float(frequency), + c_float(stopFreq), + c_float(increment), + c_float(dwellTime), + c_enum(sweepType), + c_enum(0), + c_uint32(shots), + c_uint32(numSweeps), + c_enum(triggerType), + c_enum(triggerSource), + c_int16(0), + ) self.checkResult(m) def _lowLevelSetDeviceResolution(self, resolution): self.resolution = resolution m = self.lib.ps5000aSetDeviceResolution( - c_int16(self.handle), - c_enum(resolution)) + c_int16(self.handle), c_enum(resolution) + ) self.checkResult(m) def _lowLevelChangePowerSource(self, powerstate): m = self.lib.ps5000aChangePowerSource( - c_int16(self.handle), - c_enum(powerstate)) + c_int16(self.handle), c_enum(powerstate) + ) self.checkResult(m) # Morgan's additions - def _lowLevelGetValuesBulk(self, numSamples, fromSegment, toSegment, - downSampleRatio, downSampleMode, overflow): + def _lowLevelGetValuesBulk( + self, + numSamples, + fromSegment, + toSegment, + downSampleRatio, + downSampleMode, + overflow, + ): """Copy data from several memory segments at once.""" overflowPoint = overflow.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps5000aGetValuesBulk( @@ -496,20 +625,21 @@ def _lowLevelGetValuesBulk(self, numSamples, fromSegment, toSegment, c_int32(toSegment), c_int32(downSampleRatio), c_enum(downSampleMode), - overflowPoint - ) + overflowPoint, + ) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, numCaptures): m = self.lib.ps5000aSetNoOfCaptures( - c_int16(self.handle), - c_uint32(numCaptures)) + c_int16(self.handle), c_uint32(numCaptures) + ) self.checkResult(m) def _lowLevelMemorySegments(self, numSegments): maxSamples = c_int32() m = self.lib.ps5000aMemorySegments( - c_int16(self.handle), c_uint32(numSegments), byref(maxSamples)) + c_int16(self.handle), c_uint32(numSegments), byref(maxSamples) + ) self.checkResult(m) return maxSamples.value @@ -523,20 +653,16 @@ def _lowLevelGetValuesTriggerTimeOffsetBulk(self, fromSegment, toSegment): nSegments = toSegment - fromSegment + 1 # time = c_int64() - times = np.ascontiguousarray( - np.zeros(nSegments, dtype=np.int64) - ) - timeUnits = np.ascontiguousarray( - np.zeros(nSegments, dtype=np.int32) - ) + times = np.ascontiguousarray(np.zeros(nSegments, dtype=np.int64)) + timeUnits = np.ascontiguousarray(np.zeros(nSegments, dtype=np.int32)) m = self.lib.ps5000aGetValuesTriggerTimeOffsetBulk64( c_int16(self.handle), times.ctypes.data_as(POINTER(c_int64)), timeUnits.ctypes.data_as(POINTER(c_enum)), c_uint32(fromSegment), - c_uint32(toSegment) - ) + c_uint32(toSegment), + ) self.checkResult(m) # timeUnits=np.array([self.TIME_UNITS[tu] for tu in timeUnits]) return times, timeUnits diff --git a/picoscope/ps6000.py b/picoscope/ps6000.py index a0beaf3..6cf279b 100644 --- a/picoscope/ps6000.py +++ b/picoscope/ps6000.py @@ -58,8 +58,18 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import byref, POINTER, create_string_buffer, c_float, \ - c_int8, c_int16, c_int32, c_uint32, c_uint64, c_void_p +from ctypes import ( + byref, + POINTER, + create_string_buffer, + c_float, + c_int8, + c_int16, + c_int32, + c_uint32, + c_uint64, + c_void_p, +) from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -80,36 +90,62 @@ class PS6000(_PicoscopeBase): # I don't think that the 50V range is allowed, but I left it there anyway # The 10V and 20V ranges are only allowed in high impedence modes - CHANNEL_RANGE = [{"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + CHANNEL_RANGE = [ + {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] NUM_CHANNELS = 4 - CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, - "External": 4, "MaxChannels": 4, "TriggerAux": 5} + CHANNELS = { + "A": 0, + "B": 1, + "C": 2, + "D": 3, + "External": 4, + "MaxChannels": 4, + "TriggerAux": 5, + } CHANNEL_COUPLINGS = {"DC50": 2, "DC": 1, "AC": 0} - WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, - "RampUp": 3, "RampDown": 4, - "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, - "WhiteNoise": 9} + WAVE_TYPES = { + "Sine": 0, + "Square": 1, + "Triangle": 2, + "RampUp": 3, + "RampDown": 4, + "Sinc": 5, + "Gaussian": 6, + "HalfSine": 7, + "DCVoltage": 8, + "WhiteNoise": 9, + } SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} - SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, - "GateHigh": 2, "GateLow": 3} - SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, "AuxIn": 2, - "ExtIn": 3, "SoftTrig": 4, "TriggerRaw": 5} + SIGGEN_TRIGGER_TYPES = { + "Rising": 0, + "Falling": 1, + "GateHigh": 2, + "GateLow": 3, + } + SIGGEN_TRIGGER_SOURCES = { + "None": 0, + "ScopeTrig": 1, + "AuxIn": 2, + "ExtIn": 3, + "SoftTrig": 4, + "TriggerRaw": 5, + } # This is actually different depending on the AB/CD models # I wonder how we could detect the difference between the oscilloscopes @@ -123,7 +159,7 @@ class PS6000(_PicoscopeBase): AWGBufferAddressWidth = 14 AWGMaxSamples = 2 ** AWGBufferAddressWidth - AWGDACInterval = 5E-9 # in seconds + AWGDACInterval = 5e-9 # in seconds AWGDACFrequency = 1 / AWGDACInterval # Note this is NOT what is written in the Programming guide as of version @@ -137,18 +173,23 @@ class PS6000(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLLs.""" - if platform.system() == 'Linux': + if platform.system() == "Linux": from ctypes import cdll + # ok I don't know what is wrong with my installer, # but I need to include .so.2 self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so.2") - elif platform.system() == 'Darwin': + elif platform.system() == "Darwin": from picoscope.darwin_utils import LoadLibraryDarwin + self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) super(PS6000, self).__init__(serialNumber, connect) @@ -181,9 +222,9 @@ def _lowLevelOpenUnitProgress(self): progressPercent = c_int16() handle = c_int16() - m = self.lib.ps6000OpenUnitProgress(byref(handle), - byref(progressPercent), - byref(complete)) + m = self.lib.ps6000OpenUnitProgress( + byref(handle), byref(progressPercent), byref(complete) + ) self.checkResult(m) if complete.value != 0: @@ -201,8 +242,9 @@ def _lowLevelEnumerateUnits(self): count = c_int16(0) serials = c_int8(0) serialLth = c_int16(0) - m = self.lib.ps6000EnumerateUnits(byref(count), byref(serials), - byref(serialLth)) + m = self.lib.ps6000EnumerateUnits( + byref(count), byref(serials), byref(serialLth) + ) self.checkResult(m) # a serial number is rouhgly 8 characters # an extra character for the comma @@ -211,22 +253,29 @@ def _lowLevelEnumerateUnits(self): serialLth = c_int16(count.value * (8 + 2)) serials = create_string_buffer(serialLth.value + 1) - m = self.lib.ps6000EnumerateUnits(byref(count), serials, - byref(serialLth)) + m = self.lib.ps6000EnumerateUnits( + byref(count), serials, byref(serialLth) + ) self.checkResult(m) - serialList = str(serials.value.decode('utf-8')).split(',') + serialList = str(serials.value.decode("utf-8")).split(",") serialList = [x.strip() for x in serialList] return serialList - def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, - BWLimited): - m = self.lib.ps6000SetChannel(c_int16(self.handle), c_enum(chNum), - c_int16(enabled), c_enum(coupling), - c_enum(VRange), c_float(VOffset), - c_enum(BWLimited)) # 2 for PS6404 + def _lowLevelSetChannel( + self, chNum, enabled, coupling, VRange, VOffset, BWLimited + ): + m = self.lib.ps6000SetChannel( + c_int16(self.handle), + c_enum(chNum), + c_int16(enabled), + c_enum(coupling), + c_enum(VRange), + c_float(VOffset), + c_enum(BWLimited), + ) # 2 for PS6404 self.checkResult(m) def _lowLevelStop(self): @@ -237,41 +286,67 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps6000GetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), byref(requiredSize), - c_enum(info)) + m = self.lib.ps6000GetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps6000GetUnitInfo(c_int16(self.handle), byref(s), - c_int16(len(s)), - byref(requiredSize), c_enum(info)) + m = self.lib.ps6000GetUnitInfo( + c_int16(self.handle), + byref(s), + c_int16(len(s)), + byref(requiredSize), + c_enum(info), + ) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode('utf-8') + return s.value.decode("utf-8") def _lowLevelFlashLed(self, times): m = self.lib.ps6000FlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, - direction, delay, timeout_ms): + def _lowLevelSetSimpleTrigger( + self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms + ): m = self.lib.ps6000SetSimpleTrigger( - c_int16(self.handle), c_int16(enabled), - c_enum(trigsrc), c_int16(threshold_adc), - c_enum(direction), c_uint32(delay), c_int16(timeout_ms)) + c_int16(self.handle), + c_int16(enabled), + c_enum(trigsrc), + c_int16(threshold_adc), + c_enum(direction), + c_uint32(delay), + c_int16(timeout_ms), + ) self.checkResult(m) - def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, - timebase, oversample, segmentIndex): + def _lowLevelRunBlock( + self, + numPreTrigSamples, + numPostTrigSamples, + timebase, + oversample, + segmentIndex, + ): timeIndisposedMs = c_int32() m = self.lib.ps6000RunBlock( - c_int16(self.handle), c_uint32(numPreTrigSamples), - c_uint32(numPostTrigSamples), c_uint32(timebase), - c_int16(oversample), byref(timeIndisposedMs), - c_uint32(segmentIndex), c_void_p(), c_void_p()) + c_int16(self.handle), + c_uint32(numPreTrigSamples), + c_uint32(numPostTrigSamples), + c_uint32(timebase), + c_int16(oversample), + byref(timeIndisposedMs), + c_uint32(segmentIndex), + c_void_p(), + c_void_p(), + ) self.checkResult(m) return timeIndisposedMs.value @@ -289,20 +364,25 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): maxSamples = c_int32() sampleRate = c_float() - m = self.lib.ps6000GetTimebase2(c_int16(self.handle), c_uint32(tb), - c_uint32(noSamples), byref(sampleRate), - c_int16(oversample), byref(maxSamples), - c_uint32(segmentIndex)) + m = self.lib.ps6000GetTimebase2( + c_int16(self.handle), + c_uint32(tb), + c_uint32(noSamples), + byref(sampleRate), + c_int16(oversample), + byref(maxSamples), + c_uint32(segmentIndex), + ) self.checkResult(m) - return (sampleRate.value / 1.0E9, maxSamples.value) + return (sampleRate.value / 1.0e9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """Return sample time in seconds to timebase as int for API calls.""" - maxSampleTime = (((2 ** 32 - 1) - 4) / 156250000) + maxSampleTime = ((2 ** 32 - 1) - 4) / 156250000 - if sampleTimeS < 6.4E-9: - timebase = math.floor(math.log(sampleTimeS * 5E9, 2)) + if sampleTimeS < 6.4e-9: + timebase = math.floor(math.log(sampleTimeS * 5e9, 2)) timebase = max(timebase, 0) else: # Otherwise in range 2^32-1 @@ -318,39 +398,49 @@ def getTimeBaseNum(self, sampleTimeS): def getTimestepFromTimebase(self, timebase): """Return timebase to sampletime as seconds.""" if timebase < 5: - dt = 2. ** timebase / 5E9 + dt = 2.0 ** timebase / 5e9 else: - dt = (timebase - 4.) / 156250000. + dt = (timebase - 4.0) / 156250000.0 return dt - def _lowLevelSetAWGSimpleDeltaPhase(self, waveform, deltaPhase, - offsetVoltage, pkToPk, indexMode, - shots, triggerType, triggerSource): + def _lowLevelSetAWGSimpleDeltaPhase( + self, + waveform, + deltaPhase, + offsetVoltage, + pkToPk, + indexMode, + shots, + triggerType, + triggerSource, + ): """Waveform should be an array of shorts.""" waveformPtr = waveform.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps6000SetSigGenArbitrary( c_int16(self.handle), - c_uint32(int(offsetVoltage * 1E6)), # offset voltage in microvolts - c_uint32(int(pkToPk * 1E6)), # pkToPk in microvolts - c_uint32(int(deltaPhase)), # startDeltaPhase - c_uint32(int(deltaPhase)), # stopDeltaPhase - c_uint32(0), # deltaPhaseIncrement - c_uint32(0), # dwellCount - waveformPtr, # arbitraryWaveform - c_int32(len(waveform)), # arbitraryWaveformSize - c_enum(0), # sweepType for deltaPhase - c_enum(0), # operation (adding random noise and whatnot) - c_enum(indexMode), # single, dual, quad + c_uint32(int(offsetVoltage * 1e6)), # offset voltage in microvolts + c_uint32(int(pkToPk * 1e6)), # pkToPk in microvolts + c_uint32(int(deltaPhase)), # startDeltaPhase + c_uint32(int(deltaPhase)), # stopDeltaPhase + c_uint32(0), # deltaPhaseIncrement + c_uint32(0), # dwellCount + waveformPtr, # arbitraryWaveform + c_int32(len(waveform)), # arbitraryWaveformSize + c_enum(0), # sweepType for deltaPhase + c_enum(0), # operation (adding random noise and whatnot) + c_enum(indexMode), # single, dual, quad c_uint32(shots), - c_uint32(0), # sweeps + c_uint32(0), # sweeps c_uint32(triggerType), c_uint32(triggerSource), - c_int16(0)) # extInThreshold + c_int16(0), + ) # extInThreshold self.checkResult(m) - def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, - segmentIndex): + def _lowLevelSetDataBuffer( + self, channel, data, downSampleMode, segmentIndex + ): """Set the data buffer. Be sure to call _lowLevelClearDataBuffer @@ -363,33 +453,63 @@ def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) - m = self.lib.ps6000SetDataBuffer(c_int16(self.handle), c_enum(channel), - dataPtr, c_uint32(numSamples), - c_enum(downSampleMode)) + m = self.lib.ps6000SetDataBuffer( + c_int16(self.handle), + c_enum(channel), + dataPtr, + c_uint32(numSamples), + c_enum(downSampleMode), + ) self.checkResult(m) def _lowLevelClearDataBuffer(self, channel, segmentIndex): - m = self.lib.ps6000SetDataBuffer(c_int16(self.handle), c_enum(channel), - c_void_p(), c_uint32(0), c_enum(0)) + m = self.lib.ps6000SetDataBuffer( + c_int16(self.handle), + c_enum(channel), + c_void_p(), + c_uint32(0), + c_enum(0), + ) self.checkResult(m) - def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, - downSampleMode, segmentIndex): + def _lowLevelGetValues( + self, + numSamples, + startIndex, + downSampleRatio, + downSampleMode, + segmentIndex, + ): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps6000GetValues( - c_int16(self.handle), c_uint32(startIndex), - byref(numSamplesReturned), c_uint32(downSampleRatio), - c_enum(downSampleMode), c_uint32(segmentIndex), - byref(overflow)) + c_int16(self.handle), + c_uint32(startIndex), + byref(numSamplesReturned), + c_uint32(downSampleRatio), + c_enum(downSampleMode), + c_uint32(segmentIndex), + byref(overflow), + ) self.checkResult(m) return (numSamplesReturned.value, overflow.value) - def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, - frequency, shots, triggerType, - triggerSource, stopFreq, increment, - dwellTime, sweepType, numSweeps): + def _lowLevelSetSigGenBuiltInSimple( + self, + offsetVoltage, + pkToPk, + waveType, + frequency, + shots, + triggerType, + triggerSource, + stopFreq, + increment, + dwellTime, + sweepType, + numSweeps, + ): # TODO, I just noticed that V2 exists # Maybe change to V2 in the future @@ -401,12 +521,18 @@ def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), c_float(stopFreq), - c_float(increment), c_float(dwellTime), - c_enum(sweepType), c_enum(0), - c_uint32(shots), c_uint32(numSweeps), - c_enum(triggerType), c_enum(triggerSource), - c_int16(0)) + c_float(frequency), + c_float(stopFreq), + c_float(increment), + c_float(dwellTime), + c_enum(sweepType), + c_enum(0), + c_uint32(shots), + c_uint32(numSweeps), + c_enum(triggerType), + c_enum(triggerSource), + c_int16(0), + ) self.checkResult(m) #################################################################### @@ -419,20 +545,28 @@ def _lowLevelGetAnalogueOffset(self, range, coupling): minimumVoltage = c_float() m = self.lib.ps6000GetAnalogueOffset( - c_int16(self.handle), c_enum(range), c_enum(coupling), - byref(maximumVoltage), byref(minimumVoltage)) + c_int16(self.handle), + c_enum(range), + c_enum(coupling), + byref(maximumVoltage), + byref(minimumVoltage), + ) self.checkResult(m) return (maximumVoltage.value, minimumVoltage.value) - def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, - downSampleRatioMode, segmentIndex): + def _lowLevelGetMaxDownSampleRatio( + self, noOfUnaggregatedSamples, downSampleRatioMode, segmentIndex + ): maxDownSampleRatio = c_uint32() m = self.lib.ps6000GetMaxDownSampleRatio( - c_int16(self.handle), c_uint32(noOfUnaggregatedSamples), + c_int16(self.handle), + c_uint32(noOfUnaggregatedSamples), byref(maxDownSampleRatio), - c_enum(downSampleRatioMode), c_uint32(segmentIndex)) + c_enum(downSampleRatioMode), + c_uint32(segmentIndex), + ) self.checkResult(m) return maxDownSampleRatio.value @@ -440,8 +574,9 @@ def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, def _lowLevelGetNoOfCaptures(self): nCaptures = c_uint32() - m = self.lib.ps6000GetNoOfCaptures(c_int16(self.handle), - byref(nCaptures)) + m = self.lib.ps6000GetNoOfCaptures( + c_int16(self.handle), byref(nCaptures) + ) self.checkResult(m) return nCaptures.value @@ -451,101 +586,132 @@ def _lowLevelGetTriggerTimeOffset(self, segmentIndex): timeUnits = c_enum() m = self.lib.ps6000GetTriggerTimeOffset64( - c_int16(self.handle), byref(time), - byref(timeUnits), c_uint32(segmentIndex)) + c_int16(self.handle), + byref(time), + byref(timeUnits), + c_uint32(segmentIndex), + ) self.checkResult(m) - if timeUnits.value == 0: # PS6000_FS - return time.value * 1E-15 + if timeUnits.value == 0: # PS6000_FS + return time.value * 1e-15 elif timeUnits.value == 1: # PS6000_PS - return time.value * 1E-12 + return time.value * 1e-12 elif timeUnits.value == 2: # PS6000_NS - return time.value * 1E-9 + return time.value * 1e-9 elif timeUnits.value == 3: # PS6000_US - return time.value * 1E-6 + return time.value * 1e-6 elif timeUnits.value == 4: # PS6000_MS - return time.value * 1E-3 + return time.value * 1e-3 elif timeUnits.value == 5: # PS6000_S - return time.value * 1E0 + return time.value * 1e0 else: raise TypeError("Unknown timeUnits %d" % timeUnits.value) def _lowLevelMemorySegments(self, nSegments): nMaxSamples = c_uint32() - m = self.lib.ps6000MemorySegments(c_int16(self.handle), - c_uint32(nSegments), - byref(nMaxSamples)) + m = self.lib.ps6000MemorySegments( + c_int16(self.handle), c_uint32(nSegments), byref(nMaxSamples) + ) self.checkResult(m) return nMaxSamples.value - def _lowLevelSetDataBuffers(self, channel, bufferMax, bufferMin, - downSampleRatioMode): + def _lowLevelSetDataBuffers( + self, channel, bufferMax, bufferMin, downSampleRatioMode + ): bufferMaxPtr = bufferMax.ctypes.data_as(POINTER(c_int16)) bufferMinPtr = bufferMin.ctypes.data_as(POINTER(c_int16)) bufferLth = len(bufferMax) - m = self.lib.ps6000SetDataBuffers(c_int16(self.handle), - c_enum(channel), - bufferMaxPtr, bufferMinPtr, - c_uint32(bufferLth), - c_enum(downSampleRatioMode)) + m = self.lib.ps6000SetDataBuffers( + c_int16(self.handle), + c_enum(channel), + bufferMaxPtr, + bufferMinPtr, + c_uint32(bufferLth), + c_enum(downSampleRatioMode), + ) self.checkResult(m) def _lowLevelClearDataBuffers(self, channel): m = self.lib.ps6000SetDataBuffers( - c_int16(self.handle), c_enum(channel), - c_void_p(), c_void_p(), c_uint32(0), c_enum(0)) + c_int16(self.handle), + c_enum(channel), + c_void_p(), + c_void_p(), + c_uint32(0), + c_enum(0), + ) self.checkResult(m) # Bulk values. # These would be nice, but the user would have to provide us # with an array. # we would have to make sure that it is contiguous amonts other things - def _lowLevelGetValuesBulk(self, - numSamples, fromSegmentIndex, toSegmentIndex, - downSampleRatio, downSampleRatioMode, - overflow): + def _lowLevelGetValuesBulk( + self, + numSamples, + fromSegmentIndex, + toSegmentIndex, + downSampleRatio, + downSampleRatioMode, + overflow, + ): noOfSamples = c_uint32(numSamples) m = self.lib.ps6000GetValuesBulk( c_int16(self.handle), byref(noOfSamples), - c_uint32(fromSegmentIndex), c_uint32(toSegmentIndex), - c_uint32(downSampleRatio), c_enum(downSampleRatioMode), - overflow.ctypes.data_as(POINTER(c_int16)) - ) + c_uint32(fromSegmentIndex), + c_uint32(toSegmentIndex), + c_uint32(downSampleRatio), + c_enum(downSampleRatioMode), + overflow.ctypes.data_as(POINTER(c_int16)), + ) self.checkResult(m) return noOfSamples.value - def _lowLevelSetDataBufferBulk(self, channel, buffer, waveform, - downSampleRatioMode): + def _lowLevelSetDataBufferBulk( + self, channel, buffer, waveform, downSampleRatioMode + ): bufferPtr = buffer.ctypes.data_as(POINTER(c_int16)) bufferLth = len(buffer) m = self.lib.ps6000SetDataBufferBulk( c_int16(self.handle), - c_enum(channel), bufferPtr, c_uint32(bufferLth), - c_uint32(waveform), c_enum(downSampleRatioMode)) + c_enum(channel), + bufferPtr, + c_uint32(bufferLth), + c_uint32(waveform), + c_enum(downSampleRatioMode), + ) self.checkResult(m) - def _lowLevelSetDataBuffersBulk(self, channel, bufferMax, bufferMin, - waveform, downSampleRatioMode): + def _lowLevelSetDataBuffersBulk( + self, channel, bufferMax, bufferMin, waveform, downSampleRatioMode + ): bufferMaxPtr = bufferMax.ctypes.data_as(POINTER(c_int16)) bufferMinPtr = bufferMin.ctypes.data_as(POINTER(c_int16)) bufferLth = len(bufferMax) m = self.lib.ps6000SetDataBuffersBulk( - c_int16(self.handle), c_enum(channel), - bufferMaxPtr, bufferMinPtr, c_uint32(bufferLth), - c_uint32(waveform), c_enum(downSampleRatioMode)) + c_int16(self.handle), + c_enum(channel), + bufferMaxPtr, + bufferMinPtr, + c_uint32(bufferLth), + c_uint32(waveform), + c_enum(downSampleRatioMode), + ) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, nCaptures): - m = self.lib.ps6000SetNoOfCaptures(c_int16(self.handle), - c_uint32(nCaptures)) + m = self.lib.ps6000SetNoOfCaptures( + c_int16(self.handle), c_uint32(nCaptures) + ) self.checkResult(m) # ETS Functions @@ -606,8 +772,9 @@ def _lowLevelGetStreamingLatestValues(): def _lowLevelNoOfStreamingValues(self): noOfValues = c_uint32() - m = self.lib.ps6000NoOfStreamingValues(c_int16(self.handle), - byref(noOfValues)) + m = self.lib.ps6000NoOfStreamingValues( + c_int16(self.handle), byref(noOfValues) + ) self.checkResult(m) return noOfValues.value From 717a617e6f99f1c2aa253dd1de1f6e6cf7e84d79 Mon Sep 17 00:00:00 2001 From: Jonah Shapiro Date: Fri, 9 Oct 2020 12:14:52 -0700 Subject: [PATCH 3/5] Revert "Fixed PEP8 issues" This reverts commit a44c2de8b7718c8cb67c1cd30c1e59f71deacff0. --- picoscope/ps2000.py | 233 ++++++--------------- picoscope/ps2000a.py | 453 +++++++++++++--------------------------- picoscope/ps3000.py | 215 ++++++------------- picoscope/ps3000a.py | 400 ++++++++++++----------------------- picoscope/ps4000.py | 440 ++++++++++++++------------------------- picoscope/ps4000a.py | 471 +++++++++++++++-------------------------- picoscope/ps5000.py | 477 ++++++++++++++---------------------------- picoscope/ps5000a.py | 442 ++++++++++++++------------------------- picoscope/ps6000.py | 485 ++++++++++++++----------------------------- 9 files changed, 1196 insertions(+), 2420 deletions(-) diff --git a/picoscope/ps2000.py b/picoscope/ps2000.py index d0b7fb7..f75f1b2 100644 --- a/picoscope/ps2000.py +++ b/picoscope/ps2000.py @@ -29,16 +29,8 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import ( - byref, - POINTER, - create_string_buffer, - c_float, - c_int16, - c_int32, - c_uint32, - c_void_p, -) +from ctypes import byref, POINTER, create_string_buffer, c_float, \ + c_int16, c_int32, c_uint32, c_void_p from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -84,32 +76,26 @@ class PS2000(_PicoscopeBase): NUM_CHANNELS = 2 CHANNELS = {"A": 0, "B": 1, "MaxChannels": 2} - THRESHOLD_TYPE = {"Rising": 0, "Falling": 1} + THRESHOLD_TYPE = {"Rising": 0, + "Falling": 1} CHANNEL_RANGE = [ - {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - ] + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}] CHANNEL_COUPLINGS = {"DC": 1, "AC": 0} # has_sig_gen = True - WAVE_TYPES = { - "Sine": 0, - "Square": 1, - "Triangle": 2, - "RampUp": 3, - "RampDown": 4, - "DCVoltage": 5, - } + WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, + "RampUp": 3, "RampDown": 4, "DCVoltage": 5} SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} @@ -120,34 +106,22 @@ class PS2000(_PicoscopeBase): MAX_TIMEBASES = 19 - UNIT_INFO_TYPES = { - "DriverVersion": 0x0, - "USBVersion": 0x1, - "HardwareVersion": 0x2, - "VariantInfo": 0x3, - "BatchAndSerial": 0x4, - "CalDate": 0x5, - "ErrorCode": 0x6, - "KernelVersion": 0x7, - } + UNIT_INFO_TYPES = {"DriverVersion": 0x0, + "USBVersion": 0x1, + "HardwareVersion": 0x2, + "VariantInfo": 0x3, + "BatchAndSerial": 0x4, + "CalDate": 0x5, + "ErrorCode": 0x6, + "KernelVersion": 0x7} channelBuffersPtr = [c_void_p(), c_void_p()] channelBuffersLen = [0, 0] - SIGGEN_TRIGGER_TYPES = { - "Rising": 0, - "Falling": 1, - "GateHigh": 2, - "GateLow": 3, - } - SIGGEN_TRIGGER_SOURCES = { - "None": 0, - "ScopeTrig": 1, - "AuxIn": 2, - "ExtIn": 3, - "SoftTrig": 4, - "TriggerRaw": 5, - } + SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, + "GateHigh": 2, "GateLow": 3} + SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, "AuxIn": 2, + "ExtIn": 3, "SoftTrig": 4, "TriggerRaw": 5} AWG_INDEX_MODES = {"Single": 0, "Dual": 1, "Quad": 2} @@ -160,21 +134,16 @@ class PS2000(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLL etc.""" - if platform.system() == "Linux": + if platform.system() == 'Linux': from ctypes import cdll - self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so") - elif platform.system() == "Darwin": + elif platform.system() == 'Darwin': from picoscope.darwin_utils import LoadLibraryDarwin - self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - - self.lib = windll.LoadLibrary( - find_library(str(self.LIBNAME + ".dll")) - ) + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) super(PS2000, self).__init__(serialNumber, connect) @@ -185,10 +154,8 @@ def _lowLevelOpenUnit(self, sn): m = self.lib.ps2000_open_unit() if m < 0: - raise IOError( - "Failed to Find PS2000 Unit." - + " Should you be using PS2000a driver?" - ) + raise IOError("Failed to Find PS2000 Unit." + + " Should you be using PS2000a driver?") self.handle = m self.suggested_time_units = self.TIME_UNITS["NS"] @@ -197,16 +164,11 @@ def _lowLevelCloseUnit(self): m = self.lib.ps2000_close_unit(c_int16(self.handle)) self.checkResult(m) - def _lowLevelSetChannel( - self, chNum, enabled, coupling, VRange, VOffset, BWLimited - ): + def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, + BWLimited): m = self.lib.ps2000_set_channel( - c_int16(self.handle), - c_enum(chNum), - c_int16(enabled), - c_enum(coupling), - c_enum(VRange), - ) + c_int16(self.handle), c_enum(chNum), c_int16(enabled), + c_enum(coupling), c_enum(VRange)) self.checkResult(m) def _lowLevelStop(self): @@ -217,43 +179,30 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) m = self.lib.ps2000_get_unit_info( - c_int16(self.handle), byref(s), c_int16(len(s)), c_enum(info) - ) + c_int16(self.handle), byref(s), c_int16(len(s)), c_enum(info)) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode("utf-8") + return s.value.decode('utf-8') def _lowLevelFlashLed(self, times): m = self.lib.ps2000_flash_led(c_int16(self.handle)) self.checkResult(m) - def _lowLevelSetSimpleTrigger( - self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms - ): + def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, + direction, delay, timeout_ms): # TODO: # Fix 'auto' which is where trigger occurs in block. Delay is not used m = self.lib.ps2000_set_trigger( - c_int16(self.handle), - c_enum(trigsrc), - c_int16(threshold_adc), - c_enum(direction), - c_int16(delay), - c_int16(timeout_ms), - ) + c_int16(self.handle), c_enum(trigsrc), c_int16(threshold_adc), + c_enum(direction), c_int16(delay), c_int16(timeout_ms)) self.checkResult(m) - def _lowLevelRunBlock( - self, - numPreTrigSamples, - numPostTrigSamples, - timebase, - oversample, - segmentIndex, - ): + def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, + timebase, oversample, segmentIndex): # NOT: Oversample is NOT used! # TODO: Fix 'delay' which is where trigger occurs in block @@ -262,12 +211,8 @@ def _lowLevelRunBlock( timeIndisposedMs = c_int32() m = self.lib.ps2000_run_block( - c_int16(self.handle), - c_uint32(numPostTrigSamples), - c_uint32(timebase), - c_int16(1), - byref(timeIndisposedMs), - ) + c_int16(self.handle), c_uint32(numPostTrigSamples), + c_uint32(timebase), c_int16(1), byref(timeIndisposedMs)) self.checkResult(m) return timeIndisposedMs.value @@ -289,20 +234,15 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): time_units = c_int16() m = self.lib.ps2000_get_timebase( - c_int16(self.handle), - c_int16(tb), - c_uint32(noSamples), - byref(time_interval), - byref(time_units), - c_int16(1), - byref(maxSamples), - ) + c_int16(self.handle), c_int16(tb), c_uint32(noSamples), + byref(time_interval), byref(time_units), c_int16(1), + byref(maxSamples)) self.checkResult(m) self.suggested_time_units = time_units.value - return (time_interval.value / 1.0e9, maxSamples.value) + return (time_interval.value / 1.0E9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """ps2000 doesn't seem to have published formula like other scopes.""" @@ -310,26 +250,20 @@ def getTimeBaseNum(self, sampleTimeS): timebases = [None] * self.MAX_TIMEBASES # Convert to nS - sampleTimenS = sampleTimeS * 1e9 + sampleTimenS = sampleTimeS * 1E9 tb = 0 while tb < self.MAX_TIMEBASES: rv = self.lib.ps2000_get_timebase( - c_int16(self.handle), - c_int16(tb), - c_uint32(512), - byref(time_interval), - c_void_p(), - c_int16(1), - c_void_p(), - ) + c_int16(self.handle), c_int16(tb), c_uint32(512), + byref(time_interval), c_void_p(), c_int16(1), c_void_p()) if rv != 0: timebases[tb] = time_interval.value tb += 1 # Figure out closest option - besterror = 1e99 + besterror = 1E99 bestindx = 0 for indx, val in enumerate(timebases): if val is not None: @@ -344,20 +278,13 @@ def getTimestepFromTimebase(self, timebase): """Return timestep from timebase.""" time_interval = c_int32() m = self.lib.ps2000_get_timebase( - c_int16(self.handle), - c_int16(timebase), - c_uint32(512), - byref(time_interval), - c_void_p(), - c_int16(1), - c_void_p(), - ) + c_int16(self.handle), c_int16(timebase), c_uint32(512), + byref(time_interval), c_void_p(), c_int16(1), c_void_p()) self.checkResult(m) - return time_interval.value / 1.0e9 + return (time_interval.value / 1.0E9) - def _lowLevelSetDataBuffer( - self, channel, data, downSampleMode, segmentIndex - ): + def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, + segmentIndex): dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) @@ -368,14 +295,8 @@ def _lowLevelClearDataBuffer(self, channel, segmentIndex): self.channelBuffersPtr[channel] = c_void_p() self.channelBuffersLen[channel] = 0 - def _lowLevelGetValues( - self, - numSamples, - startIndex, - downSampleRatio, - downSampleMode, - segmentIndex, - ): + def _lowLevelGetValues(self, numSamples, startIndex, + downSampleRatio, downSampleMode, segmentIndex): # TODO: Check overflow in channelBuffersLen against numSamples, # but need to not raise error if channelBuffersPtr is void @@ -385,30 +306,16 @@ def _lowLevelGetValues( c_int16(self.handle), self.channelBuffersPtr[0], self.channelBuffersPtr[1], - c_void_p(), - c_void_p(), - byref(overflow), - c_int32(numSamples), - ) + c_void_p(), c_void_p(), + byref(overflow), c_int32(numSamples)) self.checkResult(rv) return (rv, overflow.value) - def _lowLevelSetSigGenBuiltInSimple( - self, - offsetVoltage, - pkToPk, - waveType, - frequency, - shots, - triggerType, - triggerSource, - stopFreq, - increment, - dwellTime, - sweepType, - numSweeps, - ): + def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, + frequency, shots, triggerType, + triggerSource, stopFreq, increment, + dwellTime, sweepType, numSweeps): if stopFreq is None: stopFreq = frequency @@ -417,19 +324,15 @@ def _lowLevelSetSigGenBuiltInSimple( c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), - c_float(stopFreq), - c_float(increment), - c_float(dwellTime), - c_enum(sweepType), - c_uint32(numSweeps), - ) + c_float(frequency), c_float(stopFreq), + c_float(increment), c_float(dwellTime), c_enum(sweepType), + c_uint32(numSweeps)) self.checkResult(m) def checkResult(self, ec): """Check result of function calls, raise exception if not 0.""" # PS2000 differs from other drivers in that non-zero is good if ec == 0: - raise IOError("Error calling %s" % (inspect.stack()[1][3])) + raise IOError('Error calling %s' % (inspect.stack()[1][3])) return 0 diff --git a/picoscope/ps2000a.py b/picoscope/ps2000a.py index 3298c5c..ce34727 100644 --- a/picoscope/ps2000a.py +++ b/picoscope/ps2000a.py @@ -56,17 +56,8 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import ( - byref, - POINTER, - create_string_buffer, - c_float, - c_int16, - c_int32, - c_uint16, - c_uint32, - c_void_p, -) +from ctypes import byref, POINTER, create_string_buffer, c_float, \ + c_int16, c_int32, c_uint16, c_uint32, c_void_p from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -78,65 +69,39 @@ class PS2000a(_PicoscopeBase): LIBNAME = "ps2000a" NUM_CHANNELS = 4 - CHANNELS = { - "A": 0, - "B": 1, - "C": 2, - "D": 3, - "External": 4, - "MaxChannels": 4, - "TriggerAux": 5, - } + CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, + "External": 4, "MaxChannels": 4, "TriggerAux": 5} ADC_RESOLUTIONS = {"8": 0, "12": 1, "14": 2, "15": 3, "16": 4} - CHANNEL_RANGE = [ - {"rangeV": 10e-3, "apivalue": 0, "rangeStr": "10 mV"}, - {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + CHANNEL_RANGE = [{"rangeV": 10E-3, "apivalue": 0, "rangeStr": "10 mV"}, + {"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] CHANNEL_COUPLINGS = {"DC": 1, "AC": 0} # has_sig_gen = True - WAVE_TYPES = { - "Sine": 0, - "Square": 1, - "Triangle": 2, - "RampUp": 3, - "RampDown": 4, - "Sinc": 5, - "Gaussian": 6, - "HalfSine": 7, - "DCVoltage": 8, - "WhiteNoise": 9, - } + WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, + "RampUp": 3, "RampDown": 4, + "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, + "WhiteNoise": 9} SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} - SIGGEN_TRIGGER_TYPES = { - "Rising": 0, - "Falling": 1, - "GateHigh": 2, - "GateLow": 3, - } - SIGGEN_TRIGGER_SOURCES = { - "None": 0, - "ScopeTrig": 1, - "AuxIn": 2, - "ExtIn": 3, - "SoftTrig": 4, - "TriggerRaw": 5, - } + SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, + "GateHigh": 2, "GateLow": 3} + SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, "AuxIn": 2, + "ExtIn": 3, "SoftTrig": 4, "TriggerRaw": 5} # TIME_UNITS = {'PS2000A_FS':0,'PS2000A_PS':1, # 'PS2000A_NS':2,'PS2000A_US':3,'PS2000A_MS':4, @@ -162,19 +127,15 @@ class PS2000a(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLL etc.""" - if platform.system() == "Linux": + if platform.system() == 'Linux': from ctypes import cdll - self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so") - elif platform.system() == "Darwin": + elif platform.system() == 'Darwin': self.lib = self.loadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - - self.lib = windll.LoadLibrary( - find_library(str(self.LIBNAME + ".dll")) - ) + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) self.resolution = self.ADC_RESOLUTIONS["8"] @@ -194,83 +155,47 @@ def _lowLevelOpenUnit(self, sn): # The scaling factor used in the timebase calculation varies based on # the particular model. See section 2.8 (pg 27) of the 2000a # programmer's guide - self.model = self.getUnitInfo("VariantInfo") - if self.model in ("2205AMSO", "2206", "2206A", "2206B", "2405A"): + self.model = self.getUnitInfo('VariantInfo') + if self.model in ('2205AMSO', '2206', '2206A', '2206B', '2405A'): # 500 MS/s - self._timebase_to_timestep = ( - lambda n: (2 ** n / 5e8) if n < 3 else ((n - 2) / 625e5) - ) - self._timestep_to_timebase = ( - lambda t: math.log(t * 5e8, 2) - if t < 16e-9 - else ((t * 625e5) + 2) - ) - elif self.model in ( - "2206BMSO", - "2207", - "2207A", - "2207B", - "2207BMSO", - "2208", - "2208A", - "2208B", - "2208BMSO", - "2406B", - "2407B", - "2408B", - ): + self._timebase_to_timestep = \ + lambda n: (2**n / 5e8) if n < 3 else ((n - 2) / 625e5) + self._timestep_to_timebase = \ + lambda t: math.log(t * 5e8, 2) if t < 16e-9 else ( + (t * 625e5) + 2) + elif self.model in ('2206BMSO', '2207', '2207A', '2207B', '2207BMSO', + '2208', '2208A', '2208B', '2208BMSO', '2406B', + '2407B', '2408B'): # 1 GS/s - self._timebase_to_timestep = ( - lambda n: (2 ** n / 1e9) if n < 3 else ((n - 2) / 125e6) - ) - self._timestep_to_timebase = ( - lambda t: math.log(t * 1e9, 2) - if t < 8e-9 - else ((t * 125e6) + 2) - ) - elif self.model == "2205MSO": - self._timebase_to_timestep = ( - lambda n: (2 ** n / 2e8) if n < 1 else (n / 1e8) - ) - self._timestep_to_timebase = ( + self._timebase_to_timestep = lambda n: (2**n / 1e9) if n < 3 else ( + (n - 2) / 125e6) + self._timestep_to_timebase = \ + lambda t: math.log(t * 1e9, 2) if t < 8e-9 else ( + (t * 125e6) + 2) + elif self.model == '2205MSO': + self._timebase_to_timestep = \ + lambda n: (2**n / 2e8) if n < 1 else (n / 1e8) + self._timestep_to_timebase = \ lambda t: math.log(t * 2e8, 2) if t < 10e-9 else (t * 1e8) - ) else: raise ValueError("Unrecognised variant {}".format(self.model)) # The AWG parameters vary based on the particular model. See section # 3.51.2 of the 2000a programmer's guide - if self.model in ( - "2205AMSO", - "2206", - "2206A", - "2207", - "2207A", - "2208", - "2208A", - "2405A", - ): + if self.model in ('2205AMSO', '2206', '2206A', '2207', '2207A', '2208', + '2208A', '2405A'): self.AWGBufferAddressWidth = 13 - self.AWGDACInterval = 50e-9 - elif self.model in ( - "2206B", - "2206BMSO", - "2207B", - "2207BMSO", - "2208B", - "2208BMSO", - "2406B", - "2407B", - "2408B", - ): + self.AWGDACInterval = 50E-9 + elif self.model in ('2206B', '2206BMSO', '2207B', '2207BMSO', '2208B', + '2208BMSO', '2406B', '2407B', '2408B'): self.AWGBufferAddressWidth = 15 - self.AWGDACInterval = 50e-9 + self.AWGDACInterval = 50E-9 else: # The programmer's manual indicates that some older models have # these parameters. Just use them as a catch-all for any models # not listed above self.AWGBufferAddressWidth = 13 - self.AWGDACInterval = 20.83e-9 + self.AWGDACInterval = 20.83E-9 self.AWGMaxSamples = 2 ** self.AWGBufferAddressWidth self.AWGDACFrequency = 1 / self.AWGDACInterval @@ -279,17 +204,11 @@ def _lowLevelCloseUnit(self): m = self.lib.ps2000aCloseUnit(c_int16(self.handle)) self.checkResult(m) - def _lowLevelSetChannel( - self, chNum, enabled, coupling, VRange, VOffset, BWLimited - ): - m = self.lib.ps2000aSetChannel( - c_int16(self.handle), - c_enum(chNum), - c_int16(enabled), - c_enum(coupling), - c_enum(VRange), - c_float(VOffset), - ) + def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, + BWLimited): + m = self.lib.ps2000aSetChannel(c_int16(self.handle), c_enum(chNum), + c_int16(enabled), c_enum(coupling), + c_enum(VRange), c_float(VOffset)) self.checkResult(m) def _lowLevelStop(self): @@ -300,90 +219,63 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps2000aGetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps2000aGetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), byref(requiredSize), + c_enum(info)) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps2000aGetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps2000aGetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), + byref(requiredSize), c_enum(info)) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode("utf-8") + return s.value.decode('utf-8') def _lowLevelFlashLed(self, times): m = self.lib.ps2000aFlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger( - self, enabled, trigsrc, threshold_adc, direction, delay, auto - ): + def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, + direction, delay, auto): m = self.lib.ps2000aSetSimpleTrigger( - c_int16(self.handle), - c_int16(enabled), - c_enum(trigsrc), - c_int16(threshold_adc), - c_enum(direction), - c_uint32(delay), - c_int16(auto), - ) + c_int16(self.handle), c_int16(enabled), + c_enum(trigsrc), c_int16(threshold_adc), + c_enum(direction), c_uint32(delay), c_int16(auto)) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, numCaptures): m = self.lib.ps2000aSetNoOfCaptures( - c_int16(self.handle), c_uint16(numCaptures) - ) + c_int16(self.handle), c_uint16(numCaptures)) self.checkResult(m) def _lowLevelMemorySegments(self, numSegments): maxSamples = c_int32() - m = self.lib.ps2000aMemorySegments( - c_int16(self.handle), c_uint16(numSegments), byref(maxSamples) - ) + m = self.lib.ps2000aMemorySegments(c_int16(self.handle), + c_uint16(numSegments), + byref(maxSamples)) self.checkResult(m) return maxSamples.value def _lowLevelGetMaxSegments(self): maxSegments = c_int16() - m = self.lib.ps2000aGetMaxSegments( - c_int16(self.handle), byref(maxSegments) - ) + m = self.lib.ps2000aGetMaxSegments(c_int16(self.handle), + byref(maxSegments)) self.checkResult(m) return maxSegments.value - def _lowLevelRunBlock( - self, - numPreTrigSamples, - numPostTrigSamples, - timebase, - oversample, - segmentIndex, - ): + def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, + timebase, oversample, segmentIndex): # NOT: Oversample is NOT used! timeIndisposedMs = c_int32() m = self.lib.ps2000aRunBlock( - c_int16(self.handle), - c_uint32(numPreTrigSamples), - c_uint32(numPostTrigSamples), - c_uint32(timebase), - c_int16(oversample), - byref(timeIndisposedMs), + c_int16(self.handle), c_uint32(numPreTrigSamples), + c_uint32(numPostTrigSamples), c_uint32(timebase), + c_int16(oversample), byref(timeIndisposedMs), c_uint32(segmentIndex), - c_void_p(), - c_void_p(), - ) + c_void_p(), c_void_p()) self.checkResult(m) return timeIndisposedMs.value @@ -402,25 +294,17 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): intervalNanoSec = c_float() m = self.lib.ps2000aGetTimebase2( - c_int16(self.handle), - c_uint32(tb), - c_uint32(noSamples), - byref(intervalNanoSec), - c_int16(oversample), - byref(maxSamples), - c_uint32(segmentIndex), - ) + c_int16(self.handle), c_uint32(tb), c_uint32(noSamples), + byref(intervalNanoSec), c_int16(oversample), byref(maxSamples), + c_uint32(segmentIndex)) self.checkResult(m) # divide by 1e9 to return interval in seconds return (intervalNanoSec.value * 1e-9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """Convert sample time in S to something to pass to API Call.""" - clipped = np.clip( - math.floor(self._timestep_to_timebase(sampleTimeS)), - 0, - np.iinfo(np.int32).max, - ) + clipped = np.clip(math.floor(self._timestep_to_timebase(sampleTimeS)), + 0, np.iinfo(np.int32).max) return int(clipped) @@ -432,44 +316,34 @@ def getTimestepFromTimebase(self, timebase): """ return self._timebase_to_timestep(timebase) - def _lowLevelSetAWGSimpleDeltaPhase( - self, - waveform, - deltaPhase, - offsetVoltage, - pkToPk, - indexMode, - shots, - triggerType, - triggerSource, - ): + def _lowLevelSetAWGSimpleDeltaPhase(self, waveform, deltaPhase, + offsetVoltage, pkToPk, indexMode, + shots, triggerType, triggerSource): """Waveform should be an array of shorts.""" waveformPtr = waveform.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps2000aSetSigGenArbitrary( c_int16(self.handle), - c_uint32(int(offsetVoltage * 1e6)), # offset voltage in microvolts - c_uint32(int(pkToPk * 1e6)), # pkToPk in microvolts - c_uint32(int(deltaPhase)), # startDeltaPhase - c_uint32(int(deltaPhase)), # stopDeltaPhase - c_uint32(0), # deltaPhaseIncrement - c_uint32(0), # dwellCount - waveformPtr, # arbitraryWaveform - c_int32(len(waveform)), # arbitraryWaveformSize - c_enum(0), # sweepType for deltaPhase - c_enum(0), # operation (adding random noise and whatnot) - c_enum(indexMode), # single, dual, quad + c_uint32(int(offsetVoltage * 1E6)), # offset voltage in microvolts + c_uint32(int(pkToPk * 1E6)), # pkToPk in microvolts + c_uint32(int(deltaPhase)), # startDeltaPhase + c_uint32(int(deltaPhase)), # stopDeltaPhase + c_uint32(0), # deltaPhaseIncrement + c_uint32(0), # dwellCount + waveformPtr, # arbitraryWaveform + c_int32(len(waveform)), # arbitraryWaveformSize + c_enum(0), # sweepType for deltaPhase + c_enum(0), # operation (adding random noise and whatnot) + c_enum(indexMode), # single, dual, quad c_uint32(shots), - c_uint32(0), # sweeps + c_uint32(0), # sweeps c_uint32(triggerType), c_uint32(triggerSource), - c_int16(0), - ) # extInThreshold + c_int16(0)) # extInThreshold self.checkResult(m) - def _lowLevelSetDataBuffer( - self, channel, data, downSampleMode, segmentIndex - ): + def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, + segmentIndex): """Set the buffer for the picoscope. Be sure to call _lowLevelClearDataBuffer @@ -480,75 +354,47 @@ def _lowLevelSetDataBuffer( numSamples = len(data) m = self.lib.ps2000aSetDataBuffer( - c_int16(self.handle), - c_enum(channel), - dataPtr, - c_int32(numSamples), - c_uint32(segmentIndex), - c_enum(downSampleMode), - ) + c_int16(self.handle), c_enum(channel), dataPtr, + c_int32(numSamples), c_uint32(segmentIndex), + c_enum(downSampleMode)) self.checkResult(m) def _lowLevelSetMultipleDataBuffers(self, channel, data, downSampleMode): max_segments = self._lowLevelGetMaxSegments() if data.shape[0] < max_segments: raise ValueError( - "data array has fewer rows" - + " than current number of memory segments" - ) + "data array has fewer rows" + + " than current number of memory segments") if data.shape[1] < self.maxSamples: raise ValueError("data array has fewer columns than maxSamples") for i in range(max_segments): - m = self._lowLevelSetDataBuffer( - channel, data[i, :], downSampleMode, i - ) + m = self._lowLevelSetDataBuffer(channel, data[i, :], + downSampleMode, i) self.checkResult(m) def _lowLevelClearDataBuffer(self, channel, segmentIndex): """Clear the data in the picoscope.""" m = self.lib.ps2000aSetDataBuffer( - c_int16(self.handle), - c_enum(channel), - c_void_p(), - c_uint32(0), - c_uint32(segmentIndex), - c_enum(0), - ) + c_int16(self.handle), c_enum(channel), + c_void_p(), c_uint32(0), c_uint32(segmentIndex), c_enum(0)) self.checkResult(m) - def _lowLevelGetValues( - self, - numSamples, - startIndex, - downSampleRatio, - downSampleMode, - segmentIndex, - ): + def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, + downSampleMode, segmentIndex): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps2000aGetValues( - c_int16(self.handle), - c_uint32(startIndex), - byref(numSamplesReturned), - c_uint32(downSampleRatio), - c_enum(downSampleMode), - c_uint32(segmentIndex), - byref(overflow), - ) + c_int16(self.handle), c_uint32(startIndex), + byref(numSamplesReturned), c_uint32(downSampleRatio), + c_enum(downSampleMode), c_uint32(segmentIndex), + byref(overflow)) self.checkResult(m) return (numSamplesReturned.value, overflow.value) - def _lowLevelGetValuesBulk( - self, - numSamples, - fromSegment, - toSegment, - downSampleRatio, - downSampleMode, - overflow, - ): + def _lowLevelGetValuesBulk(self, numSamples, fromSegment, toSegment, + downSampleRatio, downSampleMode, overflow): m = self.lib.ps2000aGetValuesBulk( c_int16(self.handle), byref(c_int16(numSamples)), @@ -556,8 +402,8 @@ def _lowLevelGetValuesBulk( c_int16(toSegment), c_int32(downSampleRatio), c_int16(downSampleMode), - overflow.ctypes.data_as(POINTER(c_int16)), - ) + overflow.ctypes.data_as(POINTER(c_int16)) + ) self.checkResult(m) return overflow, numSamples @@ -571,31 +417,19 @@ def _lowLevelGetTriggerTimeOffset(self, segmentIndex): byref(timeLower), byref(timeUnits), c_uint32(segmentIndex), - ) + ) self.checkResult(m) # timeUpper and timeLower are the upper 4 and lower 4 bytes of a 64-bit # (8-byte) integer which is scaled by timeUnits to get the precise # trigger location - return ((timeUpper.value << 32) + timeLower.value) * self.TIME_UNITS[ - timeUnits.value - ] - - def _lowLevelSetSigGenBuiltInSimple( - self, - offsetVoltage, - pkToPk, - waveType, - frequency, - shots, - triggerType, - triggerSource, - stopFreq, - increment, - dwellTime, - sweepType, - numSweeps, - ): + return (((timeUpper.value << 32) + timeLower.value) * + self.TIME_UNITS[timeUnits.value]) + + def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, + frequency, shots, triggerType, + triggerSource, stopFreq, increment, + dwellTime, sweepType, numSweeps): # TODO, I just noticed that V2 exists # Maybe change to V2 in the future @@ -607,22 +441,15 @@ def _lowLevelSetSigGenBuiltInSimple( c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), - c_float(stopFreq), - c_float(increment), - c_float(dwellTime), - c_enum(sweepType), - c_enum(0), - c_uint32(shots), - c_uint32(numSweeps), - c_enum(triggerType), - c_enum(triggerSource), - c_int16(0), - ) + c_float(frequency), c_float(stopFreq), + c_float(increment), c_float(dwellTime), + c_enum(sweepType), c_enum(0), + c_uint32(shots), c_uint32(numSweeps), + c_enum(triggerType), c_enum(triggerSource), + c_int16(0)) self.checkResult(m) def _lowLevelSigGenSoftwareControl(self, triggerType): m = self.lib.ps2000aSigGenSoftwareControl( - c_int16(self.handle), c_enum(triggerType) - ) + c_int16(self.handle), c_enum(triggerType)) self.checkResult(m) diff --git a/picoscope/ps3000.py b/picoscope/ps3000.py index 9293bc9..40cc054 100644 --- a/picoscope/ps3000.py +++ b/picoscope/ps3000.py @@ -56,16 +56,8 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import ( - byref, - POINTER, - create_string_buffer, - c_float, - c_int16, - c_int32, - c_uint32, - c_void_p, -) +from ctypes import byref, POINTER, create_string_buffer, c_float, \ + c_int16, c_int32, c_uint32, c_void_p from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -79,32 +71,27 @@ class PS3000(_PicoscopeBase): NUM_CHANNELS = 2 CHANNELS = {"A": 0, "B": 1, "MaxChannels": 2} - THRESHOLD_TYPE = {"Rising": 0, "Falling": 1} + THRESHOLD_TYPE = {"Rising": 0, + "Falling": 1} CHANNEL_RANGE = [ - {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - ] + ] CHANNEL_COUPLINGS = {"DC": 1, "AC": 0} # has_sig_gen = True - WAVE_TYPES = { - "Sine": 0, - "Square": 1, - "Triangle": 2, - "RampUp": 3, - "RampDown": 4, - "DCVoltage": 5, - } + WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, + "RampUp": 3, "RampDown": 4, "DCVoltage": 5} SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} @@ -115,16 +102,14 @@ class PS3000(_PicoscopeBase): MAX_TIMEBASES = 19 - UNIT_INFO_TYPES = { - "DriverVersion": 0x0, - "USBVersion": 0x1, - "HardwareVersion": 0x2, - "VariantInfo": 0x3, - "BatchAndSerial": 0x4, - "CalDate": 0x5, - "ErrorCode": 0x6, - "KernelVersion": 0x7, - } + UNIT_INFO_TYPES = {"DriverVersion": 0x0, + "USBVersion": 0x1, + "HardwareVersion": 0x2, + "VariantInfo": 0x3, + "BatchAndSerial": 0x4, + "CalDate": 0x5, + "ErrorCode": 0x6, + "KernelVersion": 0x7} channelBuffersPtr = [c_void_p(), c_void_p()] channelBuffersLen = [0, 0] @@ -136,21 +121,16 @@ class PS3000(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLL etc.""" - if platform.system() == "Linux": + if platform.system() == 'Linux': from ctypes import cdll - self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so") - elif platform.system() == "Darwin": + elif platform.system() == 'Darwin': from picoscope.darwin_utils import LoadLibraryDarwin - self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - - self.lib = windll.LoadLibrary( - find_library(str(self.LIBNAME + ".dll")) - ) + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) super(PS3000, self).__init__(serialNumber, connect) @@ -161,10 +141,8 @@ def _lowLevelOpenUnit(self, sn): m = self.lib.ps3000_open_unit() if m < 0: - raise IOError( - "Failed to Find PS3000 Unit. " - + "Should you be using PS3000a driver?" - ) + raise IOError("Failed to Find PS3000 Unit. " + + "Should you be using PS3000a driver?") self.handle = m self.suggested_time_units = self.TIME_UNITS["NS"] @@ -173,16 +151,12 @@ def _lowLevelCloseUnit(self): m = self.lib.ps3000_close_unit(c_int16(self.handle)) self.checkResult(m) - def _lowLevelSetChannel( - self, chNum, enabled, coupling, VRange, VOffset, BWLimited - ): + def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, + BWLimited): m = self.lib.ps3000_set_channel( - c_int16(self.handle), - c_enum(chNum), - c_int16(enabled), - c_enum(coupling), - c_enum(VRange), - ) + c_int16(self.handle), c_enum(chNum), + c_int16(enabled), c_enum(coupling), + c_enum(VRange)) self.checkResult(m) def _lowLevelStop(self): @@ -193,42 +167,29 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) m = self.lib.ps3000_get_unit_info( - c_int16(self.handle), byref(s), c_int16(len(s)), c_enum(info) - ) + c_int16(self.handle), byref(s), c_int16(len(s)), c_enum(info)) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode("utf-8") + return s.value.decode('utf-8') def _lowLevelFlashLed(self, times): m = self.lib.ps3000_flash_led(c_int16(self.handle)) self.checkResult(m) - def _lowLevelSetSimpleTrigger( - self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms - ): + def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, + direction, delay, timeout_ms): # TODO: Fix 'auto' which is where trigger occurs in block. # Delay is not used m = self.lib.ps3000_set_trigger( - c_int16(self.handle), - c_enum(trigsrc), - c_int16(threshold_adc), - c_enum(direction), - c_int16(delay), - c_int16(timeout_ms), - ) + c_int16(self.handle), c_enum(trigsrc), c_int16(threshold_adc), + c_enum(direction), c_int16(delay), c_int16(timeout_ms)) self.checkResult(m) - def _lowLevelRunBlock( - self, - numPreTrigSamples, - numPostTrigSamples, - timebase, - oversample, - segmentIndex, - ): + def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, + timebase, oversample, segmentIndex): # NOT: Oversample is NOT used! # TODO: Fix 'delay' which is where trigger occurs in block @@ -237,12 +198,8 @@ def _lowLevelRunBlock( timeIndisposedMs = c_int32() m = self.lib.ps3000_run_block( - c_int16(self.handle), - c_uint32(numPostTrigSamples), - c_uint32(timebase), - c_int16(1), - byref(timeIndisposedMs), - ) + c_int16(self.handle), c_uint32(numPostTrigSamples), + c_uint32(timebase), c_int16(1), byref(timeIndisposedMs)) self.checkResult(m) return timeIndisposedMs.value @@ -264,20 +221,15 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): time_units = c_int16() m = self.lib.ps3000_get_timebase( - c_int16(self.handle), - c_int16(tb), - c_uint32(noSamples), - byref(time_interval), - byref(time_units), - c_int16(1), - byref(maxSamples), - ) + c_int16(self.handle), c_int16(tb), c_uint32(noSamples), + byref(time_interval), byref(time_units), c_int16(1), + byref(maxSamples)) self.checkResult(m) self.suggested_time_units = time_units.value - return (time_interval.value / 1.0e9, maxSamples.value) + return (time_interval.value / 1.0E9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """ps3000 doesn't seem to have published formula like other scopes.""" @@ -285,26 +237,20 @@ def getTimeBaseNum(self, sampleTimeS): timebases = [None] * self.MAX_TIMEBASES # Convert to nS - sampleTimenS = sampleTimeS * 1e9 + sampleTimenS = sampleTimeS * 1E9 tb = 0 while tb < self.MAX_TIMEBASES: rv = self.lib.ps3000_get_timebase( - c_int16(self.handle), - c_int16(tb), - c_uint32(512), - byref(time_interval), - c_void_p(), - c_int16(1), - c_void_p(), - ) + c_int16(self.handle), c_int16(tb), c_uint32(512), + byref(time_interval), c_void_p(), c_int16(1), c_void_p()) if rv != 0: timebases[tb] = time_interval.value tb += 1 # Figure out closest option - besterror = 1e99 + besterror = 1E99 bestindx = 0 for indx, val in enumerate(timebases): if val is not None: @@ -319,20 +265,13 @@ def getTimestepFromTimebase(self, timebase): """Return timestep from Timebase.""" time_interval = c_int32() m = self.lib.ps3000_get_timebase( - c_int16(self.handle), - c_int16(timebase), - c_uint32(512), - byref(time_interval), - c_void_p(), - c_int16(1), - c_void_p(), - ) + c_int16(self.handle), c_int16(timebase), c_uint32(512), + byref(time_interval), c_void_p(), c_int16(1), c_void_p()) self.checkResult(m) - return time_interval.value / 1.0e9 + return (time_interval.value / 1.0E9) - def _lowLevelSetDataBuffer( - self, channel, data, downSampleMode, segmentIndex - ): + def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, + segmentIndex): dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) @@ -343,14 +282,8 @@ def _lowLevelClearDataBuffer(self, channel, segmentIndex): self.channelBuffersPtr[channel] = c_void_p() self.channelBuffersLen[channel] = 0 - def _lowLevelGetValues( - self, - numSamples, - startIndex, - downSampleRatio, - downSampleMode, - segmentIndex, - ): + def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, + downSampleMode, segmentIndex): # TODO: # Check overflow in channelBuffersLen against numSamples, # but need to not raise error if channelBuffersPtr is void @@ -360,30 +293,16 @@ def _lowLevelGetValues( c_int16(self.handle), self.channelBuffersPtr[0], self.channelBuffersPtr[1], - c_void_p(), - c_void_p(), - byref(overflow), - c_int32(numSamples), - ) + c_void_p(), c_void_p(), + byref(overflow), c_int32(numSamples)) self.checkResult(rv) return (rv, overflow.value) - def _lowLevelSetSigGenBuiltInSimple( - self, - offsetVoltage, - pkToPk, - waveType, - frequency, - shots, - triggerType, - triggerSource, - stopFreq, - increment, - dwellTime, - sweepType, - numSweeps, - ): + def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, + frequency, shots, triggerType, + triggerSource, stopFreq, increment, + dwellTime, sweepType, numSweeps): if stopFreq is None: stopFreq = frequency @@ -392,19 +311,15 @@ def _lowLevelSetSigGenBuiltInSimple( c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), - c_float(stopFreq), - c_float(increment), - c_float(dwellTime), - c_enum(sweepType), - c_uint32(numSweeps), - ) + c_float(frequency), c_float(stopFreq), + c_float(increment), c_float(dwellTime), c_enum(sweepType), + c_uint32(numSweeps)) self.checkResult(m) def checkResult(self, ec): """Check result of function calls, raise exception if not 0.""" # PS3000 differs from other drivers in that non-zero is good if ec == 0: - raise IOError("Error calling %s" % (inspect.stack()[1][3])) + raise IOError('Error calling %s' % (inspect.stack()[1][3])) return 0 diff --git a/picoscope/ps3000a.py b/picoscope/ps3000a.py index 803175b..31bb888 100644 --- a/picoscope/ps3000a.py +++ b/picoscope/ps3000a.py @@ -54,17 +54,8 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import ( - byref, - POINTER, - create_string_buffer, - c_float, - c_int16, - c_int32, - c_uint16, - c_uint32, - c_void_p, -) +from ctypes import byref, POINTER, create_string_buffer, c_float, \ + c_int16, c_int32, c_uint16, c_uint32, c_void_p from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -76,65 +67,39 @@ class PS3000a(_PicoscopeBase): LIBNAME = "ps3000a" NUM_CHANNELS = 4 - CHANNELS = { - "A": 0, - "B": 1, - "C": 2, - "D": 3, - "External": 4, - "MaxChannels": 4, - "TriggerAux": 5, - } + CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, + "External": 4, "MaxChannels": 4, "TriggerAux": 5} ADC_RESOLUTIONS = {"8": 0, "12": 1, "14": 2, "15": 3, "16": 4} - CHANNEL_RANGE = [ - {"rangeV": 10e-3, "apivalue": 0, "rangeStr": "10 mV"}, - {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + CHANNEL_RANGE = [{"rangeV": 10E-3, "apivalue": 0, "rangeStr": "10 mV"}, + {"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] CHANNEL_COUPLINGS = {"DC": 1, "AC": 0} # has_sig_gen = True - WAVE_TYPES = { - "Sine": 0, - "Square": 1, - "Triangle": 2, - "RampUp": 3, - "RampDown": 4, - "Sinc": 5, - "Gaussian": 6, - "HalfSine": 7, - "DCVoltage": 8, - "WhiteNoise": 9, - } + WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, + "RampUp": 3, "RampDown": 4, + "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, + "WhiteNoise": 9} SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} - SIGGEN_TRIGGER_TYPES = { - "Rising": 0, - "Falling": 1, - "GateHigh": 2, - "GateLow": 3, - } - SIGGEN_TRIGGER_SOURCES = { - "None": 0, - "ScopeTrig": 1, - "AuxIn": 2, - "ExtIn": 3, - "SoftTrig": 4, - "TriggerRaw": 5, - } + SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, + "GateHigh": 2, "GateLow": 3} + SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, "AuxIn": 2, + "ExtIn": 3, "SoftTrig": 4, "TriggerRaw": 5} # This is actually different depending on the AB/CD models # I wonder how we could detect the difference between the oscilloscopes @@ -148,7 +113,7 @@ class PS3000a(_PicoscopeBase): AWGBufferAddressWidth = 14 AWGMaxSamples = 2 ** AWGBufferAddressWidth - AWGDACInterval = 5e-9 # in seconds + AWGDACInterval = 5E-9 # in seconds AWGDACFrequency = 1 / AWGDACInterval # Note this is NOT what is written in the Programming guide as of version @@ -169,21 +134,16 @@ class PS3000a(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLL etc.""" - if platform.system() == "Linux": + if platform.system() == 'Linux': from ctypes import cdll - self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so") - elif platform.system() == "Darwin": + elif platform.system() == 'Darwin': from picoscope.darwin_utils import LoadLibraryDarwin - self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - - self.lib = windll.LoadLibrary( - find_library(str(self.LIBNAME + ".dll")) - ) + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) self.resolution = self.ADC_RESOLUTIONS["8"] @@ -226,33 +186,26 @@ def _lowLevelEnumerateUnits(self): serialLth = c_int16(count.value * (8 + 2)) serials = create_string_buffer(serialLth.value + 1) - m = self.lib.ps3000aEnumerateUnits( - byref(count), serials, byref(serialLth) - ) + m = self.lib.ps3000aEnumerateUnits(byref(count), serials, + byref(serialLth)) self.checkResult(m) - serialList = str(serials.value.decode("utf-8")).split(",") + serialList = str(serials.value.decode('utf-8')).split(',') serialList = [x.strip() for x in serialList] return serialList - def _lowLevelSetChannel( - self, chNum, enabled, coupling, VRange, VOffset, BWLimited - ): - m = self.lib.ps3000aSetChannel( - c_int16(self.handle), - c_enum(chNum), - c_int16(enabled), - c_enum(coupling), - c_enum(VRange), - c_float(VOffset), - ) + def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, + BWLimited): + m = self.lib.ps3000aSetChannel(c_int16(self.handle), c_enum(chNum), + c_int16(enabled), c_enum(coupling), + c_enum(VRange), c_float(VOffset)) self.checkResult(m) - m = self.lib.ps3000aSetBandwidthFilter( - c_int16(self.handle), c_enum(chNum), c_enum(BWLimited) - ) + m = self.lib.ps3000aSetBandwidthFilter(c_int16(self.handle), + c_enum(chNum), + c_enum(BWLimited)) self.checkResult(m) def _lowLevelStop(self): @@ -263,90 +216,63 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps3000aGetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps3000aGetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), byref(requiredSize), + c_enum(info)) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps3000aGetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps3000aGetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), + byref(requiredSize), c_enum(info)) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode("utf-8") + return s.value.decode('utf-8') def _lowLevelFlashLed(self, times): m = self.lib.ps3000aFlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger( - self, enabled, trigsrc, threshold_adc, direction, delay, auto - ): + def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, + direction, delay, auto): m = self.lib.ps3000aSetSimpleTrigger( - c_int16(self.handle), - c_int16(enabled), - c_enum(trigsrc), - c_int16(threshold_adc), - c_enum(direction), - c_uint32(delay), - c_int16(auto), - ) + c_int16(self.handle), c_int16(enabled), + c_enum(trigsrc), c_int16(threshold_adc), + c_enum(direction), c_uint32(delay), c_int16(auto)) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, numCaptures): - m = self.lib.ps3000aSetNoOfCaptures( - c_int16(self.handle), c_uint16(numCaptures) - ) + m = self.lib.ps3000aSetNoOfCaptures(c_int16(self.handle), + c_uint16(numCaptures)) self.checkResult(m) def _lowLevelMemorySegments(self, numSegments): maxSamples = c_int32() - m = self.lib.ps3000aMemorySegments( - c_int16(self.handle), c_uint16(numSegments), byref(maxSamples) - ) + m = self.lib.ps3000aMemorySegments(c_int16(self.handle), + c_uint16(numSegments), + byref(maxSamples)) self.checkResult(m) return maxSamples.value def _lowLevelGetMaxSegments(self): maxSegments = c_int16() - m = self.lib.ps3000aGetMaxSegments( - c_int16(self.handle), byref(maxSegments) - ) + m = self.lib.ps3000aGetMaxSegments(c_int16(self.handle), + byref(maxSegments)) self.checkResult(m) return maxSegments.value - def _lowLevelRunBlock( - self, - numPreTrigSamples, - numPostTrigSamples, - timebase, - oversample, - segmentIndex, - ): + def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, + timebase, oversample, segmentIndex): # NOT: Oversample is NOT used! timeIndisposedMs = c_int32() m = self.lib.ps3000aRunBlock( - c_int16(self.handle), - c_uint32(numPreTrigSamples), - c_uint32(numPostTrigSamples), - c_uint32(timebase), - c_int16(oversample), - byref(timeIndisposedMs), + c_int16(self.handle), c_uint32(numPreTrigSamples), + c_uint32(numPostTrigSamples), c_uint32(timebase), + c_int16(oversample), byref(timeIndisposedMs), c_uint32(segmentIndex), - c_void_p(), - c_void_p(), - ) + c_void_p(), c_void_p()) self.checkResult(m) return timeIndisposedMs.value @@ -368,24 +294,21 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): maxSamples = c_int32() intervalNanoSec = c_float() - m = self.lib.ps3000aGetTimebase2( - c_int16(self.handle), - c_uint32(tb), - c_uint32(noSamples), - byref(intervalNanoSec), - c_int16(oversample), - byref(maxSamples), - c_uint32(segmentIndex), - ) + m = self.lib.ps3000aGetTimebase2(c_int16(self.handle), c_uint32(tb), + c_uint32(noSamples), + byref(intervalNanoSec), + c_int16(oversample), + byref(maxSamples), + c_uint32(segmentIndex)) self.checkResult(m) # divide by 1e9 to return interval in seconds return (intervalNanoSec.value * 1e-9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """Convert sample time in S to something to pass to API Call.""" - maxSampleTime = ((2 ** 32 - 1) - 2) / 125000000 - if sampleTimeS < 8.0e-9: - st = math.floor(math.log(sampleTimeS * 1e9, 2)) + maxSampleTime = (((2 ** 32 - 1) - 2) / 125000000) + if sampleTimeS < 8.0E-9: + st = math.floor(math.log(sampleTimeS * 1E9, 2)) st = max(st, 0) else: if sampleTimeS > maxSampleTime: @@ -402,49 +325,39 @@ def getTimestepFromTimebase(self, timebase): API timestep is an integer from 0-32 """ if timebase < 3: - dt = 2.0 ** timebase / 1.0e9 + dt = 2. ** timebase / 1.0E9 else: - dt = (timebase - 2.0) / 125000000.0 + dt = (timebase - 2.0) / 125000000. return dt - def _lowLevelSetAWGSimpleDeltaPhase( - self, - waveform, - deltaPhase, - offsetVoltage, - pkToPk, - indexMode, - shots, - triggerType, - triggerSource, - ): + def _lowLevelSetAWGSimpleDeltaPhase(self, waveform, deltaPhase, + offsetVoltage, pkToPk, indexMode, + shots, triggerType, triggerSource): """Waveform should be an array of shorts.""" waveformPtr = waveform.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps3000aSetSigGenArbitrary( c_int16(self.handle), - c_uint32(int(offsetVoltage * 1e6)), # offset voltage in microvolts - c_uint32(int(pkToPk * 1e6)), # pkToPk in microvolts - c_uint32(int(deltaPhase)), # startDeltaPhase - c_uint32(int(deltaPhase)), # stopDeltaPhase - c_uint32(0), # deltaPhaseIncrement - c_uint32(0), # dwellCount - waveformPtr, # arbitraryWaveform - c_int32(len(waveform)), # arbitraryWaveformSize - c_enum(0), # sweepType for deltaPhase - c_enum(0), # operation (adding random noise and whatnot) - c_enum(indexMode), # single, dual, quad + c_uint32(int(offsetVoltage * 1E6)), # offset voltage in microvolts + c_uint32(int(pkToPk * 1E6)), # pkToPk in microvolts + c_uint32(int(deltaPhase)), # startDeltaPhase + c_uint32(int(deltaPhase)), # stopDeltaPhase + c_uint32(0), # deltaPhaseIncrement + c_uint32(0), # dwellCount + waveformPtr, # arbitraryWaveform + c_int32(len(waveform)), # arbitraryWaveformSize + c_enum(0), # sweepType for deltaPhase + c_enum(0), # operation (adding random noise and whatnot) + c_enum(indexMode), # single, dual, quad c_uint32(shots), - c_uint32(0), # sweeps + c_uint32(0), # sweeps c_uint32(triggerType), c_uint32(triggerSource), - c_int16(0), - ) # extInThreshold + c_int16(0)) # extInThreshold self.checkResult(m) - def _lowLevelSetDataBuffer( - self, channel, data, downSampleMode, segmentIndex - ): + def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, + segmentIndex): """Set the data buffer. Be sure to call _lowLevelClearDataBuffer @@ -455,18 +368,14 @@ def _lowLevelSetDataBuffer( numSamples = len(data) m = self.lib.ps3000aSetDataBuffer( - c_int16(self.handle), - c_enum(channel), - dataPtr, - c_int32(numSamples), + c_int16(self.handle), c_enum(channel), + dataPtr, c_int32(numSamples), c_uint32(segmentIndex), - c_enum(downSampleMode), - ) + c_enum(downSampleMode)) self.checkResult(m) - def _lowLevelSetDataBufferBulk( - self, channel, data, segmentIndex, downSampleMode - ): + def _lowLevelSetDataBufferBulk(self, channel, data, segmentIndex, + downSampleMode): """Set the bulk data buffer. In ps3000a, ps3000aSetDataBuffer combines the functionality of @@ -475,69 +384,45 @@ def _lowLevelSetDataBufferBulk( needed. Note that the order of segmentIndex and downSampleMode is reversed. """ - self._lowLevelSetDataBuffer( - channel, data, downSampleMode, segmentIndex - ) + self._lowLevelSetDataBuffer(channel, data, downSampleMode, + segmentIndex) def _lowLevelSetMultipleDataBuffers(self, channel, data, downSampleMode): max_segments = self._lowLevelGetMaxSegments() if data.shape[0] < max_segments: - raise ValueError( - "data array has fewer rows than current number " - + "of memory segments" - ) + raise ValueError("data array has fewer rows than current number " + + "of memory segments") if data.shape[1] < self.maxSamples: raise ValueError("data array has fewer columns than maxSamples") for i in range(max_segments): - m = self._lowLevelSetDataBuffer( - channel, data[i, :], downSampleMode, i - ) + m = self._lowLevelSetDataBuffer(channel, data[i, :], + downSampleMode, i) self.checkResult(m) def _lowLevelClearDataBuffer(self, channel, segmentIndex): - m = self.lib.ps3000aSetDataBuffer( - c_int16(self.handle), - c_enum(channel), - c_void_p(), - c_uint32(0), - c_uint32(segmentIndex), - c_enum(0), - ) + m = self.lib.ps3000aSetDataBuffer(c_int16(self.handle), + c_enum(channel), + c_void_p(), c_uint32(0), + c_uint32(segmentIndex), + c_enum(0)) self.checkResult(m) - def _lowLevelGetValues( - self, - numSamples, - startIndex, - downSampleRatio, - downSampleMode, - segmentIndex, - ): + def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, + downSampleMode, segmentIndex): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps3000aGetValues( - c_int16(self.handle), - c_uint32(startIndex), - byref(numSamplesReturned), - c_uint32(downSampleRatio), - c_enum(downSampleMode), - c_uint32(segmentIndex), - byref(overflow), - ) + c_int16(self.handle), c_uint32(startIndex), + byref(numSamplesReturned), c_uint32(downSampleRatio), + c_enum(downSampleMode), c_uint32(segmentIndex), + byref(overflow)) self.checkResult(m) return (numSamplesReturned.value, overflow.value) - def _lowLevelGetValuesBulk( - self, - numSamples, - fromSegment, - toSegment, - downSampleRatio, - downSampleMode, - overflow, - ): + def _lowLevelGetValuesBulk(self, numSamples, fromSegment, toSegment, + downSampleRatio, downSampleMode, overflow): m = self.lib.ps3000aGetValuesBulk( c_int16(self.handle), byref(c_uint32(numSamples)), @@ -545,26 +430,15 @@ def _lowLevelGetValuesBulk( c_uint32(toSegment), c_uint32(downSampleRatio), c_int16(downSampleMode), - overflow.ctypes.data_as(POINTER(c_int16)), - ) + overflow.ctypes.data_as(POINTER(c_int16)) + ) self.checkResult(m) return overflow, numSamples - def _lowLevelSetSigGenBuiltInSimple( - self, - offsetVoltage, - pkToPk, - waveType, - frequency, - shots, - triggerType, - triggerSource, - stopFreq, - increment, - dwellTime, - sweepType, - numSweeps, - ): + def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, + frequency, shots, triggerType, + triggerSource, stopFreq, increment, + dwellTime, sweepType, numSweeps): # TODO, I just noticed that V2 exists # Maybe change to V2 in the future if stopFreq is None: @@ -575,28 +449,22 @@ def _lowLevelSetSigGenBuiltInSimple( c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), - c_float(stopFreq), - c_float(increment), - c_float(dwellTime), - c_enum(sweepType), - c_enum(0), - c_uint32(shots), - c_uint32(numSweeps), - c_enum(triggerType), - c_enum(triggerSource), - c_int16(0), - ) + c_float(frequency), c_float(stopFreq), + c_float(increment), c_float(dwellTime), + c_enum(sweepType), c_enum(0), + c_uint32(shots), c_uint32(numSweeps), + c_enum(triggerType), c_enum(triggerSource), + c_int16(0)) self.checkResult(m) def _lowLevelChangePowerSource(self, powerstate): m = self.lib.ps3000aChangePowerSource( - c_int16(self.handle), c_enum(powerstate) - ) + c_int16(self.handle), + c_enum(powerstate)) self.checkResult(m) def _lowLevelSigGenSoftwareControl(self, triggerType): m = self.lib.ps3000aSigGenSoftwareControl( - c_int16(self.handle), c_enum(triggerType) - ) + c_int16(self.handle), + c_enum(triggerType)) self.checkResult(m) diff --git a/picoscope/ps4000.py b/picoscope/ps4000.py index 0afe93e..27cd9de 100644 --- a/picoscope/ps4000.py +++ b/picoscope/ps4000.py @@ -58,18 +58,8 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import ( - byref, - POINTER, - create_string_buffer, - c_float, - c_int16, - c_uint16, - c_int32, - c_uint32, - c_uint64, - c_void_p, -) +from ctypes import byref, POINTER, create_string_buffer, c_float, \ + c_int16, c_uint16, c_int32, c_uint32, c_uint64, c_void_p from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -98,20 +88,11 @@ class PS4000(_PicoscopeBase): AWGBufferAddressWidth = 12 AWGMaxSamples = 2 ** AWGBufferAddressWidth - SIGGEN_TRIGGER_TYPES = { - "Rising": 0, - "Falling": 1, - "GateHigh": 2, - "GateLow": 3, - } - - SIGGEN_TRIGGER_SOURCES = { - "None": 0, - "ScopeTrig": 1, - "AuxIn": 2, - "ExtIn": 3, - "SoftTrig": 4, - } + SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, + "GateHigh": 2, "GateLow": 3} + + SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, + "AuxIn": 2, "ExtIn": 3, "SoftTrig": 4} # EXT/AUX seems to have an imput impedence of 50 ohm (PS6403B) EXT_MAX_VALUE = 32767 @@ -120,76 +101,60 @@ class PS4000(_PicoscopeBase): # I don't think that the 50V range is allowed, but I left it there anyway # The 10V and 20V ranges are only allowed in high impedence modes - CHANNEL_RANGE = [ - {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + CHANNEL_RANGE = [{"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] NUM_CHANNELS = 4 CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, "EXT": 4} CHANNEL_COUPLINGS = {"DC50": 2, "DC": 1, "AC": 0} - WAVE_TYPES = { - "Sine": 0, - "Square": 1, - "Triangle": 2, - "RampUp": 3, - "RampDown": 4, - "Sinc": 5, - "Gaussian": 6, - "HalfSine": 7, - "DCVoltage": 8, - "WhiteNoise": 9, - } + WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, + "RampUp": 3, "RampDown": 4, + "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, + "WhiteNoise": 9} SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} def __init__(self, serialNumber=None, connect=True): """Load DLLs.""" self.handle = None - if platform.system() == "Linux": + if platform.system() == 'Linux': from ctypes import cdll - # ok I don't know what is wrong with my installer, # but I need to include .so.2 self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so.2") - elif platform.system() == "Darwin": + elif platform.system() == 'Darwin': from picoscope.darwin_utils import LoadLibraryDarwin - self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - - self.lib = windll.LoadLibrary( - find_library(str(self.LIBNAME + ".dll")) - ) + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) super(PS4000, self).__init__(serialNumber, connect) # check to see which model we have and use special functions if needed - unit_number = self.getUnitInfo("VariantInfo") - if unit_number == "4262": + unit_number = self.getUnitInfo('VariantInfo') + if unit_number == '4262': self.getTimestepFromTimebase = self._getTimestepFromTimebase4262 self.getTimeBaseNum = self._getTimeBaseNum4262 - elif unit_number in {"4223", "4224", "4423", "4424"}: + elif unit_number in {'4223', '4224', '4423', '4424'}: self.getTimestepFromTimebase = self._getTimestepFromTimebase4223 self.getTimeBaseNum = self._getTimeBaseNum4223 else: - raise NotImplementedError( - "Timebase functions have not been " - "written for the " + unit_number - ) + raise NotImplementedError('Timebase functions have not been ' + 'written for the ' + unit_number) def _lowLevelOpenUnit(self, sn): c_handle = c_int16() @@ -220,9 +185,9 @@ def _lowLevelOpenUnitProgress(self): progressPercent = c_int16() handle = c_int16() - m = self.lib.ps4000OpenUnitProgress( - byref(handle), byref(progressPercent), byref(complete) - ) + m = self.lib.ps4000OpenUnitProgress(byref(handle), + byref(progressPercent), + byref(complete)) self.checkResult(m) if complete.value != 0: @@ -247,29 +212,22 @@ def _lowLevelEnumerateUnits(self): serialLth = c_int16(count.value * (8 + 2)) serials = create_string_buffer(serialLth.value + 1) - m = self.lib.ps4000EnumerateUnits( - byref(count), serials, byref(serialLth) - ) + m = self.lib.ps4000EnumerateUnits(byref(count), serials, + byref(serialLth)) self.checkResult(m) - serialList = str(serials.value.decode("utf-8")).split(",") + serialList = str(serials.value.decode('utf-8')).split(',') serialList = [x.strip() for x in serialList] return serialList - def _lowLevelSetChannel( - self, chNum, enabled, coupling, VRange, VOffset, BWLimited - ): - m = self.lib.ps4000SetChannel( - c_int16(self.handle), - c_enum(chNum), - c_int16(enabled), - c_enum(coupling), - c_enum(VRange), - c_float(VOffset), - c_enum(BWLimited), - ) + def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, + BWLimited): + m = self.lib.ps4000SetChannel(c_int16(self.handle), c_enum(chNum), + c_int16(enabled), c_enum(coupling), + c_enum(VRange), c_float(VOffset), + c_enum(BWLimited)) self.checkResult(m) def _lowLevelStop(self): @@ -280,67 +238,41 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps4000GetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps4000GetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), byref(requiredSize), + c_enum(info)) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps4000GetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps4000GetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), + byref(requiredSize), c_enum(info)) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode("utf-8") + return s.value.decode('utf-8') def _lowLevelFlashLed(self, times): m = self.lib.ps4000FlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger( - self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms - ): + def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, + direction, delay, timeout_ms): m = self.lib.ps4000SetSimpleTrigger( - c_int16(self.handle), - c_int16(enabled), - c_enum(trigsrc), - c_int16(threshold_adc), - c_enum(direction), - c_uint32(delay), - c_int16(timeout_ms), - ) + c_int16(self.handle), c_int16(enabled), + c_enum(trigsrc), c_int16(threshold_adc), + c_enum(direction), c_uint32(delay), c_int16(timeout_ms)) self.checkResult(m) - def _lowLevelRunBlock( - self, - numPreTrigSamples, - numPostTrigSamples, - timebase, - oversample, - segmentIndex, - ): + def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, + timebase, oversample, segmentIndex): timeIndisposedMs = c_int32() m = self.lib.ps4000RunBlock( - c_int16(self.handle), - c_uint32(numPreTrigSamples), - c_uint32(numPostTrigSamples), - c_uint32(timebase), - c_int16(oversample), - byref(timeIndisposedMs), - c_uint16(segmentIndex), - c_void_p(), - c_void_p(), - ) + c_int16(self.handle), c_uint32(numPreTrigSamples), + c_uint32(numPostTrigSamples), c_uint32(timebase), + c_int16(oversample), byref(timeIndisposedMs), + c_uint16(segmentIndex), c_void_p(), c_void_p()) self.checkResult(m) return timeIndisposedMs.value @@ -358,37 +290,30 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): maxSamples = c_int32() sampleRate = c_float() - m = self.lib.ps4000GetTimebase2( - c_int16(self.handle), - c_uint32(tb), - c_uint32(noSamples), - byref(sampleRate), - c_int16(oversample), - byref(maxSamples), - c_uint16(segmentIndex), - ) + m = self.lib.ps4000GetTimebase2(c_int16(self.handle), c_uint32(tb), + c_uint32(noSamples), byref(sampleRate), + c_int16(oversample), byref(maxSamples), + c_uint16(segmentIndex)) self.checkResult(m) - return (sampleRate.value / 1.0e9, maxSamples.value) + return (sampleRate.value / 1.0E9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """Return sample time in seconds to timebase as int for API calls.""" - raise NotImplementedError( - "Timebase functions have not been " "written for the scope." - ) + raise NotImplementedError('Timebase functions have not been ' + 'written for the scope.') def getTimestepFromTimebase(self, timebase): """Return timebase to sampletime as seconds.""" - raise NotImplementedError( - "Timebase functions have not been " "written for the scope." - ) + raise NotImplementedError('Timebase functions have not been ' + 'written for the scope.') def _getTimeBaseNum4223(self, sampleTimeS): """Return sample time in seconds to timebase as int for API calls.""" - maxSampleTime = ((2 ** 32 - 1) - 4) / 2e7 + maxSampleTime = (((2 ** 32 - 1) - 4) / 2e7) - if sampleTimeS <= 12.5e-9: - timebase = math.floor(math.log(sampleTimeS * 8e7, 2)) + if sampleTimeS <= 12.5E-9: + timebase = math.floor(math.log(sampleTimeS * 8E7, 2)) timebase = max(timebase, 0) else: # Otherwise in range 2^32-1 @@ -404,7 +329,7 @@ def _getTimeBaseNum4223(self, sampleTimeS): def _getTimestepFromTimebase4223(self, timebase): """Return timebase to sampletime as seconds.""" if timebase < 3: - dt = 2.0 ** timebase / 8e7 + dt = 2. ** timebase / 8e7 else: dt = (timebase - 1) / 2e7 return dt @@ -412,7 +337,7 @@ def _getTimestepFromTimebase4223(self, timebase): def _getTimestepFromTimebase4262(self, timebase): """Return timebase to sampletime as seconds for ps4262.""" someConstant = 10000000.0 - return (timebase + 1) / someConstant + return (timebase+1) / someConstant def _getTimeBaseNum4262(self, sampleTimeS): """Return timebase for the ps4262. @@ -421,13 +346,13 @@ def _getTimeBaseNum4262(self, sampleTimeS): int for API calls for ps4262. """ someConstant = 10000000.0 - maxSampleTime = (2 ** 30) / someConstant + maxSampleTime = ((2 ** 30) / someConstant) minSampleTime = 1 / someConstant if sampleTimeS <= minSampleTime: timebase = 0 elif sampleTimeS >= maxSampleTime: - timebase = 2 ** 30 + timebase = (2 ** 30) else: timebase = round(sampleTimeS * someConstant) - 1 @@ -435,9 +360,8 @@ def _getTimeBaseNum4262(self, sampleTimeS): timebase = int(timebase) return timebase - def _lowLevelSetDataBuffer( - self, channel, data, downSampleMode, segmentIndex - ): + def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, + segmentIndex): """Set the data buffer. Be sure to call _lowLevelClearDataBuffer @@ -450,97 +374,58 @@ def _lowLevelSetDataBuffer( dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) - m = self.lib.ps4000SetDataBuffer( - c_int16(self.handle), - c_enum(channel), - dataPtr, - c_uint32(numSamples), - ) + m = self.lib.ps4000SetDataBuffer(c_int16(self.handle), c_enum(channel), + dataPtr, c_uint32(numSamples)) self.checkResult(m) def _lowLevelClearDataBuffer(self, channel, segmentIndex): - m = self.lib.ps4000SetDataBuffer( - c_int16(self.handle), - c_enum(channel), - c_void_p(), - c_uint32(0), - c_enum(0), - ) + m = self.lib.ps4000SetDataBuffer(c_int16(self.handle), c_enum(channel), + c_void_p(), c_uint32(0), c_enum(0)) self.checkResult(m) - def _lowLevelGetValues( - self, - numSamples, - startIndex, - downSampleRatio, - downSampleMode, - segmentIndex, - ): + def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, + downSampleMode, segmentIndex): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps4000GetValues( - c_int16(self.handle), - c_uint32(startIndex), - byref(numSamplesReturned), - c_uint32(downSampleRatio), - c_enum(downSampleMode), - c_uint16(segmentIndex), - byref(overflow), - ) + c_int16(self.handle), c_uint32(startIndex), + byref(numSamplesReturned), c_uint32(downSampleRatio), + c_enum(downSampleMode), c_uint16(segmentIndex), + byref(overflow)) self.checkResult(m) return (numSamplesReturned.value, overflow.value) - def _lowLevelSetAWGSimpleDeltaPhase( - self, - waveform, - deltaPhase, - offsetVoltage, - pkToPk, - indexMode, - shots, - triggerType, - triggerSource, - ): + def _lowLevelSetAWGSimpleDeltaPhase(self, waveform, deltaPhase, + offsetVoltage, pkToPk, indexMode, + shots, triggerType, triggerSource): """Waveform should be an array of shorts.""" waveformPtr = waveform.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps4000SetSigGenArbitrary( c_int16(self.handle), - c_uint32(int(offsetVoltage * 1e6)), # offset voltage in microvolts - c_uint32(int(pkToPk * 1e6)), # pkToPk in microvolts - c_uint32(int(deltaPhase)), # startDeltaPhase - c_uint32(int(deltaPhase)), # stopDeltaPhase - c_uint32(0), # deltaPhaseIncrement - c_uint32(0), # dwellCount - waveformPtr, # arbitraryWaveform - c_int32(len(waveform)), # arbitraryWaveformSize - c_enum(0), # sweepType for deltaPhase - c_enum(0), # operation (adding random noise and whatnot) - c_enum(indexMode), # single, dual, quad + c_uint32(int(offsetVoltage * 1E6)), # offset voltage in microvolts + c_uint32(int(pkToPk * 1E6)), # pkToPk in microvolts + c_uint32(int(deltaPhase)), # startDeltaPhase + c_uint32(int(deltaPhase)), # stopDeltaPhase + c_uint32(0), # deltaPhaseIncrement + c_uint32(0), # dwellCount + waveformPtr, # arbitraryWaveform + c_int32(len(waveform)), # arbitraryWaveformSize + c_enum(0), # sweepType for deltaPhase + c_enum(0), # operation (adding random noise and whatnot) + c_enum(indexMode), # single, dual, quad c_uint32(shots), - c_uint32(0), # sweeps + c_uint32(0), # sweeps c_uint32(triggerType), c_uint32(triggerSource), - c_int16(0), - ) # extInThreshold + c_int16(0)) # extInThreshold self.checkResult(m) - def _lowLevelSetSigGenBuiltInSimple( - self, - offsetVoltage, - pkToPk, - waveType, - frequency, - shots, - triggerType, - triggerSource, - stopFreq, - increment, - dwellTime, - sweepType, - numSweeps, - ): + def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, + frequency, shots, triggerType, + triggerSource, stopFreq, increment, + dwellTime, sweepType, numSweeps): if stopFreq is None: stopFreq = frequency @@ -549,25 +434,18 @@ def _lowLevelSetSigGenBuiltInSimple( c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), - c_float(stopFreq), - c_float(increment), - c_float(dwellTime), - c_enum(sweepType), - c_enum(0), - c_uint32(shots), - c_uint32(numSweeps), - c_enum(triggerType), - c_enum(triggerSource), - c_int16(0), - ) + c_float(frequency), c_float(stopFreq), + c_float(increment), c_float(dwellTime), + c_enum(sweepType), c_enum(0), + c_uint32(shots), c_uint32(numSweeps), + c_enum(triggerType), c_enum(triggerSource), + c_int16(0)) self.checkResult(m) def _lowLevelSigGenSoftwareControl(self, triggerType): m = self.lib.ps4000SigGenSoftwareControl( - c_int16(self.handle), c_enum(triggerType) - ) + c_int16(self.handle), c_enum(triggerType)) self.checkResult(m) # use VRange=5 for +/- 500mV signal range @@ -575,8 +453,8 @@ def _lowLevelSigGenSoftwareControl(self, triggerType): # VRange=8 for +/- 5V range def _lowLevelSetExtTriggerRange(self, VRange): m = self.lib.ps4000SetExtTriggerRange( - c_int16(self.handle), c_enum(VRange) - ) + c_int16(self.handle), + c_enum(VRange)) self.checkResult(m) #################################################################### @@ -584,9 +462,8 @@ def _lowLevelSetExtTriggerRange(self, VRange): # # #################################################################### - def _lowLevelGetMaxDownSampleRatio( - self, noOfUnaggregatedSamples, downSampleRatioMode, segmentIndex - ): + def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, + downSampleRatioMode, segmentIndex): maxDownSampleRatio = c_uint32() m = self.lib.ps4000GetMaxDownSampleRatio( @@ -594,8 +471,7 @@ def _lowLevelGetMaxDownSampleRatio( c_uint32(noOfUnaggregatedSamples), byref(maxDownSampleRatio), c_enum(downSampleRatioMode), - c_uint16(segmentIndex), - ) + c_uint16(segmentIndex)) self.checkResult(m) return maxDownSampleRatio.value @@ -604,8 +480,7 @@ def _lowLevelGetNoOfCaptures(self): nCaptures = c_uint32() m = self.lib.ps4000GetNoOfCaptures( - c_int16(self.handle), byref(nCaptures) - ) + c_int16(self.handle), byref(nCaptures)) self.checkResult(m) return nCaptures.value @@ -618,39 +493,37 @@ def _lowLevelGetTriggerTimeOffset(self, segmentIndex): c_int16(self.handle), byref(time), byref(timeUnits), - c_uint16(segmentIndex), - ) + c_uint16(segmentIndex)) self.checkResult(m) - if timeUnits.value == 0: # PS4000_FS - return time.value * 1e-15 + if timeUnits.value == 0: # PS4000_FS + return time.value * 1E-15 elif timeUnits.value == 1: # PS4000_PS - return time.value * 1e-12 + return time.value * 1E-12 elif timeUnits.value == 2: # PS4000_NS - return time.value * 1e-9 + return time.value * 1E-9 elif timeUnits.value == 3: # PS4000_US - return time.value * 1e-6 + return time.value * 1E-6 elif timeUnits.value == 4: # PS4000_MS - return time.value * 1e-3 + return time.value * 1E-3 elif timeUnits.value == 5: # PS4000_S - return time.value * 1e0 + return time.value * 1E0 else: raise TypeError("Unknown timeUnits %d" % timeUnits.value) def _lowLevelMemorySegments(self, nSegments): nMaxSamples = c_uint32() - m = self.lib.ps4000MemorySegments( - c_int16(self.handle), c_uint16(nSegments), byref(nMaxSamples) - ) + m = self.lib.ps4000MemorySegments(c_int16(self.handle), + c_uint16(nSegments), + byref(nMaxSamples)) self.checkResult(m) return nMaxSamples.value - def _lowLevelSetDataBuffers( - self, channel, bufferMax, bufferMin, downSampleRatioMode - ): + def _lowLevelSetDataBuffers(self, channel, bufferMax, bufferMin, + downSampleRatioMode): bufferMaxPtr = bufferMax.ctypes.data_as(POINTER(c_int16)) bufferMinPtr = bufferMin.ctypes.data_as(POINTER(c_int16)) bufferLth = len(bufferMax) @@ -660,8 +533,7 @@ def _lowLevelSetDataBuffers( c_enum(channel), bufferMaxPtr, bufferMinPtr, - c_uint32(bufferLth), - ) + c_uint32(bufferLth)) self.checkResult(m) def _lowLevelClearDataBuffers(self, channel): @@ -670,38 +542,32 @@ def _lowLevelClearDataBuffers(self, channel): c_enum(channel), c_void_p(), c_void_p(), - c_uint32(0), - ) + c_uint32(0)) self.checkResult(m) # Bulk values. # These would be nice, but the user would have to provide us # with an array. # we would have to make sure that it is contiguous amonts other things - def _lowLevelGetValuesBulk( - self, - numSamples, - fromSegmentIndex, - toSegmentIndex, - downSampleRatio, - downSampleMode, - overflow, - ): + def _lowLevelGetValuesBulk(self, + numSamples, + fromSegmentIndex, + toSegmentIndex, + downSampleRatio, + downSampleMode, + overflow): noOfSamples = c_uint32(numSamples) m = self.lib.ps4000GetValuesBulk( c_int16(self.handle), byref(noOfSamples), - c_uint16(fromSegmentIndex), - c_uint16(toSegmentIndex), - overflow.ctypes.data_as(POINTER(c_int16)), - ) + c_uint16(fromSegmentIndex), c_uint16(toSegmentIndex), + overflow.ctypes.data_as(POINTER(c_int16))) self.checkResult(m) return noOfSamples.value - def _lowLevelSetDataBufferBulk( - self, channel, buffer, waveform, downSampleRatioMode - ): + def _lowLevelSetDataBufferBulk(self, channel, buffer, waveform, + downSampleRatioMode): bufferPtr = buffer.ctypes.data_as(POINTER(c_int16)) bufferLth = len(buffer) @@ -710,14 +576,13 @@ def _lowLevelSetDataBufferBulk( c_enum(channel), bufferPtr, c_uint32(bufferLth), - c_uint16(waveform), - ) + c_uint16(waveform)) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, nCaptures): m = self.lib.ps4000SetNoOfCaptures( - c_int16(self.handle), c_uint16(nCaptures) - ) + c_int16(self.handle), + c_uint16(nCaptures)) self.checkResult(m) # ETS Functions @@ -779,8 +644,7 @@ def _lowLevelNoOfStreamingValues(self): noOfValues = c_uint32() m = self.lib.ps4000NoOfStreamingValues( - c_int16(self.handle), byref(noOfValues) - ) + c_int16(self.handle), byref(noOfValues)) self.checkResult(m) return noOfValues.value diff --git a/picoscope/ps4000a.py b/picoscope/ps4000a.py index 3c92800..56a7e86 100644 --- a/picoscope/ps4000a.py +++ b/picoscope/ps4000a.py @@ -58,19 +58,8 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import ( - byref, - POINTER, - create_string_buffer, - c_float, - c_int16, - c_uint16, - c_int32, - c_uint32, - c_uint64, - c_void_p, - c_int8, -) +from ctypes import byref, POINTER, create_string_buffer, c_float, \ + c_int16, c_uint16, c_int32, c_uint32, c_uint64, c_void_p, c_int8 from ctypes import c_int32 as c_enum import warnings @@ -93,82 +82,57 @@ class PS4000a(_PicoscopeBase): # I don't think that the 50V range is allowed, but I left it there anyway # The 10V and 20V ranges are only allowed in high impedence modes - CHANNEL_RANGE = [ - {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + CHANNEL_RANGE = [{"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] NUM_CHANNELS = 8 - CHANNELS = { - "A": 0, - "B": 1, - "C": 2, - "D": 3, - "E": 4, - "F": 5, - "G": 6, - "H": 7, - "MaxChannels": 8, - } + CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, "E": 4, "F": 5, "G": 6, + "H": 7, "MaxChannels": 8} ADC_RESOLUTIONS = {"8": 0, "12": 1, "14": 2, "15": 3, "16": 4} CHANNEL_COUPLINGS = {"DC50": 2, "DC": 1, "AC": 0} - WAVE_TYPES = { - "Sine": 0, - "Square": 1, - "Triangle": 2, - "RampUp": 3, - "RampDown": 4, - "Sinc": 5, - "Gaussian": 6, - "HalfSine": 7, - "DCVoltage": 8, - "WhiteNoise": 9, - } + WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, + "RampUp": 3, "RampDown": 4, + "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, + "WhiteNoise": 9} SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} - TIME_UNITS = { - "femtoseconds": 0, - "picoseconds": 1, - "nanoseconds": 2, - "microseconds": 3, - "milliseconds": 4, - "seconds": 5, - } + TIME_UNITS = {"femtoseconds": 0, + "picoseconds": 1, + "nanoseconds": 2, + "microseconds": 3, + "milliseconds": 4, + "seconds": 5} def __init__(self, serialNumber=None, connect=True): """Load DLLs.""" self.handle = None - if platform.system() == "Linux": + if platform.system() == 'Linux': from ctypes import cdll - # ok I don't know what is wrong with my installer, # but I need to include .so.2 self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so.2") - elif platform.system() == "Darwin": + elif platform.system() == 'Darwin': from picoscope.darwin_utils import LoadLibraryDarwin - self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - - self.lib = windll.LoadLibrary( - find_library(str(self.LIBNAME + ".dll")) - ) + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) self.resolution = self.ADC_RESOLUTIONS["12"] @@ -195,7 +159,7 @@ def _lowLevelOpenUnit(self, sn): else: self.checkResult(m) - self.model = self.getUnitInfo("VariantInfo") + self.model = self.getUnitInfo('VariantInfo') def _lowLevelOpenUnitAsync(self, sn): c_status = c_int16() @@ -215,9 +179,9 @@ def _lowLevelOpenUnitProgress(self): progressPercent = c_int16() handle = c_int16() - m = self.lib.ps4000aOpenUnitProgress( - byref(handle), byref(progressPercent), byref(complete) - ) + m = self.lib.ps4000aOpenUnitProgress(byref(handle), + byref(progressPercent), + byref(complete)) self.checkResult(m) if complete.value != 0: @@ -236,9 +200,8 @@ def _lowLevelEnumerateUnits(self): serials = c_int8(0) serialLth = c_int16(0) - m = self.lib.ps4000aEnumerateUnits( - byref(count), byref(serials), byref(serialLth) - ) + m = self.lib.ps4000aEnumerateUnits(byref(count), byref(serials), + byref(serialLth)) self.checkResult(m) # a serial number is rouhgly 8 characters # an extra character for the comma @@ -247,33 +210,26 @@ def _lowLevelEnumerateUnits(self): serialLth = c_int16(count.value * (8 + 2)) serials = create_string_buffer(serialLth.value + 1) - m = self.lib.ps4000aEnumerateUnits( - byref(count), serials, byref(serialLth) - ) + m = self.lib.ps4000aEnumerateUnits(byref(count), serials, + byref(serialLth)) self.checkResult(m) - serialList = str(serials.value.decode("utf-8")).split(",") + serialList = str(serials.value.decode('utf-8')).split(',') serialList = [x.strip() for x in serialList] return serialList - def _lowLevelSetChannel( - self, chNum, enabled, coupling, VRange, VOffset, BWLimited - ): - m = self.lib.ps4000aSetChannel( - c_int16(self.handle), - c_enum(chNum), - c_int16(enabled), - c_enum(coupling), - c_enum(VRange), - c_float(VOffset), - ) + def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, + BWLimited): + m = self.lib.ps4000aSetChannel(c_int16(self.handle), c_enum(chNum), + c_int16(enabled), c_enum(coupling), + c_enum(VRange), c_float(VOffset)) self.checkResult(m) - m = self.lib.ps4000aSetBandwidthFilter( - c_int16(self.handle), c_enum(chNum), c_enum(BWLimited) - ) + m = self.lib.ps4000aSetBandwidthFilter(c_int16(self.handle), + c_enum(chNum), + c_enum(BWLimited)) self.checkResult(m) def _lowLevelStop(self): @@ -284,66 +240,41 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps4000aGetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps4000aGetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), byref(requiredSize), + c_enum(info)) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps4000aGetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps4000aGetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), + byref(requiredSize), c_enum(info)) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode("utf-8") + return s.value.decode('utf-8') def _lowLevelFlashLed(self, times): m = self.lib.ps4000aFlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger( - self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms - ): + def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, + direction, delay, timeout_ms): m = self.lib.ps4000aSetSimpleTrigger( - c_int16(self.handle), - c_int16(enabled), - c_enum(trigsrc), - c_int16(threshold_adc), - c_enum(direction), - c_uint32(delay), - c_int16(timeout_ms), - ) + c_int16(self.handle), c_int16(enabled), + c_enum(trigsrc), c_int16(threshold_adc), + c_enum(direction), c_uint32(delay), c_int16(timeout_ms)) self.checkResult(m) - def _lowLevelRunBlock( - self, - numPreTrigSamples, - numPostTrigSamples, - timebase, - oversample, - segmentIndex, - ): + def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, + timebase, oversample, segmentIndex): timeIndisposedMs = c_int32() m = self.lib.ps4000aRunBlock( - c_int16(self.handle), - c_int32(numPreTrigSamples), - c_int32(numPostTrigSamples), - c_uint32(timebase), + c_int16(self.handle), c_int32(numPreTrigSamples), + c_int32(numPostTrigSamples), c_uint32(timebase), byref(timeIndisposedMs), - c_uint32(segmentIndex), - c_void_p(), - c_void_p(), - ) + c_uint32(segmentIndex), c_void_p(), c_void_p()) self.checkResult(m) return timeIndisposedMs.value @@ -361,29 +292,25 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): maxSamples = c_int32() sampleRate = c_float() - m = self.lib.ps4000aGetTimebase2( - c_int16(self.handle), - c_uint32(tb), - c_int32(noSamples), - byref(sampleRate), - byref(maxSamples), - c_uint32(segmentIndex), - ) + m = self.lib.ps4000aGetTimebase2(c_int16(self.handle), c_uint32(tb), + c_int32(noSamples), byref(sampleRate), + byref(maxSamples), + c_uint32(segmentIndex)) self.checkResult(m) - return (sampleRate.value / 1.0e9, maxSamples.value) + return (sampleRate.value / 1.0E9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): - """Convert the sample interval (float of seconds) to the + """ Convert the sample interval (float of seconds) to the corresponding integer timebase value as defined by the API. See "Timebases" section of the PS4000a programmers guide for more information. """ - if self.model == "4828": - maxSampleTime = ((2 ** 32 - 1) + 1) / 8e7 + if self.model == '4828': + maxSampleTime = (((2 ** 32 - 1) + 1) / 8E7) - if sampleTimeS <= 12.5e-9: + if sampleTimeS <= 12.5E-9: timebase = 0 else: # Otherwise in range 2^32-1 @@ -392,36 +319,29 @@ def getTimeBaseNum(self, sampleTimeS): timebase = math.floor((sampleTimeS * 2e7) + 1) - elif self.model == "4444": - maxSampleTime = ((2 ** 32 - 1) - 2) / 5.0e7 + elif self.model == '4444': + maxSampleTime = (((2 ** 32 - 1) - 2) / 5.0E7) - if ( - sampleTimeS <= 2.5e-9 - and self.resolution == self.ADC_RESOLUTIONS["12"] - ): + if (sampleTimeS <= 2.5E-9 and + self.resolution == self.ADC_RESOLUTIONS["12"]): timebase = 0 - elif ( - sampleTimeS <= 20e-9 - and self.resolution == self.ADC_RESOLUTIONS["14"] - ): + elif (sampleTimeS <= 20E-9 and + self.resolution == self.ADC_RESOLUTIONS["14"]): timebase = 3 else: # Otherwise in range 2^32-1 if sampleTimeS > maxSampleTime: sampleTimeS = maxSampleTime - timebase = math.floor((sampleTimeS * 5.0e7) + 2) + timebase = math.floor((sampleTimeS * 5.0E7) + 2) else: # The original case from non "A" series - warnings.warn( - "The model PS4000a you are using may not be " - "fully supported", - stacklevel=2, - ) - maxSampleTime = ((2 ** 32 - 1) - 4) / 2e7 - - if sampleTimeS <= 12.5e-9: - timebase = math.floor(math.log(sampleTimeS * 8e7, 2)) + warnings.warn("The model PS4000a you are using may not be " + "fully supported", stacklevel=2) + maxSampleTime = (((2 ** 32 - 1) - 4) / 2e7) + + if sampleTimeS <= 12.5E-9: + timebase = math.floor(math.log(sampleTimeS * 8E7, 2)) timebase = max(timebase, 0) else: # Otherwise in range 2^32-1 @@ -436,30 +356,26 @@ def getTimeBaseNum(self, sampleTimeS): def getTimestepFromTimebase(self, timebase): """Return timebase to sampletime as seconds.""" - if self.model == "4828": - dt = (timebase + 1) / 8.0e7 - elif self.model == "4444": + if self.model == '4828': + dt = (timebase + 1) / 8.0E7 + elif self.model == '4444': if timebase < 3: - dt = 2.5 ** timebase / 4.0e8 + dt = 2.5 ** timebase / 4.0E8 else: - dt = (timebase - 2) / 5.0e7 + dt = (timebase - 2) / 5.0E7 else: # The original case from non "A" series - warnings.warn( - "The model PS4000a you are using may not be " - "fully supported", - stacklevel=2, - ) + warnings.warn("The model PS4000a you are using may not be " + "fully supported", stacklevel=2) if timebase < 3: - dt = 2.0 ** timebase / 8e7 + dt = 2. ** timebase / 8e7 else: dt = (timebase - 1) / 2e7 return dt return dt - def _lowLevelSetDataBuffer( - self, channel, data, downSampleMode, segmentIndex - ): + def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, + segmentIndex): """Set the data buffer. Be sure to call _lowLevelClearDataBuffer @@ -472,72 +388,48 @@ def _lowLevelSetDataBuffer( dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) - m = self.lib.ps4000aSetDataBuffer( - c_int16(self.handle), - c_enum(channel), - dataPtr, - c_uint32(numSamples), - c_uint32(segmentIndex), - c_uint32(downSampleMode), - ) + m = self.lib.ps4000aSetDataBuffer(c_int16(self.handle), + c_enum(channel), + dataPtr, c_uint32(numSamples), + c_uint32(segmentIndex), + c_uint32(downSampleMode)) self.checkResult(m) def _lowLevelClearDataBuffer(self, channel, segmentIndex): - m = self.lib.ps4000aSetDataBuffer( - c_int16(self.handle), - c_enum(channel), - c_void_p(), - c_uint32(0), - c_uint32(0), - c_enum(0), - ) + m = self.lib.ps4000aSetDataBuffer(c_int16(self.handle), + c_enum(channel), + c_void_p(), c_uint32(0), c_uint32(0), + c_enum(0)) self.checkResult(m) - def _lowLevelGetValues( - self, - numSamples, - startIndex, - downSampleRatio, - downSampleMode, - segmentIndex, - ): + def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, + downSampleMode, segmentIndex): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps4000aGetValues( - c_int16(self.handle), - c_uint32(startIndex), - byref(numSamplesReturned), - c_uint32(downSampleRatio), - c_enum(downSampleMode), - c_uint16(segmentIndex), - byref(overflow), - ) + c_int16(self.handle), c_uint32(startIndex), + byref(numSamplesReturned), c_uint32(downSampleRatio), + c_enum(downSampleMode), c_uint16(segmentIndex), + byref(overflow)) self.checkResult(m) return (numSamplesReturned.value, overflow.value) def _lowLevelSetDeviceResolution(self, resolution): self.resolution = resolution m = self.lib.ps4000aSetDeviceResolution( - c_int16(self.handle), c_enum(resolution) - ) + c_int16(self.handle), + c_enum(resolution)) self.checkResult(m) def _lowLevelChangePowerSource(self, powerstate): m = self.lib.ps4000aChangePowerSource( - c_int16(self.handle), c_enum(powerstate) - ) + c_int16(self.handle), + c_enum(powerstate)) self.checkResult(m) - def _lowLevelGetValuesBulk( - self, - numSamples, - fromSegment, - toSegment, - downSampleRatio, - downSampleMode, - overflow, - ): + def _lowLevelGetValuesBulk(self, numSamples, fromSegment, toSegment, + downSampleRatio, downSampleMode, overflow): """Copy data from several memory segments at once.""" overflowPoint = overflow.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps4000aGetValuesBulk( @@ -547,40 +439,27 @@ def _lowLevelGetValuesBulk( c_int32(toSegment), c_int32(downSampleRatio), c_enum(downSampleMode), - overflowPoint, + overflowPoint ) self.checkResult(m) - def _lowLevelSetDataBufferBulk( - self, channel, data, segmentIndex, downSampleMode - ): + def _lowLevelSetDataBufferBulk(self, channel, data, segmentIndex, + downSampleMode): """Just calls setDataBuffer with argument order changed. For compatibility with current picobase.py. """ - self._lowLevelSetDataBuffer( - channel, data, downSampleMode, segmentIndex - ) + self._lowLevelSetDataBuffer(channel, data, downSampleMode, + segmentIndex) #################################################################### # Untested functions below # # # #################################################################### - def _lowLevelSetSigGenBuiltInSimple( - self, - offsetVoltage, - pkToPk, - waveType, - frequency, - shots, - triggerType, - triggerSource, - stopFreq, - increment, - dwellTime, - sweepType, - numSweeps, - ): + def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, + frequency, shots, triggerType, + triggerSource, stopFreq, increment, + dwellTime, sweepType, numSweeps): if stopFreq is None: stopFreq = frequency @@ -589,23 +468,16 @@ def _lowLevelSetSigGenBuiltInSimple( c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), - c_float(stopFreq), - c_float(increment), - c_float(dwellTime), - c_enum(sweepType), - c_enum(0), - c_uint32(shots), - c_uint32(numSweeps), - c_enum(triggerType), - c_enum(triggerSource), - c_int16(0), - ) + c_float(frequency), c_float(stopFreq), + c_float(increment), c_float(dwellTime), + c_enum(sweepType), c_enum(0), + c_uint32(shots), c_uint32(numSweeps), + c_enum(triggerType), c_enum(triggerSource), + c_int16(0)) self.checkResult(m) - def _lowLevelGetMaxDownSampleRatio( - self, noOfUnaggregatedSamples, downSampleRatioMode, segmentIndex - ): + def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, + downSampleRatioMode, segmentIndex): maxDownSampleRatio = c_uint32() m = self.lib.ps4000aGetMaxDownSampleRatio( @@ -613,8 +485,7 @@ def _lowLevelGetMaxDownSampleRatio( c_uint32(noOfUnaggregatedSamples), byref(maxDownSampleRatio), c_enum(downSampleRatioMode), - c_uint16(segmentIndex), - ) + c_uint16(segmentIndex)) self.checkResult(m) return maxDownSampleRatio.value @@ -622,9 +493,8 @@ def _lowLevelGetMaxDownSampleRatio( def _lowLevelGetNoOfCaptures(self): nCaptures = c_uint32() - m = self.lib.ps4000aGetNoOfCaptures( - c_int16(self.handle), byref(nCaptures) - ) + m = self.lib.ps4000aGetNoOfCaptures(c_int16(self.handle), + byref(nCaptures)) self.checkResult(m) return nCaptures.value @@ -637,39 +507,37 @@ def _lowLevelGetTriggerTimeOffset(self, segmentIndex): c_int16(self.handle), byref(time), byref(timeUnits), - c_uint16(segmentIndex), - ) + c_uint16(segmentIndex)) self.checkResult(m) if timeUnits.value == 0: # PS4000a_FS - return time.value * 1e-15 + return time.value * 1E-15 elif timeUnits.value == 1: # PS4000a_PS - return time.value * 1e-12 + return time.value * 1E-12 elif timeUnits.value == 2: # PS4000a_NS - return time.value * 1e-9 + return time.value * 1E-9 elif timeUnits.value == 3: # PS4000a_US - return time.value * 1e-6 + return time.value * 1E-6 elif timeUnits.value == 4: # PS4000a_MS - return time.value * 1e-3 + return time.value * 1E-3 elif timeUnits.value == 5: # PS4000a_S - return time.value * 1e0 + return time.value * 1E0 else: raise TypeError("Unknown timeUnits %d" % timeUnits.value) def _lowLevelMemorySegments(self, nSegments): nMaxSamples = c_uint32() - m = self.lib.ps4000aMemorySegments( - c_int16(self.handle), c_uint16(nSegments), byref(nMaxSamples) - ) + m = self.lib.ps4000aMemorySegments(c_int16(self.handle), + c_uint16(nSegments), + byref(nMaxSamples)) self.checkResult(m) return nMaxSamples.value - def _lowLevelSetDataBuffers( - self, channel, bufferMax, bufferMin, downSampleRatioMode - ): + def _lowLevelSetDataBuffers(self, channel, bufferMax, bufferMin, + downSampleRatioMode): bufferMaxPtr = bufferMax.ctypes.data_as(POINTER(c_int16)) bufferMinPtr = bufferMin.ctypes.data_as(POINTER(c_int16)) bufferLth = len(bufferMax) @@ -679,8 +547,7 @@ def _lowLevelSetDataBuffers( c_enum(channel), bufferMaxPtr, bufferMinPtr, - c_uint32(bufferLth), - ) + c_uint32(bufferLth)) self.checkResult(m) def _lowLevelClearDataBuffers(self, channel): @@ -689,14 +556,13 @@ def _lowLevelClearDataBuffers(self, channel): c_enum(channel), c_void_p(), c_void_p(), - c_uint32(0), - ) + c_uint32(0)) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, nCaptures): m = self.lib.ps4000aSetNoOfCaptures( - c_int16(self.handle), c_uint16(nCaptures) - ) + c_int16(self.handle), + c_uint16(nCaptures)) self.checkResult(m) # ETS Functions @@ -751,35 +617,27 @@ def _lowLevelGetValuesOverlappedBulk(self): pass # Streaming related functions - def _lowLevelGetStreamingLatestValues( - self, lpPs4000Ready, pParameter=c_void_p() - ): + def _lowLevelGetStreamingLatestValues(self, lpPs4000Ready, + pParameter=c_void_p()): m = self.lib.ps4000aGetStreamingLatestValues( - c_uint16(self.handle), lpPs4000Ready, pParameter - ) + c_uint16(self.handle), + lpPs4000Ready, + pParameter) self.checkResult(m) def _lowLevelNoOfStreamingValues(self): noOfValues = c_uint32() - m = self.lib.ps4000aNoOfStreamingValues( - c_int16(self.handle), byref(noOfValues) - ) + m = self.lib.ps4000aNoOfStreamingValues(c_int16(self.handle), + byref(noOfValues)) self.checkResult(m) return noOfValues.value - def _lowLevelRunStreaming( - self, - sampleInterval, - sampleIntervalTimeUnits, - maxPreTriggerSamples, - maxPostTriggerSamples, - autoStop, - downSampleRatio, - downSampleRatioMode, - overviewBufferSize, - ): + def _lowLevelRunStreaming(self, sampleInterval, sampleIntervalTimeUnits, + maxPreTriggerSamples, maxPostTriggerSamples, + autoStop, downSampleRatio, downSampleRatioMode, + overviewBufferSize): m = self.lib.ps4000aRunStreaming( c_int16(self.handle), byref(c_uint32(sampleInterval)), @@ -789,8 +647,7 @@ def _lowLevelRunStreaming( c_int16(autoStop), c_uint32(downSampleRatio), c_enum(downSampleRatioMode), - c_uint32(overviewBufferSize), - ) + c_uint32(overviewBufferSize)) self.checkResult(m) diff --git a/picoscope/ps5000.py b/picoscope/ps5000.py index 6ceee36..fdce198 100644 --- a/picoscope/ps5000.py +++ b/picoscope/ps5000.py @@ -58,17 +58,8 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import ( - byref, - POINTER, - create_string_buffer, - c_float, - c_int16, - c_int32, - c_uint32, - c_uint64, - c_void_p, -) +from ctypes import byref, POINTER, create_string_buffer, c_float, \ + c_int16, c_int32, c_uint32, c_uint64, c_void_p from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -89,61 +80,35 @@ class PS5000(_PicoscopeBase): # The 10V and 20V ranges are only allowed in high impedence modes CHANNEL_RANGE = [ - {"rangeV": 10e-3, "apivalue": 1, "rangeStr": "10 mV"}, - {"rangeV": 20e-3, "apivalue": 2, "rangeStr": "20 mV"}, - {"rangeV": 50e-3, "apivalue": 3, "rangeStr": "50 mV"}, - {"rangeV": 100e-3, "apivalue": 4, "rangeStr": "100 mV"}, - {"rangeV": 200e-3, "apivalue": 5, "rangeStr": "200 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + {"rangeV": 10E-3, "apivalue": 1, "rangeStr": "10 mV"}, + {"rangeV": 20E-3, "apivalue": 2, "rangeStr": "20 mV"}, + {"rangeV": 50E-3, "apivalue": 3, "rangeStr": "50 mV"}, + {"rangeV": 100E-3, "apivalue": 4, "rangeStr": "100 mV"}, + {"rangeV": 200E-3, "apivalue": 5, "rangeStr": "200 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}] NUM_CHANNELS = 4 - CHANNELS = { - "A": 0, - "B": 1, - "C": 2, - "D": 3, - "External": 4, - "MaxChannels": 4, - "TriggerAux": 5, - } + CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, + "External": 4, "MaxChannels": 4, "TriggerAux": 5} CHANNEL_COUPLINGS = {"DC": 1, "AC": 0} - WAVE_TYPES = { - "Sine": 0, - "Square": 1, - "Triangle": 2, - "RampUp": 3, - "RampDown": 4, - "Sinc": 5, - "Gaussian": 6, - "HalfSine": 7, - "DCVoltage": 8, - "WhiteNoise": 9, - } + WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, + "RampUp": 3, "RampDown": 4, + "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, + "WhiteNoise": 9} SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} - SIGGEN_TRIGGER_TYPES = { - "Rising": 0, - "Falling": 1, - "GateHigh": 2, - "GateLow": 3, - } - SIGGEN_TRIGGER_SOURCES = { - "None": 0, - "ScopeTrig": 1, - "AuxIn": 2, - "ExtIn": 3, - "SoftTrig": 4, - "TriggerRaw": 5, - } + SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, + "GateHigh": 2, "GateLow": 3} + SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, "AuxIn": 2, + "ExtIn": 3, "SoftTrig": 4, "TriggerRaw": 5} # This is actually different depending on the AB/CD models # I wonder how we could detect the difference between the oscilloscopes @@ -157,7 +122,7 @@ class PS5000(_PicoscopeBase): AWGBufferAddressWidth = 14 AWGMaxSamples = 2 ** AWGBufferAddressWidth - AWGDACInterval = 5e-9 # in seconds + AWGDACInterval = 5E-9 # in seconds AWGDACFrequency = 1 / AWGDACInterval # Note this is NOT what is written in the Programming guide as of version @@ -171,23 +136,18 @@ class PS5000(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLLs.""" - if platform.system() == "Linux": + if platform.system() == 'Linux': from ctypes import cdll - # ok I don't know what is wrong with my installer, # but I need to include .so.2 self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so.2") - elif platform.system() == "Darwin": + elif platform.system() == 'Darwin': from picoscope.darwin_utils import LoadLibraryDarwin - self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - - self.lib = windll.LoadLibrary( - find_library(str(self.LIBNAME + ".dll")) - ) + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) super(PS5000, self).__init__(serialNumber, connect) @@ -220,9 +180,9 @@ def _lowLevelOpenUnitProgress(self): progressPercent = c_int16() handle = c_int16() - m = self.lib.ps5000OpenUnitProgress( - byref(handle), byref(progressPercent), byref(complete) - ) + m = self.lib.ps5000OpenUnitProgress(byref(handle), + byref(progressPercent), + byref(complete)) self.checkResult(m) if complete.value != 0: @@ -247,29 +207,22 @@ def _lowLevelEnumerateUnits(self): serialLth = c_int16(count.value * (8 + 2)) serials = create_string_buffer(serialLth.value + 1) - m = self.lib.ps5000EnumerateUnits( - byref(count), serials, byref(serialLth) - ) + m = self.lib.ps5000EnumerateUnits(byref(count), serials, + byref(serialLth)) self.checkResult(m) - serialList = str(serials.value.decode("utf-8")).split(",") + serialList = str(serials.value.decode('utf-8')).split(',') serialList = [x.strip() for x in serialList] return serialList - def _lowLevelSetChannel( - self, chNum, enabled, coupling, VRange, VOffset, BWLimited - ): - m = self.lib.ps5000SetChannel( - c_int16(self.handle), - c_enum(chNum), - c_int16(enabled), - c_enum(coupling), - c_enum(VRange), - c_float(VOffset), - c_enum(BWLimited), - ) # 2 for PS6404 + def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, + BWLimited): + m = self.lib.ps5000SetChannel(c_int16(self.handle), c_enum(chNum), + c_int16(enabled), c_enum(coupling), + c_enum(VRange), c_float(VOffset), + c_enum(BWLimited)) # 2 for PS6404 self.checkResult(m) def _lowLevelStop(self): @@ -280,67 +233,41 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps6000GetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps6000GetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), byref(requiredSize), + c_enum(info)) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps5000GetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps5000GetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), + byref(requiredSize), c_enum(info)) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode("utf-8") + return s.value.decode('utf-8') def _lowLevelFlashLed(self, times): m = self.lib.ps5000FlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger( - self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms - ): + def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, + direction, delay, timeout_ms): m = self.lib.ps5000SetSimpleTrigger( - c_int16(self.handle), - c_int16(enabled), - c_enum(trigsrc), - c_int16(threshold_adc), - c_enum(direction), - c_uint32(delay), - c_int16(timeout_ms), - ) + c_int16(self.handle), c_int16(enabled), + c_enum(trigsrc), c_int16(threshold_adc), + c_enum(direction), c_uint32(delay), c_int16(timeout_ms)) self.checkResult(m) - def _lowLevelRunBlock( - self, - numPreTrigSamples, - numPostTrigSamples, - timebase, - oversample, - segmentIndex, - ): + def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, + timebase, oversample, segmentIndex): timeIndisposedMs = c_int32() m = self.lib.ps5000RunBlock( - c_int16(self.handle), - c_uint32(numPreTrigSamples), - c_uint32(numPostTrigSamples), - c_uint32(timebase), - c_int16(oversample), - byref(timeIndisposedMs), - c_uint32(segmentIndex), - c_void_p(), - c_void_p(), - ) + c_int16(self.handle), c_uint32(numPreTrigSamples), + c_uint32(numPostTrigSamples), c_uint32(timebase), + c_int16(oversample), byref(timeIndisposedMs), + c_uint32(segmentIndex), c_void_p(), c_void_p()) self.checkResult(m) return timeIndisposedMs.value @@ -358,25 +285,20 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): maxSamples = c_int32() sampleRate = c_float() - m = self.lib.ps5000GetTimebase2( - c_int16(self.handle), - c_uint32(tb), - c_uint32(noSamples), - byref(sampleRate), - c_int16(oversample), - byref(maxSamples), - c_uint32(segmentIndex), - ) + m = self.lib.ps5000GetTimebase2(c_int16(self.handle), c_uint32(tb), + c_uint32(noSamples), byref(sampleRate), + c_int16(oversample), byref(maxSamples), + c_uint32(segmentIndex)) self.checkResult(m) - return (sampleRate.value / 1.0e9, maxSamples.value) + return (sampleRate.value / 1.0E9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """Return sample time in seconds to timebase as int for API calls.""" - maxSampleTime = ((2 ** 32 - 1) - 2) / 125000000 + maxSampleTime = (((2 ** 32 - 1) - 2) / 125000000) - if sampleTimeS < 8e-9: - timebase = math.floor(math.log(sampleTimeS * 1e9, 2)) + if sampleTimeS < 8E-9: + timebase = math.floor(math.log(sampleTimeS * 1E9, 2)) timebase = max(timebase, 0) else: # Otherwise in range 2^32-1 @@ -392,14 +314,13 @@ def getTimeBaseNum(self, sampleTimeS): def getTimestepFromTimebase(self, timebase): """Return timebase to sampletime as seconds.""" if timebase < 3: - dt = 2.0 ** timebase / 1e9 + dt = 2. ** timebase / 1E9 else: - dt = (timebase - 2) / 125000000.0 + dt = (timebase - 2) / 125000000. return dt - def _lowLevelSetDataBuffer( - self, channel, data, downSampleMode, segmentIndex - ): + def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, + segmentIndex): """Set the data buffer. Be sure to call _lowLevelClearDataBuffer @@ -412,45 +333,26 @@ def _lowLevelSetDataBuffer( dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) - m = self.lib.ps5000SetDataBuffer( - c_int16(self.handle), - c_enum(channel), - dataPtr, - c_uint32(numSamples), - c_enum(downSampleMode), - ) + m = self.lib.ps5000SetDataBuffer(c_int16(self.handle), c_enum(channel), + dataPtr, c_uint32(numSamples), + c_enum(downSampleMode)) self.checkResult(m) def _lowLevelClearDataBuffer(self, channel, segmentIndex): - m = self.lib.ps5000SetDataBuffer( - c_int16(self.handle), - c_enum(channel), - c_void_p(), - c_uint32(0), - c_enum(0), - ) + m = self.lib.ps5000SetDataBuffer(c_int16(self.handle), c_enum(channel), + c_void_p(), c_uint32(0), c_enum(0)) self.checkResult(m) - def _lowLevelGetValues( - self, - numSamples, - startIndex, - downSampleRatio, - downSampleMode, - segmentIndex, - ): + def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, + downSampleMode, segmentIndex): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps5000GetValues( - c_int16(self.handle), - c_uint32(startIndex), - byref(numSamplesReturned), - c_uint32(downSampleRatio), - c_enum(downSampleMode), - c_uint32(segmentIndex), - byref(overflow), - ) + c_int16(self.handle), c_uint32(startIndex), + byref(numSamplesReturned), c_uint32(downSampleRatio), + c_enum(downSampleMode), c_uint32(segmentIndex), + byref(overflow)) self.checkResult(m) return (numSamplesReturned.value, overflow.value) @@ -458,56 +360,36 @@ def _lowLevelGetValues( # Untested functions below # # # #################################################################### - def _lowLevelSetAWGSimpleDeltaPhase( - self, - waveform, - deltaPhase, - offsetVoltage, - pkToPk, - indexMode, - shots, - triggerType, - triggerSource, - ): + def _lowLevelSetAWGSimpleDeltaPhase(self, waveform, deltaPhase, + offsetVoltage, pkToPk, indexMode, + shots, triggerType, triggerSource): """Waveform should be an array of shorts.""" waveformPtr = waveform.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps5000SetSigGenArbitrary( c_int16(self.handle), - c_uint32(int(offsetVoltage * 1e6)), # offset voltage in microvolts - c_uint32(int(pkToPk * 1e6)), # pkToPk in microvolts - c_uint32(int(deltaPhase)), # startDeltaPhase - c_uint32(int(deltaPhase)), # stopDeltaPhase - c_uint32(0), # deltaPhaseIncrement - c_uint32(0), # dwellCount - waveformPtr, # arbitraryWaveform - c_int32(len(waveform)), # arbitraryWaveformSize - c_enum(0), # sweepType for deltaPhase - c_enum(0), # operation (adding random noise and whatnot) - c_enum(indexMode), # single, dual, quad + c_uint32(int(offsetVoltage * 1E6)), # offset voltage in microvolts + c_uint32(int(pkToPk * 1E6)), # pkToPk in microvolts + c_uint32(int(deltaPhase)), # startDeltaPhase + c_uint32(int(deltaPhase)), # stopDeltaPhase + c_uint32(0), # deltaPhaseIncrement + c_uint32(0), # dwellCount + waveformPtr, # arbitraryWaveform + c_int32(len(waveform)), # arbitraryWaveformSize + c_enum(0), # sweepType for deltaPhase + c_enum(0), # operation (adding random noise and whatnot) + c_enum(indexMode), # single, dual, quad c_uint32(shots), - c_uint32(0), # sweeps + c_uint32(0), # sweeps c_uint32(triggerType), c_uint32(triggerSource), - c_int16(0), - ) # extInThreshold + c_int16(0)) # extInThreshold self.checkResult(m) - def _lowLevelSetSigGenBuiltInSimple( - self, - offsetVoltage, - pkToPk, - waveType, - frequency, - shots, - triggerType, - triggerSource, - stopFreq, - increment, - dwellTime, - sweepType, - numSweeps, - ): + def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, + frequency, shots, triggerType, + triggerSource, stopFreq, increment, + dwellTime, sweepType, numSweeps): # TODO, I just noticed that V2 exists # Maybe change to V2 in the future @@ -519,18 +401,12 @@ def _lowLevelSetSigGenBuiltInSimple( c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), - c_float(stopFreq), - c_float(increment), - c_float(dwellTime), - c_enum(sweepType), - c_enum(0), - c_uint32(shots), - c_uint32(numSweeps), - c_enum(triggerType), - c_enum(triggerSource), - c_int16(0), - ) + c_float(frequency), c_float(stopFreq), + c_float(increment), c_float(dwellTime), + c_enum(sweepType), c_enum(0), + c_uint32(shots), c_uint32(numSweeps), + c_enum(triggerType), c_enum(triggerSource), + c_int16(0)) self.checkResult(m) def _lowLevelGetAnalogueOffset(self, range, coupling): @@ -539,28 +415,20 @@ def _lowLevelGetAnalogueOffset(self, range, coupling): minimumVoltage = c_float() m = self.lib.ps5000GetAnalogueOffset( - c_int16(self.handle), - c_enum(range), - c_enum(coupling), - byref(maximumVoltage), - byref(minimumVoltage), - ) + c_int16(self.handle), c_enum(range), c_enum(coupling), + byref(maximumVoltage), byref(minimumVoltage)) self.checkResult(m) return (maximumVoltage.value, minimumVoltage.value) - def _lowLevelGetMaxDownSampleRatio( - self, noOfUnaggregatedSamples, downSampleRatioMode, segmentIndex - ): + def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, + downSampleRatioMode, segmentIndex): maxDownSampleRatio = c_uint32() m = self.lib.ps5000GetMaxDownSampleRatio( - c_int16(self.handle), - c_uint32(noOfUnaggregatedSamples), + c_int16(self.handle), c_uint32(noOfUnaggregatedSamples), byref(maxDownSampleRatio), - c_enum(downSampleRatioMode), - c_uint32(segmentIndex), - ) + c_enum(downSampleRatioMode), c_uint32(segmentIndex)) self.checkResult(m) return maxDownSampleRatio.value @@ -568,9 +436,8 @@ def _lowLevelGetMaxDownSampleRatio( def _lowLevelGetNoOfCaptures(self): nCaptures = c_uint32() - m = self.lib.ps5000GetNoOfCaptures( - c_int16(self.handle), byref(nCaptures) - ) + m = self.lib.ps5000GetNoOfCaptures(c_int16(self.handle), + byref(nCaptures)) self.checkResult(m) return nCaptures.value @@ -580,132 +447,101 @@ def _lowLevelGetTriggerTimeOffset(self, segmentIndex): timeUnits = c_enum() m = self.lib.ps5000GetTriggerTimeOffset64( - c_int16(self.handle), - byref(time), - byref(timeUnits), - c_uint32(segmentIndex), - ) + c_int16(self.handle), byref(time), + byref(timeUnits), c_uint32(segmentIndex)) self.checkResult(m) - if timeUnits.value == 0: # PS5000_FS - return time.value * 1e-15 + if timeUnits.value == 0: # PS5000_FS + return time.value * 1E-15 elif timeUnits.value == 1: # PS5000_PS - return time.value * 1e-12 + return time.value * 1E-12 elif timeUnits.value == 2: # PS5000_NS - return time.value * 1e-9 + return time.value * 1E-9 elif timeUnits.value == 3: # PS5000_US - return time.value * 1e-6 + return time.value * 1E-6 elif timeUnits.value == 4: # PS5000_MS - return time.value * 1e-3 + return time.value * 1E-3 elif timeUnits.value == 5: # PS5000_S - return time.value * 1e0 + return time.value * 1E0 else: raise TypeError("Unknown timeUnits %d" % timeUnits.value) def _lowLevelMemorySegments(self, nSegments): nMaxSamples = c_uint32() - m = self.lib.ps5000MemorySegments( - c_int16(self.handle), c_uint32(nSegments), byref(nMaxSamples) - ) + m = self.lib.ps5000MemorySegments(c_int16(self.handle), + c_uint32(nSegments), + byref(nMaxSamples)) self.checkResult(m) return nMaxSamples.value - def _lowLevelSetDataBuffers( - self, channel, bufferMax, bufferMin, downSampleRatioMode - ): + def _lowLevelSetDataBuffers(self, channel, bufferMax, bufferMin, + downSampleRatioMode): bufferMaxPtr = bufferMax.ctypes.data_as(POINTER(c_int16)) bufferMinPtr = bufferMin.ctypes.data_as(POINTER(c_int16)) bufferLth = len(bufferMax) - m = self.lib.ps5000SetDataBuffers( - c_int16(self.handle), - c_enum(channel), - bufferMaxPtr, - bufferMinPtr, - c_uint32(bufferLth), - c_enum(downSampleRatioMode), - ) + m = self.lib.ps5000SetDataBuffers(c_int16(self.handle), + c_enum(channel), + bufferMaxPtr, bufferMinPtr, + c_uint32(bufferLth), + c_enum(downSampleRatioMode)) self.checkResult(m) def _lowLevelClearDataBuffers(self, channel): m = self.lib.ps5000SetDataBuffers( - c_int16(self.handle), - c_enum(channel), - c_void_p(), - c_void_p(), - c_uint32(0), - c_enum(0), - ) + c_int16(self.handle), c_enum(channel), + c_void_p(), c_void_p(), c_uint32(0), c_enum(0)) self.checkResult(m) # Bulk values. # These would be nice, but the user would have to provide us # with an array. # we would have to make sure that it is contiguous amonts other things - def _lowLevelGetValuesBulk( - self, - numSamples, - fromSegmentIndex, - toSegmentIndex, - downSampleRatio, - downSampleRatioMode, - overflow, - ): + def _lowLevelGetValuesBulk(self, + numSamples, fromSegmentIndex, toSegmentIndex, + downSampleRatio, downSampleRatioMode, + overflow): noOfSamples = c_uint32(numSamples) m = self.lib.ps5000GetValuesBulk( c_int16(self.handle), byref(noOfSamples), - c_uint32(fromSegmentIndex), - c_uint32(toSegmentIndex), - c_uint32(downSampleRatio), - c_enum(downSampleRatioMode), - overflow.ctypes.data_as(POINTER(c_int16)), - ) + c_uint32(fromSegmentIndex), c_uint32(toSegmentIndex), + c_uint32(downSampleRatio), c_enum(downSampleRatioMode), + overflow.ctypes.data_as(POINTER(c_int16)) + ) self.checkResult(m) return noOfSamples.value - def _lowLevelSetDataBufferBulk( - self, channel, buffer, waveform, downSampleRatioMode - ): + def _lowLevelSetDataBufferBulk(self, channel, buffer, waveform, + downSampleRatioMode): bufferPtr = buffer.ctypes.data_as(POINTER(c_int16)) bufferLth = len(buffer) m = self.lib.ps5000SetDataBufferBulk( c_int16(self.handle), - c_enum(channel), - bufferPtr, - c_uint32(bufferLth), - c_uint32(waveform), - c_enum(downSampleRatioMode), - ) + c_enum(channel), bufferPtr, c_uint32(bufferLth), + c_uint32(waveform), c_enum(downSampleRatioMode)) self.checkResult(m) - def _lowLevelSetDataBuffersBulk( - self, channel, bufferMax, bufferMin, waveform, downSampleRatioMode - ): + def _lowLevelSetDataBuffersBulk(self, channel, bufferMax, bufferMin, + waveform, downSampleRatioMode): bufferMaxPtr = bufferMax.ctypes.data_as(POINTER(c_int16)) bufferMinPtr = bufferMin.ctypes.data_as(POINTER(c_int16)) bufferLth = len(bufferMax) m = self.lib.ps5000SetDataBuffersBulk( - c_int16(self.handle), - c_enum(channel), - bufferMaxPtr, - bufferMinPtr, - c_uint32(bufferLth), - c_uint32(waveform), - c_enum(downSampleRatioMode), - ) + c_int16(self.handle), c_enum(channel), + bufferMaxPtr, bufferMinPtr, c_uint32(bufferLth), + c_uint32(waveform), c_enum(downSampleRatioMode)) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, nCaptures): - m = self.lib.ps5000SetNoOfCaptures( - c_int16(self.handle), c_uint32(nCaptures) - ) + m = self.lib.ps5000SetNoOfCaptures(c_int16(self.handle), + c_uint32(nCaptures)) self.checkResult(m) # ETS Functions @@ -766,9 +602,8 @@ def _lowLevelGetStreamingLatestValues(): def _lowLevelNoOfStreamingValues(self): noOfValues = c_uint32() - m = self.lib.ps5000NoOfStreamingValues( - c_int16(self.handle), byref(noOfValues) - ) + m = self.lib.ps5000NoOfStreamingValues(c_int16(self.handle), + byref(noOfValues)) self.checkResult(m) return noOfValues.value diff --git a/picoscope/ps5000a.py b/picoscope/ps5000a.py index b426ebe..2417378 100644 --- a/picoscope/ps5000a.py +++ b/picoscope/ps5000a.py @@ -55,17 +55,8 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import ( - byref, - POINTER, - create_string_buffer, - c_float, - c_int16, - c_int32, - c_uint32, - c_void_p, - c_int64, -) +from ctypes import byref, POINTER, create_string_buffer, c_float, \ + c_int16, c_int32, c_uint32, c_void_p, c_int64 from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -77,65 +68,39 @@ class PS5000a(_PicoscopeBase): LIBNAME = "ps5000a" NUM_CHANNELS = 4 - CHANNELS = { - "A": 0, - "B": 1, - "C": 2, - "D": 3, - "External": 4, - "MaxChannels": 4, - "TriggerAux": 5, - } + CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, + "External": 4, "MaxChannels": 4, "TriggerAux": 5} ADC_RESOLUTIONS = {"8": 0, "12": 1, "14": 2, "15": 3, "16": 4} - CHANNEL_RANGE = [ - {"rangeV": 10e-3, "apivalue": 0, "rangeStr": "10 mV"}, - {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + CHANNEL_RANGE = [{"rangeV": 10E-3, "apivalue": 0, "rangeStr": "10 mV"}, + {"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] CHANNEL_COUPLINGS = {"DC": 1, "AC": 0} # has_sig_gen = True - WAVE_TYPES = { - "Sine": 0, - "Square": 1, - "Triangle": 2, - "RampUp": 3, - "RampDown": 4, - "Sinc": 5, - "Gaussian": 6, - "HalfSine": 7, - "DCVoltage": 8, - "WhiteNoise": 9, - } + WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, + "RampUp": 3, "RampDown": 4, + "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, + "WhiteNoise": 9} SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} - SIGGEN_TRIGGER_TYPES = { - "Rising": 0, - "Falling": 1, - "GateHigh": 2, - "GateLow": 3, - } - SIGGEN_TRIGGER_SOURCES = { - "None": 0, - "ScopeTrig": 1, - "AuxIn": 2, - "ExtIn": 3, - "SoftTrig": 4, - "TriggerRaw": 5, - } + SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, + "GateHigh": 2, "GateLow": 3} + SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, "AuxIn": 2, + "ExtIn": 3, "SoftTrig": 4, "TriggerRaw": 5} # This is actually different depending on the AB/CD models # I wonder how we could detect the difference between the oscilloscopes @@ -147,7 +112,7 @@ class PS5000a(_PicoscopeBase): AWGPhaseAccumulatorSize = 32 - AWGDACInterval = 5e-9 # in seconds + AWGDACInterval = 5E-9 # in seconds AWGDACFrequency = 1 / AWGDACInterval AWG_INDEX_MODES = {"Single": 0, "Dual": 1, "Quad": 2} @@ -161,21 +126,16 @@ class PS5000a(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLL etc.""" - if platform.system() == "Linux": + if platform.system() == 'Linux': from ctypes import cdll - self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so") - elif platform.system() == "Darwin": + elif platform.system() == 'Darwin': from picoscope.darwin_utils import LoadLibraryDarwin - self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - - self.lib = windll.LoadLibrary( - find_library(str(self.LIBNAME + ".dll")) - ) + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) self.resolution = self.ADC_RESOLUTIONS["8"] @@ -188,9 +148,8 @@ def _lowLevelOpenUnit(self, sn): else: serialNullTermStr = None # Passing None is the same as passing NULL - m = self.lib.ps5000aOpenUnit( - byref(c_handle), serialNullTermStr, self.resolution - ) + m = self.lib.ps5000aOpenUnit(byref(c_handle), serialNullTermStr, + self.resolution) self.handle = c_handle.value # This will check if the power supply is not connected @@ -211,18 +170,18 @@ def _lowLevelOpenUnit(self, sn): # Model 5444B identifies itself properly in VariantInfo, I will assume # the others do as well. - self.model = self.getUnitInfo("VariantInfo") + self.model = self.getUnitInfo('VariantInfo') # print("Checking variant, found: " + str(self.model)) - if self.model in ("5244B", "5444B"): - self.AWGBufferAddressWidth = math.log(3 * 2 ** 14, 2) + if self.model in ('5244B', '5444B'): + self.AWGBufferAddressWidth = math.log(3 * 2**14, 2) self.AWGMaxVal = 32767 self.AWGMinVal = -32768 self.AWGMaxSamples = 49152 - elif self.model in ("5243B", "5443B", "5243D", "5443D"): + elif self.model in ('5243B', '5443B', '5243D', '5443D'): self.AWGBufferAddressWidth = 15 self.AWGMaxVal = 32767 self.AWGMinVal = -32768 - self.AWGMaxSamples = 2 ** self.AWGBufferAddressWidth + self.AWGMaxSamples = 2**self.AWGBufferAddressWidth else: # This is what the previous PS5000a used for all scopes. # I am leaving it the same, although I think the AWGMaxVal and @@ -235,23 +194,17 @@ def _lowLevelOpenUnit(self, sn): # http://www.picotech.com/support/topic13217.html self.AWGMaxVal = 0x0FFF self.AWGMinVal = 0x0000 - self.AWGMaxSamples = 2 ** self.AWGBufferAddressWidth + self.AWGMaxSamples = 2**self.AWGBufferAddressWidth def _lowLevelCloseUnit(self): m = self.lib.ps5000aCloseUnit(c_int16(self.handle)) self.checkResult(m) - def _lowLevelSetChannel( - self, chNum, enabled, coupling, VRange, VOffset, bandwidth - ): - m = self.lib.ps5000aSetChannel( - c_int16(self.handle), - c_enum(chNum), - c_int16(enabled), - c_enum(coupling), - c_enum(VRange), - c_float(VOffset), - ) + def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, + bandwidth): + m = self.lib.ps5000aSetChannel(c_int16(self.handle), c_enum(chNum), + c_int16(enabled), c_enum(coupling), + c_enum(VRange), c_float(VOffset)) self.checkResult(m) # The error this might through are @@ -269,19 +222,17 @@ def _lowLevelSetChannel( # change the bandwidth separately # changing the bandwidth would be it's own function (implemented below) if bandwidth: - m = self.lib.ps5000aSetBandwidthFilter( - c_int16(self.handle), c_enum(chNum), c_enum(1) - ) + m = self.lib.ps5000aSetBandwidthFilter(c_int16(self.handle), + c_enum(chNum), c_enum(1)) else: - m = self.lib.ps5000aSetBandwidthFilter( - c_int16(self.handle), c_enum(chNum), c_enum(0) - ) + m = self.lib.ps5000aSetBandwidthFilter(c_int16(self.handle), + c_enum(chNum), c_enum(0)) self.checkResult(m) def _lowLevelSetBandwidthFilter(self, channel, bandwidth): - m = self.lib.ps5000aSetBandwidthFilter( - c_int16(self.handle), c_enum(channel), c_enum(bandwidth) - ) + m = self.lib.ps5000aSetBandwidthFilter(c_int16(self.handle), + c_enum(channel), + c_enum(bandwidth)) self.checkResult(m) def _lowLevelStop(self): @@ -292,67 +243,42 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps5000aGetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps5000aGetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), byref(requiredSize), + c_enum(info)) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps5000aGetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps5000aGetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), + byref(requiredSize), c_enum(info)) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode("utf-8") + return s.value.decode('utf-8') def _lowLevelFlashLed(self, times): m = self.lib.ps5000aFlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger( - self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms - ): + def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, + direction, delay, timeout_ms): m = self.lib.ps5000aSetSimpleTrigger( - c_int16(self.handle), - c_int16(enabled), - c_enum(trigsrc), - c_int16(threshold_adc), - c_enum(direction), - c_uint32(delay), - c_int16(timeout_ms), - ) + c_int16(self.handle), c_int16(enabled), + c_enum(trigsrc), c_int16(threshold_adc), + c_enum(direction), c_uint32(delay), c_int16(timeout_ms)) self.checkResult(m) - def _lowLevelRunBlock( - self, - numPreTrigSamples, - numPostTrigSamples, - timebase, - oversample, - segmentIndex, - ): + def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, + timebase, oversample, segmentIndex): # Oversample is NOT used! timeIndisposedMs = c_int32() m = self.lib.ps5000aRunBlock( - c_int16(self.handle), - c_uint32(numPreTrigSamples), - c_uint32(numPostTrigSamples), - c_uint32(timebase), - byref(timeIndisposedMs), - c_uint32(segmentIndex), - c_void_p(), - c_void_p(), - ) + c_int16(self.handle), c_uint32(numPreTrigSamples), + c_uint32(numPostTrigSamples), c_uint32(timebase), + byref(timeIndisposedMs), c_uint32(segmentIndex), + c_void_p(), c_void_p()) self.checkResult(m) return timeIndisposedMs.value @@ -374,24 +300,21 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): maxSamples = c_int32() sampleRate = c_float() - m = self.lib.ps5000aGetTimebase2( - c_int16(self.handle), - c_uint32(tb), - c_uint32(noSamples), - byref(sampleRate), - byref(maxSamples), - c_uint32(segmentIndex), - ) + m = self.lib.ps5000aGetTimebase2(c_int16(self.handle), c_uint32(tb), + c_uint32(noSamples), + byref(sampleRate), + byref(maxSamples), + c_uint32(segmentIndex)) self.checkResult(m) - return (sampleRate.value / 1.0e9, maxSamples.value) + return (sampleRate.value / 1.0E9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """Convert sample time in S to something to pass to API Call.""" if self.resolution == self.ADC_RESOLUTIONS["8"]: - maxSampleTime = ((2 ** 32 - 1) - 2) / 125000000 - if sampleTimeS < 8.0e-9: - st = math.floor(math.log(sampleTimeS * 1e9, 2)) + maxSampleTime = (((2 ** 32 - 1) - 2) / 125000000) + if sampleTimeS < 8.0E-9: + st = math.floor(math.log(sampleTimeS * 1E9, 2)) st = max(st, 0) else: if sampleTimeS > maxSampleTime: @@ -399,9 +322,9 @@ def getTimeBaseNum(self, sampleTimeS): st = math.floor((sampleTimeS * 125000000) + 2) elif self.resolution == self.ADC_RESOLUTIONS["12"]: - maxSampleTime = ((2 ** 32 - 1) - 3) / 62500000 - if sampleTimeS < 16.0e-9: - st = math.floor(math.log(sampleTimeS * 5e8, 2)) + 1 + maxSampleTime = (((2 ** 32 - 1) - 3) / 62500000) + if sampleTimeS < 16.0E-9: + st = math.floor(math.log(sampleTimeS * 5E8, 2)) + 1 st = max(st, 1) else: if sampleTimeS > maxSampleTime: @@ -409,16 +332,15 @@ def getTimeBaseNum(self, sampleTimeS): st = math.floor((sampleTimeS * 62500000) + 3) elif (self.resolution == self.ADC_RESOLUTIONS["14"]) or ( - self.resolution == self.ADC_RESOLUTIONS["15"] - ): - maxSampleTime = ((2 ** 32 - 1) - 2) / 125000000 + self.resolution == self.ADC_RESOLUTIONS["15"]): + maxSampleTime = (((2 ** 32 - 1) - 2) / 125000000) if sampleTimeS > maxSampleTime: sampleTimeS = maxSampleTime st = math.floor((sampleTimeS * 125000000) + 2) st = max(st, 3) elif self.resolution == self.ADC_RESOLUTIONS["16"]: - maxSampleTime = ((2 ** 32 - 1) - 3) / 62500000 + maxSampleTime = (((2 ** 32 - 1) - 3) / 62500000) if sampleTimeS > maxSampleTime: sampleTimeS = maxSampleTime st = math.floor((sampleTimeS * 62500000) + 3) @@ -435,60 +357,49 @@ def getTimestepFromTimebase(self, timebase): """Return Timestep from timebase.""" if self.resolution == self.ADC_RESOLUTIONS["8"]: if timebase < 3: - dt = 2.0 ** timebase / 1.0e9 + dt = 2. ** timebase / 1.0E9 else: - dt = (timebase - 2.0) / 125000000.0 + dt = (timebase - 2.0) / 125000000. elif self.resolution == self.ADC_RESOLUTIONS["12"]: if timebase < 4: - dt = 2.0 ** (timebase - 1) / 5.0e8 + dt = 2. ** (timebase - 1) / 5.0E8 else: - dt = (timebase - 3.0) / 62500000.0 + dt = (timebase - 3.0) / 62500000. elif (self.resolution == self.ADC_RESOLUTIONS["14"]) or ( - self.resolution == self.ADC_RESOLUTIONS["15"] - ): - dt = (timebase - 2.0) / 125000000.0 + self.resolution == self.ADC_RESOLUTIONS["15"]): + dt = (timebase - 2.0) / 125000000. elif self.resolution == self.ADC_RESOLUTIONS["16"]: - dt = (timebase - 3.0) / 62500000.0 + dt = (timebase - 3.0) / 62500000. return dt - def _lowLevelSetAWGSimpleDeltaPhase( - self, - waveform, - deltaPhase, - offsetVoltage, - pkToPk, - indexMode, - shots, - triggerType, - triggerSource, - ): + def _lowLevelSetAWGSimpleDeltaPhase(self, waveform, deltaPhase, + offsetVoltage, pkToPk, indexMode, + shots, triggerType, triggerSource): """Waveform should be an array of shorts.""" waveformPtr = waveform.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps5000aSetSigGenArbitrary( c_int16(self.handle), - c_uint32(int(offsetVoltage * 1e6)), # offset voltage in microvolts - c_uint32(int(pkToPk * 1e6)), # pkToPk in microvolts - c_uint32(int(deltaPhase)), # startDeltaPhase - c_uint32(int(deltaPhase)), # stopDeltaPhase - c_uint32(0), # deltaPhaseIncrement - c_uint32(0), # dwellCount - waveformPtr, # arbitraryWaveform - c_int32(len(waveform)), # arbitraryWaveformSize - c_enum(0), # sweepType for deltaPhase - c_enum(0), # operation (adding random noise and whatnot) - c_enum(indexMode), # single, dual, quad + c_uint32(int(offsetVoltage * 1E6)), # offset voltage in microvolts + c_uint32(int(pkToPk * 1E6)), # pkToPk in microvolts + c_uint32(int(deltaPhase)), # startDeltaPhase + c_uint32(int(deltaPhase)), # stopDeltaPhase + c_uint32(0), # deltaPhaseIncrement + c_uint32(0), # dwellCount + waveformPtr, # arbitraryWaveform + c_int32(len(waveform)), # arbitraryWaveformSize + c_enum(0), # sweepType for deltaPhase + c_enum(0), # operation (adding random noise and whatnot) + c_enum(indexMode), # single, dual, quad c_uint32(shots), - c_uint32(0), # sweeps + c_uint32(0), # sweeps c_uint32(triggerType), c_uint32(triggerSource), - c_int16(0), - ) # extInThreshold + c_int16(0)) # extInThreshold self.checkResult(m) - def _lowLevelSetDataBuffer( - self, channel, data, downSampleMode, segmentIndex - ): + def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, + segmentIndex): """Set the data buffer. Be sure to call _lowLevelClearDataBuffer @@ -498,76 +409,49 @@ def _lowLevelSetDataBuffer( dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) - m = self.lib.ps5000aSetDataBuffer( - c_int16(self.handle), - c_enum(channel), - dataPtr, - c_int32(numSamples), - c_uint32(segmentIndex), - c_enum(downSampleMode), - ) + m = self.lib.ps5000aSetDataBuffer(c_int16(self.handle), + c_enum(channel), + dataPtr, c_int32(numSamples), + c_uint32(segmentIndex), + c_enum(downSampleMode)) self.checkResult(m) - def _lowLevelSetDataBufferBulk( - self, channel, data, segmentIndex, downSampleMode - ): + def _lowLevelSetDataBufferBulk(self, channel, data, segmentIndex, + downSampleMode): """Just calls setDataBuffer with argument order changed. For compatibility with current picobase.py. """ - self._lowLevelSetDataBuffer( - channel, data, downSampleMode, segmentIndex - ) + self._lowLevelSetDataBuffer(channel, + data, + downSampleMode, + segmentIndex) def _lowLevelClearDataBuffer(self, channel, segmentIndex): - m = self.lib.ps5000aSetDataBuffer( - c_int16(self.handle), - c_enum(channel), - c_void_p(), - c_uint32(0), - c_uint32(segmentIndex), - c_enum(0), - ) + m = self.lib.ps5000aSetDataBuffer(c_int16(self.handle), + c_enum(channel), + c_void_p(), c_uint32(0), + c_uint32(segmentIndex), + c_enum(0)) self.checkResult(m) - def _lowLevelGetValues( - self, - numSamples, - startIndex, - downSampleRatio, - downSampleMode, - segmentIndex, - ): + def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, + downSampleMode, segmentIndex): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps5000aGetValues( - c_int16(self.handle), - c_uint32(startIndex), - byref(numSamplesReturned), - c_uint32(downSampleRatio), - c_enum(downSampleMode), - c_uint32(segmentIndex), - byref(overflow), - ) + c_int16(self.handle), c_uint32(startIndex), + byref(numSamplesReturned), c_uint32(downSampleRatio), + c_enum(downSampleMode), c_uint32(segmentIndex), + byref(overflow)) self.checkResult(m) return (numSamplesReturned.value, overflow.value) - def _lowLevelSetSigGenBuiltInSimple( - self, - offsetVoltage, - pkToPk, - waveType, - frequency, - shots, - triggerType, - triggerSource, - stopFreq, - increment, - dwellTime, - sweepType, - numSweeps, - ): + def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, + frequency, shots, triggerType, + triggerSource, stopFreq, increment, + dwellTime, sweepType, numSweeps): # TODO, I just noticed that V2 exists # Maybe change to V2 in the future @@ -579,43 +463,30 @@ def _lowLevelSetSigGenBuiltInSimple( c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), - c_float(stopFreq), - c_float(increment), - c_float(dwellTime), - c_enum(sweepType), - c_enum(0), - c_uint32(shots), - c_uint32(numSweeps), - c_enum(triggerType), - c_enum(triggerSource), - c_int16(0), - ) + c_float(frequency), c_float(stopFreq), + c_float(increment), c_float(dwellTime), + c_enum(sweepType), c_enum(0), + c_uint32(shots), c_uint32(numSweeps), + c_enum(triggerType), c_enum(triggerSource), + c_int16(0)) self.checkResult(m) def _lowLevelSetDeviceResolution(self, resolution): self.resolution = resolution m = self.lib.ps5000aSetDeviceResolution( - c_int16(self.handle), c_enum(resolution) - ) + c_int16(self.handle), + c_enum(resolution)) self.checkResult(m) def _lowLevelChangePowerSource(self, powerstate): m = self.lib.ps5000aChangePowerSource( - c_int16(self.handle), c_enum(powerstate) - ) + c_int16(self.handle), + c_enum(powerstate)) self.checkResult(m) # Morgan's additions - def _lowLevelGetValuesBulk( - self, - numSamples, - fromSegment, - toSegment, - downSampleRatio, - downSampleMode, - overflow, - ): + def _lowLevelGetValuesBulk(self, numSamples, fromSegment, toSegment, + downSampleRatio, downSampleMode, overflow): """Copy data from several memory segments at once.""" overflowPoint = overflow.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps5000aGetValuesBulk( @@ -625,21 +496,20 @@ def _lowLevelGetValuesBulk( c_int32(toSegment), c_int32(downSampleRatio), c_enum(downSampleMode), - overflowPoint, - ) + overflowPoint + ) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, numCaptures): m = self.lib.ps5000aSetNoOfCaptures( - c_int16(self.handle), c_uint32(numCaptures) - ) + c_int16(self.handle), + c_uint32(numCaptures)) self.checkResult(m) def _lowLevelMemorySegments(self, numSegments): maxSamples = c_int32() m = self.lib.ps5000aMemorySegments( - c_int16(self.handle), c_uint32(numSegments), byref(maxSamples) - ) + c_int16(self.handle), c_uint32(numSegments), byref(maxSamples)) self.checkResult(m) return maxSamples.value @@ -653,16 +523,20 @@ def _lowLevelGetValuesTriggerTimeOffsetBulk(self, fromSegment, toSegment): nSegments = toSegment - fromSegment + 1 # time = c_int64() - times = np.ascontiguousarray(np.zeros(nSegments, dtype=np.int64)) - timeUnits = np.ascontiguousarray(np.zeros(nSegments, dtype=np.int32)) + times = np.ascontiguousarray( + np.zeros(nSegments, dtype=np.int64) + ) + timeUnits = np.ascontiguousarray( + np.zeros(nSegments, dtype=np.int32) + ) m = self.lib.ps5000aGetValuesTriggerTimeOffsetBulk64( c_int16(self.handle), times.ctypes.data_as(POINTER(c_int64)), timeUnits.ctypes.data_as(POINTER(c_enum)), c_uint32(fromSegment), - c_uint32(toSegment), - ) + c_uint32(toSegment) + ) self.checkResult(m) # timeUnits=np.array([self.TIME_UNITS[tu] for tu in timeUnits]) return times, timeUnits diff --git a/picoscope/ps6000.py b/picoscope/ps6000.py index 6cf279b..a0beaf3 100644 --- a/picoscope/ps6000.py +++ b/picoscope/ps6000.py @@ -58,18 +58,8 @@ # use the values specified in the h file # float is always defined as 32 bits # double is defined as 64 bits -from ctypes import ( - byref, - POINTER, - create_string_buffer, - c_float, - c_int8, - c_int16, - c_int32, - c_uint32, - c_uint64, - c_void_p, -) +from ctypes import byref, POINTER, create_string_buffer, c_float, \ + c_int8, c_int16, c_int32, c_uint32, c_uint64, c_void_p from ctypes import c_int32 as c_enum from picoscope.picobase import _PicoscopeBase @@ -90,62 +80,36 @@ class PS6000(_PicoscopeBase): # I don't think that the 50V range is allowed, but I left it there anyway # The 10V and 20V ranges are only allowed in high impedence modes - CHANNEL_RANGE = [ - {"rangeV": 20e-3, "apivalue": 1, "rangeStr": "20 mV"}, - {"rangeV": 50e-3, "apivalue": 2, "rangeStr": "50 mV"}, - {"rangeV": 100e-3, "apivalue": 3, "rangeStr": "100 mV"}, - {"rangeV": 200e-3, "apivalue": 4, "rangeStr": "200 mV"}, - {"rangeV": 500e-3, "apivalue": 5, "rangeStr": "500 mV"}, - {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, - {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, - {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, - {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, - {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, - {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, - ] + CHANNEL_RANGE = [{"rangeV": 20E-3, "apivalue": 1, "rangeStr": "20 mV"}, + {"rangeV": 50E-3, "apivalue": 2, "rangeStr": "50 mV"}, + {"rangeV": 100E-3, "apivalue": 3, "rangeStr": "100 mV"}, + {"rangeV": 200E-3, "apivalue": 4, "rangeStr": "200 mV"}, + {"rangeV": 500E-3, "apivalue": 5, "rangeStr": "500 mV"}, + {"rangeV": 1.0, "apivalue": 6, "rangeStr": "1 V"}, + {"rangeV": 2.0, "apivalue": 7, "rangeStr": "2 V"}, + {"rangeV": 5.0, "apivalue": 8, "rangeStr": "5 V"}, + {"rangeV": 10.0, "apivalue": 9, "rangeStr": "10 V"}, + {"rangeV": 20.0, "apivalue": 10, "rangeStr": "20 V"}, + {"rangeV": 50.0, "apivalue": 11, "rangeStr": "50 V"}, + ] NUM_CHANNELS = 4 - CHANNELS = { - "A": 0, - "B": 1, - "C": 2, - "D": 3, - "External": 4, - "MaxChannels": 4, - "TriggerAux": 5, - } + CHANNELS = {"A": 0, "B": 1, "C": 2, "D": 3, + "External": 4, "MaxChannels": 4, "TriggerAux": 5} CHANNEL_COUPLINGS = {"DC50": 2, "DC": 1, "AC": 0} - WAVE_TYPES = { - "Sine": 0, - "Square": 1, - "Triangle": 2, - "RampUp": 3, - "RampDown": 4, - "Sinc": 5, - "Gaussian": 6, - "HalfSine": 7, - "DCVoltage": 8, - "WhiteNoise": 9, - } + WAVE_TYPES = {"Sine": 0, "Square": 1, "Triangle": 2, + "RampUp": 3, "RampDown": 4, + "Sinc": 5, "Gaussian": 6, "HalfSine": 7, "DCVoltage": 8, + "WhiteNoise": 9} SWEEP_TYPES = {"Up": 0, "Down": 1, "UpDown": 2, "DownUp": 3} - SIGGEN_TRIGGER_TYPES = { - "Rising": 0, - "Falling": 1, - "GateHigh": 2, - "GateLow": 3, - } - SIGGEN_TRIGGER_SOURCES = { - "None": 0, - "ScopeTrig": 1, - "AuxIn": 2, - "ExtIn": 3, - "SoftTrig": 4, - "TriggerRaw": 5, - } + SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1, + "GateHigh": 2, "GateLow": 3} + SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1, "AuxIn": 2, + "ExtIn": 3, "SoftTrig": 4, "TriggerRaw": 5} # This is actually different depending on the AB/CD models # I wonder how we could detect the difference between the oscilloscopes @@ -159,7 +123,7 @@ class PS6000(_PicoscopeBase): AWGBufferAddressWidth = 14 AWGMaxSamples = 2 ** AWGBufferAddressWidth - AWGDACInterval = 5e-9 # in seconds + AWGDACInterval = 5E-9 # in seconds AWGDACFrequency = 1 / AWGDACInterval # Note this is NOT what is written in the Programming guide as of version @@ -173,23 +137,18 @@ class PS6000(_PicoscopeBase): def __init__(self, serialNumber=None, connect=True): """Load DLLs.""" - if platform.system() == "Linux": + if platform.system() == 'Linux': from ctypes import cdll - # ok I don't know what is wrong with my installer, # but I need to include .so.2 self.lib = cdll.LoadLibrary("lib" + self.LIBNAME + ".so.2") - elif platform.system() == "Darwin": + elif platform.system() == 'Darwin': from picoscope.darwin_utils import LoadLibraryDarwin - self.lib = LoadLibraryDarwin("lib" + self.LIBNAME + ".dylib") else: from ctypes import windll from ctypes.util import find_library - - self.lib = windll.LoadLibrary( - find_library(str(self.LIBNAME + ".dll")) - ) + self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) super(PS6000, self).__init__(serialNumber, connect) @@ -222,9 +181,9 @@ def _lowLevelOpenUnitProgress(self): progressPercent = c_int16() handle = c_int16() - m = self.lib.ps6000OpenUnitProgress( - byref(handle), byref(progressPercent), byref(complete) - ) + m = self.lib.ps6000OpenUnitProgress(byref(handle), + byref(progressPercent), + byref(complete)) self.checkResult(m) if complete.value != 0: @@ -242,9 +201,8 @@ def _lowLevelEnumerateUnits(self): count = c_int16(0) serials = c_int8(0) serialLth = c_int16(0) - m = self.lib.ps6000EnumerateUnits( - byref(count), byref(serials), byref(serialLth) - ) + m = self.lib.ps6000EnumerateUnits(byref(count), byref(serials), + byref(serialLth)) self.checkResult(m) # a serial number is rouhgly 8 characters # an extra character for the comma @@ -253,29 +211,22 @@ def _lowLevelEnumerateUnits(self): serialLth = c_int16(count.value * (8 + 2)) serials = create_string_buffer(serialLth.value + 1) - m = self.lib.ps6000EnumerateUnits( - byref(count), serials, byref(serialLth) - ) + m = self.lib.ps6000EnumerateUnits(byref(count), serials, + byref(serialLth)) self.checkResult(m) - serialList = str(serials.value.decode("utf-8")).split(",") + serialList = str(serials.value.decode('utf-8')).split(',') serialList = [x.strip() for x in serialList] return serialList - def _lowLevelSetChannel( - self, chNum, enabled, coupling, VRange, VOffset, BWLimited - ): - m = self.lib.ps6000SetChannel( - c_int16(self.handle), - c_enum(chNum), - c_int16(enabled), - c_enum(coupling), - c_enum(VRange), - c_float(VOffset), - c_enum(BWLimited), - ) # 2 for PS6404 + def _lowLevelSetChannel(self, chNum, enabled, coupling, VRange, VOffset, + BWLimited): + m = self.lib.ps6000SetChannel(c_int16(self.handle), c_enum(chNum), + c_int16(enabled), c_enum(coupling), + c_enum(VRange), c_float(VOffset), + c_enum(BWLimited)) # 2 for PS6404 self.checkResult(m) def _lowLevelStop(self): @@ -286,67 +237,41 @@ def _lowLevelGetUnitInfo(self, info): s = create_string_buffer(256) requiredSize = c_int16(0) - m = self.lib.ps6000GetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps6000GetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), byref(requiredSize), + c_enum(info)) self.checkResult(m) if requiredSize.value > len(s): s = create_string_buffer(requiredSize.value + 1) - m = self.lib.ps6000GetUnitInfo( - c_int16(self.handle), - byref(s), - c_int16(len(s)), - byref(requiredSize), - c_enum(info), - ) + m = self.lib.ps6000GetUnitInfo(c_int16(self.handle), byref(s), + c_int16(len(s)), + byref(requiredSize), c_enum(info)) self.checkResult(m) # should this bee ascii instead? # I think they are equivalent... - return s.value.decode("utf-8") + return s.value.decode('utf-8') def _lowLevelFlashLed(self, times): m = self.lib.ps6000FlashLed(c_int16(self.handle), c_int16(times)) self.checkResult(m) - def _lowLevelSetSimpleTrigger( - self, enabled, trigsrc, threshold_adc, direction, delay, timeout_ms - ): + def _lowLevelSetSimpleTrigger(self, enabled, trigsrc, threshold_adc, + direction, delay, timeout_ms): m = self.lib.ps6000SetSimpleTrigger( - c_int16(self.handle), - c_int16(enabled), - c_enum(trigsrc), - c_int16(threshold_adc), - c_enum(direction), - c_uint32(delay), - c_int16(timeout_ms), - ) + c_int16(self.handle), c_int16(enabled), + c_enum(trigsrc), c_int16(threshold_adc), + c_enum(direction), c_uint32(delay), c_int16(timeout_ms)) self.checkResult(m) - def _lowLevelRunBlock( - self, - numPreTrigSamples, - numPostTrigSamples, - timebase, - oversample, - segmentIndex, - ): + def _lowLevelRunBlock(self, numPreTrigSamples, numPostTrigSamples, + timebase, oversample, segmentIndex): timeIndisposedMs = c_int32() m = self.lib.ps6000RunBlock( - c_int16(self.handle), - c_uint32(numPreTrigSamples), - c_uint32(numPostTrigSamples), - c_uint32(timebase), - c_int16(oversample), - byref(timeIndisposedMs), - c_uint32(segmentIndex), - c_void_p(), - c_void_p(), - ) + c_int16(self.handle), c_uint32(numPreTrigSamples), + c_uint32(numPostTrigSamples), c_uint32(timebase), + c_int16(oversample), byref(timeIndisposedMs), + c_uint32(segmentIndex), c_void_p(), c_void_p()) self.checkResult(m) return timeIndisposedMs.value @@ -364,25 +289,20 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex): maxSamples = c_int32() sampleRate = c_float() - m = self.lib.ps6000GetTimebase2( - c_int16(self.handle), - c_uint32(tb), - c_uint32(noSamples), - byref(sampleRate), - c_int16(oversample), - byref(maxSamples), - c_uint32(segmentIndex), - ) + m = self.lib.ps6000GetTimebase2(c_int16(self.handle), c_uint32(tb), + c_uint32(noSamples), byref(sampleRate), + c_int16(oversample), byref(maxSamples), + c_uint32(segmentIndex)) self.checkResult(m) - return (sampleRate.value / 1.0e9, maxSamples.value) + return (sampleRate.value / 1.0E9, maxSamples.value) def getTimeBaseNum(self, sampleTimeS): """Return sample time in seconds to timebase as int for API calls.""" - maxSampleTime = ((2 ** 32 - 1) - 4) / 156250000 + maxSampleTime = (((2 ** 32 - 1) - 4) / 156250000) - if sampleTimeS < 6.4e-9: - timebase = math.floor(math.log(sampleTimeS * 5e9, 2)) + if sampleTimeS < 6.4E-9: + timebase = math.floor(math.log(sampleTimeS * 5E9, 2)) timebase = max(timebase, 0) else: # Otherwise in range 2^32-1 @@ -398,49 +318,39 @@ def getTimeBaseNum(self, sampleTimeS): def getTimestepFromTimebase(self, timebase): """Return timebase to sampletime as seconds.""" if timebase < 5: - dt = 2.0 ** timebase / 5e9 + dt = 2. ** timebase / 5E9 else: - dt = (timebase - 4.0) / 156250000.0 + dt = (timebase - 4.) / 156250000. return dt - def _lowLevelSetAWGSimpleDeltaPhase( - self, - waveform, - deltaPhase, - offsetVoltage, - pkToPk, - indexMode, - shots, - triggerType, - triggerSource, - ): + def _lowLevelSetAWGSimpleDeltaPhase(self, waveform, deltaPhase, + offsetVoltage, pkToPk, indexMode, + shots, triggerType, triggerSource): """Waveform should be an array of shorts.""" waveformPtr = waveform.ctypes.data_as(POINTER(c_int16)) m = self.lib.ps6000SetSigGenArbitrary( c_int16(self.handle), - c_uint32(int(offsetVoltage * 1e6)), # offset voltage in microvolts - c_uint32(int(pkToPk * 1e6)), # pkToPk in microvolts - c_uint32(int(deltaPhase)), # startDeltaPhase - c_uint32(int(deltaPhase)), # stopDeltaPhase - c_uint32(0), # deltaPhaseIncrement - c_uint32(0), # dwellCount - waveformPtr, # arbitraryWaveform - c_int32(len(waveform)), # arbitraryWaveformSize - c_enum(0), # sweepType for deltaPhase - c_enum(0), # operation (adding random noise and whatnot) - c_enum(indexMode), # single, dual, quad + c_uint32(int(offsetVoltage * 1E6)), # offset voltage in microvolts + c_uint32(int(pkToPk * 1E6)), # pkToPk in microvolts + c_uint32(int(deltaPhase)), # startDeltaPhase + c_uint32(int(deltaPhase)), # stopDeltaPhase + c_uint32(0), # deltaPhaseIncrement + c_uint32(0), # dwellCount + waveformPtr, # arbitraryWaveform + c_int32(len(waveform)), # arbitraryWaveformSize + c_enum(0), # sweepType for deltaPhase + c_enum(0), # operation (adding random noise and whatnot) + c_enum(indexMode), # single, dual, quad c_uint32(shots), - c_uint32(0), # sweeps + c_uint32(0), # sweeps c_uint32(triggerType), c_uint32(triggerSource), - c_int16(0), - ) # extInThreshold + c_int16(0)) # extInThreshold self.checkResult(m) - def _lowLevelSetDataBuffer( - self, channel, data, downSampleMode, segmentIndex - ): + def _lowLevelSetDataBuffer(self, channel, data, downSampleMode, + segmentIndex): """Set the data buffer. Be sure to call _lowLevelClearDataBuffer @@ -453,63 +363,33 @@ def _lowLevelSetDataBuffer( dataPtr = data.ctypes.data_as(POINTER(c_int16)) numSamples = len(data) - m = self.lib.ps6000SetDataBuffer( - c_int16(self.handle), - c_enum(channel), - dataPtr, - c_uint32(numSamples), - c_enum(downSampleMode), - ) + m = self.lib.ps6000SetDataBuffer(c_int16(self.handle), c_enum(channel), + dataPtr, c_uint32(numSamples), + c_enum(downSampleMode)) self.checkResult(m) def _lowLevelClearDataBuffer(self, channel, segmentIndex): - m = self.lib.ps6000SetDataBuffer( - c_int16(self.handle), - c_enum(channel), - c_void_p(), - c_uint32(0), - c_enum(0), - ) + m = self.lib.ps6000SetDataBuffer(c_int16(self.handle), c_enum(channel), + c_void_p(), c_uint32(0), c_enum(0)) self.checkResult(m) - def _lowLevelGetValues( - self, - numSamples, - startIndex, - downSampleRatio, - downSampleMode, - segmentIndex, - ): + def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio, + downSampleMode, segmentIndex): numSamplesReturned = c_uint32() numSamplesReturned.value = numSamples overflow = c_int16() m = self.lib.ps6000GetValues( - c_int16(self.handle), - c_uint32(startIndex), - byref(numSamplesReturned), - c_uint32(downSampleRatio), - c_enum(downSampleMode), - c_uint32(segmentIndex), - byref(overflow), - ) + c_int16(self.handle), c_uint32(startIndex), + byref(numSamplesReturned), c_uint32(downSampleRatio), + c_enum(downSampleMode), c_uint32(segmentIndex), + byref(overflow)) self.checkResult(m) return (numSamplesReturned.value, overflow.value) - def _lowLevelSetSigGenBuiltInSimple( - self, - offsetVoltage, - pkToPk, - waveType, - frequency, - shots, - triggerType, - triggerSource, - stopFreq, - increment, - dwellTime, - sweepType, - numSweeps, - ): + def _lowLevelSetSigGenBuiltInSimple(self, offsetVoltage, pkToPk, waveType, + frequency, shots, triggerType, + triggerSource, stopFreq, increment, + dwellTime, sweepType, numSweeps): # TODO, I just noticed that V2 exists # Maybe change to V2 in the future @@ -521,18 +401,12 @@ def _lowLevelSetSigGenBuiltInSimple( c_int32(int(offsetVoltage * 1000000)), c_int32(int(pkToPk * 1000000)), c_int16(waveType), - c_float(frequency), - c_float(stopFreq), - c_float(increment), - c_float(dwellTime), - c_enum(sweepType), - c_enum(0), - c_uint32(shots), - c_uint32(numSweeps), - c_enum(triggerType), - c_enum(triggerSource), - c_int16(0), - ) + c_float(frequency), c_float(stopFreq), + c_float(increment), c_float(dwellTime), + c_enum(sweepType), c_enum(0), + c_uint32(shots), c_uint32(numSweeps), + c_enum(triggerType), c_enum(triggerSource), + c_int16(0)) self.checkResult(m) #################################################################### @@ -545,28 +419,20 @@ def _lowLevelGetAnalogueOffset(self, range, coupling): minimumVoltage = c_float() m = self.lib.ps6000GetAnalogueOffset( - c_int16(self.handle), - c_enum(range), - c_enum(coupling), - byref(maximumVoltage), - byref(minimumVoltage), - ) + c_int16(self.handle), c_enum(range), c_enum(coupling), + byref(maximumVoltage), byref(minimumVoltage)) self.checkResult(m) return (maximumVoltage.value, minimumVoltage.value) - def _lowLevelGetMaxDownSampleRatio( - self, noOfUnaggregatedSamples, downSampleRatioMode, segmentIndex - ): + def _lowLevelGetMaxDownSampleRatio(self, noOfUnaggregatedSamples, + downSampleRatioMode, segmentIndex): maxDownSampleRatio = c_uint32() m = self.lib.ps6000GetMaxDownSampleRatio( - c_int16(self.handle), - c_uint32(noOfUnaggregatedSamples), + c_int16(self.handle), c_uint32(noOfUnaggregatedSamples), byref(maxDownSampleRatio), - c_enum(downSampleRatioMode), - c_uint32(segmentIndex), - ) + c_enum(downSampleRatioMode), c_uint32(segmentIndex)) self.checkResult(m) return maxDownSampleRatio.value @@ -574,9 +440,8 @@ def _lowLevelGetMaxDownSampleRatio( def _lowLevelGetNoOfCaptures(self): nCaptures = c_uint32() - m = self.lib.ps6000GetNoOfCaptures( - c_int16(self.handle), byref(nCaptures) - ) + m = self.lib.ps6000GetNoOfCaptures(c_int16(self.handle), + byref(nCaptures)) self.checkResult(m) return nCaptures.value @@ -586,132 +451,101 @@ def _lowLevelGetTriggerTimeOffset(self, segmentIndex): timeUnits = c_enum() m = self.lib.ps6000GetTriggerTimeOffset64( - c_int16(self.handle), - byref(time), - byref(timeUnits), - c_uint32(segmentIndex), - ) + c_int16(self.handle), byref(time), + byref(timeUnits), c_uint32(segmentIndex)) self.checkResult(m) - if timeUnits.value == 0: # PS6000_FS - return time.value * 1e-15 + if timeUnits.value == 0: # PS6000_FS + return time.value * 1E-15 elif timeUnits.value == 1: # PS6000_PS - return time.value * 1e-12 + return time.value * 1E-12 elif timeUnits.value == 2: # PS6000_NS - return time.value * 1e-9 + return time.value * 1E-9 elif timeUnits.value == 3: # PS6000_US - return time.value * 1e-6 + return time.value * 1E-6 elif timeUnits.value == 4: # PS6000_MS - return time.value * 1e-3 + return time.value * 1E-3 elif timeUnits.value == 5: # PS6000_S - return time.value * 1e0 + return time.value * 1E0 else: raise TypeError("Unknown timeUnits %d" % timeUnits.value) def _lowLevelMemorySegments(self, nSegments): nMaxSamples = c_uint32() - m = self.lib.ps6000MemorySegments( - c_int16(self.handle), c_uint32(nSegments), byref(nMaxSamples) - ) + m = self.lib.ps6000MemorySegments(c_int16(self.handle), + c_uint32(nSegments), + byref(nMaxSamples)) self.checkResult(m) return nMaxSamples.value - def _lowLevelSetDataBuffers( - self, channel, bufferMax, bufferMin, downSampleRatioMode - ): + def _lowLevelSetDataBuffers(self, channel, bufferMax, bufferMin, + downSampleRatioMode): bufferMaxPtr = bufferMax.ctypes.data_as(POINTER(c_int16)) bufferMinPtr = bufferMin.ctypes.data_as(POINTER(c_int16)) bufferLth = len(bufferMax) - m = self.lib.ps6000SetDataBuffers( - c_int16(self.handle), - c_enum(channel), - bufferMaxPtr, - bufferMinPtr, - c_uint32(bufferLth), - c_enum(downSampleRatioMode), - ) + m = self.lib.ps6000SetDataBuffers(c_int16(self.handle), + c_enum(channel), + bufferMaxPtr, bufferMinPtr, + c_uint32(bufferLth), + c_enum(downSampleRatioMode)) self.checkResult(m) def _lowLevelClearDataBuffers(self, channel): m = self.lib.ps6000SetDataBuffers( - c_int16(self.handle), - c_enum(channel), - c_void_p(), - c_void_p(), - c_uint32(0), - c_enum(0), - ) + c_int16(self.handle), c_enum(channel), + c_void_p(), c_void_p(), c_uint32(0), c_enum(0)) self.checkResult(m) # Bulk values. # These would be nice, but the user would have to provide us # with an array. # we would have to make sure that it is contiguous amonts other things - def _lowLevelGetValuesBulk( - self, - numSamples, - fromSegmentIndex, - toSegmentIndex, - downSampleRatio, - downSampleRatioMode, - overflow, - ): + def _lowLevelGetValuesBulk(self, + numSamples, fromSegmentIndex, toSegmentIndex, + downSampleRatio, downSampleRatioMode, + overflow): noOfSamples = c_uint32(numSamples) m = self.lib.ps6000GetValuesBulk( c_int16(self.handle), byref(noOfSamples), - c_uint32(fromSegmentIndex), - c_uint32(toSegmentIndex), - c_uint32(downSampleRatio), - c_enum(downSampleRatioMode), - overflow.ctypes.data_as(POINTER(c_int16)), - ) + c_uint32(fromSegmentIndex), c_uint32(toSegmentIndex), + c_uint32(downSampleRatio), c_enum(downSampleRatioMode), + overflow.ctypes.data_as(POINTER(c_int16)) + ) self.checkResult(m) return noOfSamples.value - def _lowLevelSetDataBufferBulk( - self, channel, buffer, waveform, downSampleRatioMode - ): + def _lowLevelSetDataBufferBulk(self, channel, buffer, waveform, + downSampleRatioMode): bufferPtr = buffer.ctypes.data_as(POINTER(c_int16)) bufferLth = len(buffer) m = self.lib.ps6000SetDataBufferBulk( c_int16(self.handle), - c_enum(channel), - bufferPtr, - c_uint32(bufferLth), - c_uint32(waveform), - c_enum(downSampleRatioMode), - ) + c_enum(channel), bufferPtr, c_uint32(bufferLth), + c_uint32(waveform), c_enum(downSampleRatioMode)) self.checkResult(m) - def _lowLevelSetDataBuffersBulk( - self, channel, bufferMax, bufferMin, waveform, downSampleRatioMode - ): + def _lowLevelSetDataBuffersBulk(self, channel, bufferMax, bufferMin, + waveform, downSampleRatioMode): bufferMaxPtr = bufferMax.ctypes.data_as(POINTER(c_int16)) bufferMinPtr = bufferMin.ctypes.data_as(POINTER(c_int16)) bufferLth = len(bufferMax) m = self.lib.ps6000SetDataBuffersBulk( - c_int16(self.handle), - c_enum(channel), - bufferMaxPtr, - bufferMinPtr, - c_uint32(bufferLth), - c_uint32(waveform), - c_enum(downSampleRatioMode), - ) + c_int16(self.handle), c_enum(channel), + bufferMaxPtr, bufferMinPtr, c_uint32(bufferLth), + c_uint32(waveform), c_enum(downSampleRatioMode)) self.checkResult(m) def _lowLevelSetNoOfCaptures(self, nCaptures): - m = self.lib.ps6000SetNoOfCaptures( - c_int16(self.handle), c_uint32(nCaptures) - ) + m = self.lib.ps6000SetNoOfCaptures(c_int16(self.handle), + c_uint32(nCaptures)) self.checkResult(m) # ETS Functions @@ -772,9 +606,8 @@ def _lowLevelGetStreamingLatestValues(): def _lowLevelNoOfStreamingValues(self): noOfValues = c_uint32() - m = self.lib.ps6000NoOfStreamingValues( - c_int16(self.handle), byref(noOfValues) - ) + m = self.lib.ps6000NoOfStreamingValues(c_int16(self.handle), + byref(noOfValues)) self.checkResult(m) return noOfValues.value From 7451ee3100b961cd0a8ae0383406f198e17c855c Mon Sep 17 00:00:00 2001 From: Jonah Shapiro Date: Fri, 9 Oct 2020 12:25:38 -0700 Subject: [PATCH 4/5] Fix PEP8 issues without autoformatting --- picoscope/ps2000.py | 4 +++- picoscope/ps2000a.py | 4 +++- picoscope/ps3000.py | 4 +++- picoscope/ps3000a.py | 4 +++- picoscope/ps4000.py | 4 +++- picoscope/ps4000a.py | 4 +++- picoscope/ps5000.py | 4 +++- picoscope/ps5000a.py | 4 +++- picoscope/ps6000.py | 6 ++++-- 9 files changed, 28 insertions(+), 10 deletions(-) diff --git a/picoscope/ps2000.py b/picoscope/ps2000.py index f75f1b2..372ce95 100644 --- a/picoscope/ps2000.py +++ b/picoscope/ps2000.py @@ -143,7 +143,9 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) super(PS2000, self).__init__(serialNumber, connect) diff --git a/picoscope/ps2000a.py b/picoscope/ps2000a.py index ce34727..4e37609 100644 --- a/picoscope/ps2000a.py +++ b/picoscope/ps2000a.py @@ -135,7 +135,9 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) self.resolution = self.ADC_RESOLUTIONS["8"] diff --git a/picoscope/ps3000.py b/picoscope/ps3000.py index 40cc054..859eb94 100644 --- a/picoscope/ps3000.py +++ b/picoscope/ps3000.py @@ -130,7 +130,9 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) super(PS3000, self).__init__(serialNumber, connect) diff --git a/picoscope/ps3000a.py b/picoscope/ps3000a.py index 31bb888..d7cca64 100644 --- a/picoscope/ps3000a.py +++ b/picoscope/ps3000a.py @@ -143,7 +143,9 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) self.resolution = self.ADC_RESOLUTIONS["8"] diff --git a/picoscope/ps4000.py b/picoscope/ps4000.py index 27cd9de..fdff18a 100644 --- a/picoscope/ps4000.py +++ b/picoscope/ps4000.py @@ -140,7 +140,9 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) super(PS4000, self).__init__(serialNumber, connect) # check to see which model we have and use special functions if needed diff --git a/picoscope/ps4000a.py b/picoscope/ps4000a.py index 56a7e86..6dae8f9 100644 --- a/picoscope/ps4000a.py +++ b/picoscope/ps4000a.py @@ -132,7 +132,9 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) self.resolution = self.ADC_RESOLUTIONS["12"] diff --git a/picoscope/ps5000.py b/picoscope/ps5000.py index fdce198..5462f22 100644 --- a/picoscope/ps5000.py +++ b/picoscope/ps5000.py @@ -147,7 +147,9 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) super(PS5000, self).__init__(serialNumber, connect) diff --git a/picoscope/ps5000a.py b/picoscope/ps5000a.py index 2417378..65250a1 100644 --- a/picoscope/ps5000a.py +++ b/picoscope/ps5000a.py @@ -135,7 +135,9 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) self.resolution = self.ADC_RESOLUTIONS["8"] diff --git a/picoscope/ps6000.py b/picoscope/ps6000.py index a0beaf3..942f5b7 100644 --- a/picoscope/ps6000.py +++ b/picoscope/ps6000.py @@ -148,8 +148,10 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary(find_library(str(self.LIBNAME + ".dll"))) - + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) + ) + super(PS6000, self).__init__(serialNumber, connect) def _lowLevelOpenUnit(self, sn): From 3bd6701ba86d0c585305ee47c0747f008e013f64 Mon Sep 17 00:00:00 2001 From: Jonah Shapiro Date: Fri, 9 Oct 2020 12:29:58 -0700 Subject: [PATCH 5/5] Fix whitespace --- picoscope/ps2000.py | 2 +- picoscope/ps2000a.py | 2 +- picoscope/ps3000.py | 2 +- picoscope/ps3000a.py | 2 +- picoscope/ps4000.py | 2 +- picoscope/ps4000a.py | 2 +- picoscope/ps5000.py | 2 +- picoscope/ps5000a.py | 2 +- picoscope/ps6000.py | 6 +++--- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/picoscope/ps2000.py b/picoscope/ps2000.py index 372ce95..402d794 100644 --- a/picoscope/ps2000.py +++ b/picoscope/ps2000.py @@ -143,7 +143,7 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary( + self.lib = windll.LoadLibrary( find_library(str(self.LIBNAME + ".dll")) ) diff --git a/picoscope/ps2000a.py b/picoscope/ps2000a.py index 4e37609..b823c2a 100644 --- a/picoscope/ps2000a.py +++ b/picoscope/ps2000a.py @@ -135,7 +135,7 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary( + self.lib = windll.LoadLibrary( find_library(str(self.LIBNAME + ".dll")) ) diff --git a/picoscope/ps3000.py b/picoscope/ps3000.py index 859eb94..af7c50c 100644 --- a/picoscope/ps3000.py +++ b/picoscope/ps3000.py @@ -130,7 +130,7 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary( + self.lib = windll.LoadLibrary( find_library(str(self.LIBNAME + ".dll")) ) diff --git a/picoscope/ps3000a.py b/picoscope/ps3000a.py index d7cca64..e24a172 100644 --- a/picoscope/ps3000a.py +++ b/picoscope/ps3000a.py @@ -143,7 +143,7 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary( + self.lib = windll.LoadLibrary( find_library(str(self.LIBNAME + ".dll")) ) diff --git a/picoscope/ps4000.py b/picoscope/ps4000.py index fdff18a..3683d8e 100644 --- a/picoscope/ps4000.py +++ b/picoscope/ps4000.py @@ -140,7 +140,7 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary( + self.lib = windll.LoadLibrary( find_library(str(self.LIBNAME + ".dll")) ) diff --git a/picoscope/ps4000a.py b/picoscope/ps4000a.py index 6dae8f9..57d4507 100644 --- a/picoscope/ps4000a.py +++ b/picoscope/ps4000a.py @@ -132,7 +132,7 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary( + self.lib = windll.LoadLibrary( find_library(str(self.LIBNAME + ".dll")) ) diff --git a/picoscope/ps5000.py b/picoscope/ps5000.py index 5462f22..f443fd1 100644 --- a/picoscope/ps5000.py +++ b/picoscope/ps5000.py @@ -147,7 +147,7 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary( + self.lib = windll.LoadLibrary( find_library(str(self.LIBNAME + ".dll")) ) diff --git a/picoscope/ps5000a.py b/picoscope/ps5000a.py index 65250a1..b84c05f 100644 --- a/picoscope/ps5000a.py +++ b/picoscope/ps5000a.py @@ -135,7 +135,7 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary( + self.lib = windll.LoadLibrary( find_library(str(self.LIBNAME + ".dll")) ) diff --git a/picoscope/ps6000.py b/picoscope/ps6000.py index 942f5b7..f7d1cbe 100644 --- a/picoscope/ps6000.py +++ b/picoscope/ps6000.py @@ -148,10 +148,10 @@ def __init__(self, serialNumber=None, connect=True): else: from ctypes import windll from ctypes.util import find_library - self.lib = windll.LoadLibrary( - find_library(str(self.LIBNAME + ".dll")) + self.lib = windll.LoadLibrary( + find_library(str(self.LIBNAME + ".dll")) ) - + super(PS6000, self).__init__(serialNumber, connect) def _lowLevelOpenUnit(self, sn):