62
62
c_int16 , c_uint16 , c_int32 , c_uint32 , c_uint64 , c_void_p , c_int8
63
63
from ctypes import c_int32 as c_enum
64
64
65
+ import warnings
66
+
65
67
from picoscope .picobase import _PicoscopeBase
66
68
67
69
@@ -73,7 +75,7 @@ class PS4000a(_PicoscopeBase):
73
75
MAX_VALUE = 32764
74
76
MIN_VALUE = - 32764
75
77
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)
77
79
EXT_MAX_VALUE = 32767
78
80
EXT_MIN_VALUE = - 32767
79
81
EXT_RANGE_VOLTS = 1
@@ -97,6 +99,8 @@ class PS4000a(_PicoscopeBase):
97
99
CHANNELS = {"A" : 0 , "B" : 1 , "C" : 2 , "D" : 3 , "E" : 4 , "F" : 5 , "G" : 6 ,
98
100
"H" : 7 , "MaxChannels" : 8 }
99
101
102
+ ADC_RESOLUTIONS = {"8" : 0 , "12" : 1 , "14" : 2 , "15" : 3 , "16" : 4 }
103
+
100
104
CHANNEL_COUPLINGS = {"DC50" : 2 , "DC" : 1 , "AC" : 0 }
101
105
102
106
WAVE_TYPES = {"Sine" : 0 , "Square" : 1 , "Triangle" : 2 ,
@@ -129,6 +133,8 @@ def __init__(self, serialNumber=None, connect=True):
129
133
from ctypes import windll
130
134
self .lib = windll .LoadLibrary (str (self .LIBNAME + ".dll" ))
131
135
136
+ self .resolution = self .ADC_RESOLUTIONS ["12" ]
137
+
132
138
super (PS4000a , self ).__init__ (serialNumber , connect )
133
139
134
140
def _lowLevelOpenUnit (self , sn ):
@@ -142,6 +148,8 @@ def _lowLevelOpenUnit(self, sn):
142
148
self .checkResult (m )
143
149
self .handle = c_handle .value
144
150
151
+ self .model = self .getUnitInfo ('VariantInfo' )
152
+
145
153
def _lowLevelOpenUnitAsync (self , sn ):
146
154
c_status = c_int16 ()
147
155
if sn is not None :
@@ -277,29 +285,77 @@ def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex):
277
285
return (sampleRate .value / 1.0E9 , maxSamples .value )
278
286
279
287
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
+ """
290
293
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 )
292
336
293
337
# is this cast needed?
294
338
timebase = int (timebase )
295
339
return timebase
296
340
297
341
def getTimestepFromTimebase (self , timebase ):
298
342
"""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
303
359
return dt
304
360
305
361
def _lowLevelSetDataBuffer (self , channel , data , downSampleMode ,
@@ -313,11 +369,12 @@ def _lowLevelSetDataBuffer(self, channel, data, downSampleMode,
313
369
segmentIndex is unused, but required by other versions of the API
314
370
(eg PS5000a)
315
371
"""
372
+ dataPtr = data .ctypes .data_as (POINTER (c_int16 ))
316
373
numSamples = len (data )
317
374
318
375
m = self .lib .ps4000aSetDataBuffer (c_int16 (self .handle ),
319
376
c_enum (channel ),
320
- byref ( data ) , c_uint32 (numSamples ),
377
+ dataPtr , c_uint32 (numSamples ),
321
378
c_uint32 (segmentIndex ),
322
379
c_uint32 (downSampleMode ))
323
380
self .checkResult (m )
@@ -342,6 +399,37 @@ def _lowLevelGetValues(self, numSamples, startIndex, downSampleRatio,
342
399
self .checkResult (m )
343
400
return (numSamplesReturned .value , overflow .value )
344
401
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
+
345
433
####################################################################
346
434
# Untested functions below #
347
435
# #
@@ -449,95 +537,61 @@ def _lowLevelClearDataBuffers(self, channel):
449
537
c_uint32 (0 ))
450
538
self .checkResult (m )
451
539
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
-
486
540
def _lowLevelSetNoOfCaptures (self , nCaptures ):
487
541
m = self .lib .ps4000aSetNoOfCaptures (
488
542
c_int16 (self .handle ),
489
543
c_uint16 (nCaptures ))
490
544
self .checkResult (m )
491
545
492
546
# ETS Functions
493
- def _lowLevelSetEts ():
547
+ def _lowLevelSetEts (self ):
494
548
pass
495
549
496
- def _lowLevelSetEtsTimeBuffer ():
550
+ def _lowLevelSetEtsTimeBuffer (self ):
497
551
pass
498
552
499
- def _lowLevelSetEtsTimeBuffers ():
553
+ def _lowLevelSetEtsTimeBuffers (self ):
500
554
pass
501
555
502
- def _lowLevelSetExternalClock ():
556
+ def _lowLevelSetExternalClock (self ):
503
557
pass
504
558
505
559
# Complicated triggering
506
560
# need to understand structs for this one to work
507
- def _lowLevelIsTriggerOrPulseWidthQualifierEnabled ():
561
+ def _lowLevelIsTriggerOrPulseWidthQualifierEnabled (self ):
508
562
pass
509
563
510
- def _lowLevelGetValuesTriggerTimeOffsetBulk ():
564
+ def _lowLevelGetValuesTriggerTimeOffsetBulk (self ):
511
565
pass
512
566
513
- def _lowLevelSetTriggerChannelConditions ():
567
+ def _lowLevelSetTriggerChannelConditions (self ):
514
568
pass
515
569
516
- def _lowLevelSetTriggerChannelDirections ():
570
+ def _lowLevelSetTriggerChannelDirections (self ):
517
571
pass
518
572
519
- def _lowLevelSetTriggerChannelProperties ():
573
+ def _lowLevelSetTriggerChannelProperties (self ):
520
574
pass
521
575
522
- def _lowLevelSetPulseWidthQualifier ():
576
+ def _lowLevelSetPulseWidthQualifier (self ):
523
577
pass
524
578
525
- def _lowLevelSetTriggerDelay ():
579
+ def _lowLevelSetTriggerDelay (self ):
526
580
pass
527
581
528
582
# Async functions
529
583
# would be nice, but we would have to learn to implement callbacks
530
- def _lowLevelGetValuesAsync ():
584
+ def _lowLevelGetValuesAsync (self ):
531
585
pass
532
586
533
- def _lowLevelGetValuesBulkAsync ():
587
+ def _lowLevelGetValuesBulkAsync (self ):
534
588
pass
535
589
536
590
# overlapped functions
537
- def _lowLevelGetValuesOverlapped ():
591
+ def _lowLevelGetValuesOverlapped (self ):
538
592
pass
539
593
540
- def _lowLevelGetValuesOverlappedBulk ():
594
+ def _lowLevelGetValuesOverlappedBulk (self ):
541
595
pass
542
596
543
597
# Streaming related functions
@@ -575,5 +629,5 @@ def _lowLevelRunStreaming(self, sampleInterval, sampleIntervalTimeUnits,
575
629
576
630
self .checkResult (m )
577
631
578
- def _lowLevelStreamingReady ():
632
+ def _lowLevelStreamingReady (self ):
579
633
pass
0 commit comments