6262 c_int16 , c_uint16 , c_int32 , c_uint32 , c_uint64 , c_void_p , c_int8
6363from ctypes import c_int32 as c_enum
6464
65+ import warnings
66+
6567from picoscope .picobase import _PicoscopeBase
6668
6769
@@ -73,7 +75,7 @@ class PS4000a(_PicoscopeBase):
7375 MAX_VALUE = 32764
7476 MIN_VALUE = - 32764
7577
76- # EXT/AUX seems to have an imput impedence of 50 ohm (PS6403B)
78+ # EXT/AUX seems to have an input impedance of 50 ohm (PS6403B)
7779 EXT_MAX_VALUE = 32767
7880 EXT_MIN_VALUE = - 32767
7981 EXT_RANGE_VOLTS = 1
@@ -97,6 +99,8 @@ class PS4000a(_PicoscopeBase):
9799 CHANNELS = {"A" : 0 , "B" : 1 , "C" : 2 , "D" : 3 , "E" : 4 , "F" : 5 , "G" : 6 ,
98100 "H" : 7 , "MaxChannels" : 8 }
99101
102+ ADC_RESOLUTIONS = {"8" : 0 , "12" : 1 , "14" : 2 , "15" : 3 , "16" : 4 }
103+
100104 CHANNEL_COUPLINGS = {"DC50" : 2 , "DC" : 1 , "AC" : 0 }
101105
102106 WAVE_TYPES = {"Sine" : 0 , "Square" : 1 , "Triangle" : 2 ,
@@ -129,6 +133,8 @@ def __init__(self, serialNumber=None, connect=True):
129133 from ctypes import windll
130134 self .lib = windll .LoadLibrary (str (self .LIBNAME + ".dll" ))
131135
136+ self .resolution = self .ADC_RESOLUTIONS ["12" ]
137+
132138 super (PS4000a , self ).__init__ (serialNumber , connect )
133139
134140 def _lowLevelOpenUnit (self , sn ):
@@ -142,6 +148,8 @@ def _lowLevelOpenUnit(self, sn):
142148 self .checkResult (m )
143149 self .handle = c_handle .value
144150
151+ self .model = self .getUnitInfo ('VariantInfo' )
152+
145153 def _lowLevelOpenUnitAsync (self , sn ):
146154 c_status = c_int16 ()
147155 if sn is not None :
@@ -277,29 +285,77 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex):
277285 return (sampleRate .value / 1.0E9 , maxSamples .value )
278286
279287 def getTimeBaseNum (self , sampleTimeS ):
280- """Return sample time in seconds to timebase as int for API calls."""
281- maxSampleTime = (((2 ** 32 - 1 ) - 4 ) / 2e7 )
282-
283- if sampleTimeS <= 12.5E-9 :
284- timebase = math .floor (math .log (sampleTimeS * 8E7 , 2 ))
285- timebase = max (timebase , 0 )
286- else :
287- # Otherwise in range 2^32-1
288- if sampleTimeS > maxSampleTime :
289- sampleTimeS = maxSampleTime
288+ """ Convert the sample interval (float of seconds) to the
289+ corresponding integer timebase value as defined by the API.
290+ See "Timebases" section of the PS4000a programmers guide
291+ for more information.
292+ """
290293
291- timebase = math .floor ((sampleTimeS * 2e7 ) + 1 )
294+ if self .model == '4828' :
295+ maxSampleTime = (((2 ** 32 - 1 ) + 1 ) / 8E7 )
296+
297+ if sampleTimeS <= 12.5E-9 :
298+ timebase = 0
299+ else :
300+ # Otherwise in range 2^32-1
301+ if sampleTimeS > maxSampleTime :
302+ sampleTimeS = maxSampleTime
303+
304+ timebase = math .floor ((sampleTimeS * 2e7 ) + 1 )
305+
306+ elif self .model == '4444' :
307+ maxSampleTime = (((2 ** 32 - 1 ) - 2 ) / 5.0E7 )
308+
309+ if (sampleTimeS <= 2.5E-9 and
310+ self .resolution == self .ADC_RESOLUTIONS ["12" ]):
311+ timebase = 0
312+ elif (sampleTimeS <= 20E-9 and
313+ self .resolution == self .ADC_RESOLUTIONS ["14" ]):
314+ timebase = 3
315+ else :
316+ # Otherwise in range 2^32-1
317+ if sampleTimeS > maxSampleTime :
318+ sampleTimeS = maxSampleTime
319+
320+ timebase = math .floor ((sampleTimeS * 5.0E7 ) + 2 )
321+
322+ else : # The original case from non "A" series
323+ warnings .warn ("The model PS4000a you are using may not be "
324+ "fully supported" , stacklevel = 2 )
325+ maxSampleTime = (((2 ** 32 - 1 ) - 4 ) / 2e7 )
326+
327+ if sampleTimeS <= 12.5E-9 :
328+ timebase = math .floor (math .log (sampleTimeS * 8E7 , 2 ))
329+ timebase = max (timebase , 0 )
330+ else :
331+ # Otherwise in range 2^32-1
332+ if sampleTimeS > maxSampleTime :
333+ sampleTimeS = maxSampleTime
334+
335+ timebase = math .floor ((sampleTimeS * 2e7 ) + 1 )
292336
293337 # is this cast needed?
294338 timebase = int (timebase )
295339 return timebase
296340
297341 def getTimestepFromTimebase (self , timebase ):
298342 """Return timebase to sampletime as seconds."""
299- if timebase < 3 :
300- dt = 2. ** timebase / 8e7
301- else :
302- dt = (timebase - 1 ) / 2e7
343+ if self .model == '4828' :
344+ dt = (timebase + 1 ) / 8.0E7
345+ elif self .model == '4444' :
346+ if timebase < 3 :
347+ dt = 2.5 ** timebase / 4.0E8
348+ else :
349+ dt = (timebase - 2 ) / 5.0E7
350+
351+ else : # The original case from non "A" series
352+ warnings .warn ("The model PS4000a you are using may not be "
353+ "fully supported" , stacklevel = 2 )
354+ if timebase < 3 :
355+ dt = 2. ** timebase / 8e7
356+ else :
357+ dt = (timebase - 1 ) / 2e7
358+ return dt
303359 return dt
304360
305361 def _lowLevelSetDataBuffer (self , channel , data , downSampleMode ,
@@ -313,11 +369,12 @@ def _lowLevelSetDataBuffer(self, channel, data, downSampleMode,
313369 segmentIndex is unused, but required by other versions of the API
314370 (eg PS5000a)
315371 """
372+ dataPtr = data .ctypes .data_as (POINTER (c_int16 ))
316373 numSamples = len (data )
317374
318375 m = self .lib .ps4000aSetDataBuffer (c_int16 (self .handle ),
319376 c_enum (channel ),
320- byref ( data ) , c_uint32 (numSamples ),
377+ dataPtr , c_uint32 (numSamples ),
321378 c_uint32 (segmentIndex ),
322379 c_uint32 (downSampleMode ))
323380 self .checkResult (m )
@@ -342,6 +399,37 @@ def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio,
342399 self .checkResult (m )
343400 return (numSamplesReturned .value , overflow .value )
344401
402+ def _lowLevelSetDeviceResolution (self , resolution ):
403+ self .resolution = resolution
404+ m = self .lib .ps4000aSetDeviceResolution (
405+ c_int16 (self .handle ),
406+ c_enum (resolution ))
407+ self .checkResult (m )
408+
409+ def _lowLevelGetValuesBulk (self , numSamples , fromSegment , toSegment ,
410+ downSampleRatio , downSampleMode , overflow ):
411+ """Copy data from several memory segments at once."""
412+ overflowPoint = overflow .ctypes .data_as (POINTER (c_int16 ))
413+ m = self .lib .ps4000aGetValuesBulk (
414+ c_int16 (self .handle ),
415+ byref (c_int32 (numSamples )),
416+ c_int32 (fromSegment ),
417+ c_int32 (toSegment ),
418+ c_int32 (downSampleRatio ),
419+ c_enum (downSampleMode ),
420+ overflowPoint
421+ )
422+ self .checkResult (m )
423+
424+ def _lowLevelSetDataBufferBulk (self , channel , data , segmentIndex ,
425+ downSampleMode ):
426+ """Just calls setDataBuffer with argument order changed.
427+
428+ For compatibility with current picobase.py.
429+ """
430+ self ._lowLevelSetDataBuffer (channel , data , downSampleMode ,
431+ segmentIndex )
432+
345433 ####################################################################
346434 # Untested functions below #
347435 # #
@@ -449,95 +537,61 @@ def _lowLevelClearDataBuffers(self, channel):
449537 c_uint32 (0 ))
450538 self .checkResult (m )
451539
452- # Bulk values.
453- # These would be nice, but the user would have to provide us
454- # with an array.
455- # we would have to make sure that it is contiguous amonts other things
456- def _lowLevelGetValuesBulk (self ,
457- numSamples ,
458- fromSegmentIndex ,
459- toSegmentIndex ,
460- downSampleRatio ,
461- downSampleMode ,
462- overflow ):
463- noOfSamples = c_uint32 (numSamples )
464-
465- m = self .lib .ps4000aGetValuesBulk (
466- c_int16 (self .handle ),
467- byref (noOfSamples ),
468- c_uint16 (fromSegmentIndex ), c_uint16 (toSegmentIndex ),
469- overflow .ctypes .data_as (POINTER (c_int16 )))
470- self .checkResult (m )
471- return noOfSamples .value
472-
473- def _lowLevelSetDataBufferBulk (self , channel , buffer , waveform ,
474- downSampleRatioMode ):
475- bufferPtr = buffer .ctypes .data_as (POINTER (c_int16 ))
476- bufferLth = len (buffer )
477-
478- m = self .lib .ps4000aSetDataBufferBulk (
479- c_int16 (self .handle ),
480- c_enum (channel ),
481- bufferPtr ,
482- c_uint32 (bufferLth ),
483- c_uint16 (waveform ))
484- self .checkResult (m )
485-
486540 def _lowLevelSetNoOfCaptures (self , nCaptures ):
487541 m = self .lib .ps4000aSetNoOfCaptures (
488542 c_int16 (self .handle ),
489543 c_uint16 (nCaptures ))
490544 self .checkResult (m )
491545
492546 # ETS Functions
493- def _lowLevelSetEts ():
547+ def _lowLevelSetEts (self ):
494548 pass
495549
496- def _lowLevelSetEtsTimeBuffer ():
550+ def _lowLevelSetEtsTimeBuffer (self ):
497551 pass
498552
499- def _lowLevelSetEtsTimeBuffers ():
553+ def _lowLevelSetEtsTimeBuffers (self ):
500554 pass
501555
502- def _lowLevelSetExternalClock ():
556+ def _lowLevelSetExternalClock (self ):
503557 pass
504558
505559 # Complicated triggering
506560 # need to understand structs for this one to work
507- def _lowLevelIsTriggerOrPulseWidthQualifierEnabled ():
561+ def _lowLevelIsTriggerOrPulseWidthQualifierEnabled (self ):
508562 pass
509563
510- def _lowLevelGetValuesTriggerTimeOffsetBulk ():
564+ def _lowLevelGetValuesTriggerTimeOffsetBulk (self ):
511565 pass
512566
513- def _lowLevelSetTriggerChannelConditions ():
567+ def _lowLevelSetTriggerChannelConditions (self ):
514568 pass
515569
516- def _lowLevelSetTriggerChannelDirections ():
570+ def _lowLevelSetTriggerChannelDirections (self ):
517571 pass
518572
519- def _lowLevelSetTriggerChannelProperties ():
573+ def _lowLevelSetTriggerChannelProperties (self ):
520574 pass
521575
522- def _lowLevelSetPulseWidthQualifier ():
576+ def _lowLevelSetPulseWidthQualifier (self ):
523577 pass
524578
525- def _lowLevelSetTriggerDelay ():
579+ def _lowLevelSetTriggerDelay (self ):
526580 pass
527581
528582 # Async functions
529583 # would be nice, but we would have to learn to implement callbacks
530- def _lowLevelGetValuesAsync ():
584+ def _lowLevelGetValuesAsync (self ):
531585 pass
532586
533- def _lowLevelGetValuesBulkAsync ():
587+ def _lowLevelGetValuesBulkAsync (self ):
534588 pass
535589
536590 # overlapped functions
537- def _lowLevelGetValuesOverlapped ():
591+ def _lowLevelGetValuesOverlapped (self ):
538592 pass
539593
540- def _lowLevelGetValuesOverlappedBulk ():
594+ def _lowLevelGetValuesOverlappedBulk (self ):
541595 pass
542596
543597 # Streaming related functions
@@ -575,5 +629,5 @@ def _lowLevelRunStreaming(self, sampleInterval, sampleIntervalTimeUnits,
575629
576630 self .checkResult (m )
577631
578- def _lowLevelStreamingReady ():
632+ def _lowLevelStreamingReady (self ):
579633 pass
0 commit comments