1+ #
2+ # Copyright (C) 2024 Pico Technology Ltd. See LICENSE file for terms.
3+ #
4+ # PSOSPA RAPID BLOCK MODE EXAMPLE
5+ # This example opens a psospa driver device, sets up two channels and a trigger then collects 10 blocks of data in rapid block mode.
6+ # This data is then plotted as mV against time in ns.
7+
8+ import ctypes
9+ import numpy as np
10+ from picosdk .psospa import psospa as ps
11+ from picosdk .PicoDeviceEnums import picoEnum as enums
12+ from picosdk .PicoDeviceStructs import picoStruct as structs
13+ # from picosdk.PicoConnectProbes import picoConnectProbes as probes
14+ import matplotlib .pyplot as plt
15+ from picosdk .functions import adc2mVV2 , assert_pico_ok , mV2adcV2
16+
17+ # Create chandle and status ready for use
18+ chandle = ctypes .c_int16 ()
19+ status = {}
20+
21+ # Open a psospa driver device
22+ # returns handle for future API functions
23+ resolution = enums .PICO_DEVICE_RESOLUTION ["PICO_DR_8BIT" ]
24+ status ["openUnit" ] = ps .psospaOpenUnit (ctypes .byref (chandle ), None , resolution , None )
25+ assert_pico_ok (status ["openUnit" ])
26+
27+ # Set channel A on
28+ # handle = chandle
29+ channelA = enums .PICO_CHANNEL ["PICO_CHANNEL_A" ]
30+ coupling = enums .PICO_COUPLING ["PICO_DC" ]
31+ rangeMax = 2000000000 #nV
32+ rangeMin = - rangeMax #nV
33+ rangeType = 0 #probes.PICO_PROBE_RANGE_INFO["PICO_PROBE_NONE_NV"]
34+ analogueOffset = 0
35+ bandwidth = enums .PICO_BANDWIDTH_LIMITER ["PICO_BW_FULL" ]
36+ status ["setChannelA" ] = ps .psospaSetChannelOn (chandle , channelA , coupling , rangeMin , rangeMax , rangeType , analogueOffset , bandwidth )
37+ assert_pico_ok (status ["setChannelA" ])
38+
39+ for x in range (1 , 3 , 1 ):
40+ channel = x
41+ status ["setChannel" ,x ] = ps .psospaSetChannelOff (chandle ,channel )
42+ assert_pico_ok (status ["setChannel" ,x ])
43+
44+ # get max ADC value
45+ # handle = chandle
46+ minADC = ctypes .c_int16 ()
47+ maxADC = ctypes .c_int16 ()
48+ status ["getAdcLimits" ] = ps .psospaGetAdcLimits (chandle , resolution , ctypes .byref (minADC ), ctypes .byref (maxADC ))
49+ assert_pico_ok (status ["getAdcLimits" ])
50+
51+ # Set simple trigger on channel A, 1 V rising with 1 s autotrigger
52+ # handle = chandle
53+ # enable = 1
54+ source = channelA
55+ # threshold = 100 mV
56+ direction = enums .PICO_THRESHOLD_DIRECTION ["PICO_RISING" ]
57+ # delay = 0 s
58+ # autoTriggerMicroSeconds = 1000000 us
59+ status ["setSimpleTrigger" ] = ps .psospaSetSimpleTrigger (chandle , 1 , source , mV2adcV2 (100 ,rangeMax ,maxADC ), direction , 0 , 1000000 )
60+ assert_pico_ok (status ["setSimpleTrigger" ])
61+
62+ # Get fastest available timebase
63+ # handle = chandle
64+ enabledChannelFlags = enums .PICO_CHANNEL_FLAGS ["PICO_CHANNEL_A_FLAGS" ]
65+ timebase = ctypes .c_uint32 (0 )
66+ timeInterval = ctypes .c_double (0 )
67+ # resolution = resolution
68+ status ["getMinimumTimebaseStateless" ] = ps .psospaGetMinimumTimebaseStateless (chandle , enabledChannelFlags , ctypes .byref (timebase ), ctypes .byref (timeInterval ), resolution )
69+ print ("timebase = " , timebase .value )
70+ print ("sample interval =" , timeInterval .value , "s" )
71+
72+ # Set number of samples to be collected
73+ noOfPreTriggerSamples = 500000
74+ noOfPostTriggerSamples = 1000000
75+ nSamples = (noOfPostTriggerSamples + noOfPreTriggerSamples )
76+
77+ # Set number of memory segments
78+ noOfCaptures = 20
79+ maxSegments = ctypes .c_uint64 (10 )
80+ status ["memorySegments" ] = ps .psospaMemorySegments (chandle , noOfCaptures , ctypes .byref (maxSegments ))
81+ assert_pico_ok (status ["memorySegments" ])
82+
83+ # Set number of captures
84+ status ["setNoOfCaptures" ] = ps .psospaSetNoOfCaptures (chandle , noOfCaptures )
85+ assert_pico_ok (status ["setNoOfCaptures" ])
86+
87+ # Create buffers
88+ bufferAMax = (ctypes .c_int16 * nSamples )()
89+ bufferAMin = (ctypes .c_int16 * nSamples )() # used for downsampling which isn't in the scope of this example
90+ bufferAMax1 = (ctypes .c_int16 * nSamples )()
91+ bufferAMin1 = (ctypes .c_int16 * nSamples )() # used for downsampling which isn't in the scope of this example
92+ bufferAMax2 = (ctypes .c_int16 * nSamples )()
93+ bufferAMin2 = (ctypes .c_int16 * nSamples )() # used for downsampling which isn't in the scope of this example
94+ bufferAMax3 = (ctypes .c_int16 * nSamples )()
95+ bufferAMin3 = (ctypes .c_int16 * nSamples )() # used for downsampling which isn't in the scope of this example
96+ bufferAMax4 = (ctypes .c_int16 * nSamples )()
97+ bufferAMin4 = (ctypes .c_int16 * nSamples )() # used for downsampling which isn't in the scope of this example
98+ bufferAMax5 = (ctypes .c_int16 * nSamples )()
99+ bufferAMin5 = (ctypes .c_int16 * nSamples )() # used for downsampling which isn't in the scope of this example
100+ bufferAMax6 = (ctypes .c_int16 * nSamples )()
101+ bufferAMin6 = (ctypes .c_int16 * nSamples )() # used for downsampling which isn't in the scope of this example
102+ bufferAMax7 = (ctypes .c_int16 * nSamples )()
103+ bufferAMin7 = (ctypes .c_int16 * nSamples )() # used for downsampling which isn't in the scope of this example
104+ bufferAMax8 = (ctypes .c_int16 * nSamples )()
105+ bufferAMin8 = (ctypes .c_int16 * nSamples )() # used for downsampling which isn't in the scope of this example
106+ bufferAMax9 = (ctypes .c_int16 * nSamples )()
107+ bufferAMin9 = (ctypes .c_int16 * nSamples )() # used for downsampling which isn't in the scope of this example
108+
109+ # Set data buffers
110+ # handle = chandle
111+ # channel = channelA
112+ # bufferMax = bufferAMax
113+ # bufferMin = bufferAMin
114+ # nSamples = nSamples
115+ dataType = enums .PICO_DATA_TYPE ["PICO_INT16_T" ]
116+ waveform = 0
117+ downSampleMode = enums .PICO_RATIO_MODE ["PICO_RATIO_MODE_RAW" ]
118+ clear = enums .PICO_ACTION ["PICO_CLEAR_ALL" ]
119+ add = enums .PICO_ACTION ["PICO_ADD" ]
120+ action = clear | add # PICO_ACTION["PICO_CLEAR_WAVEFORM_CLEAR_ALL"] | PICO_ACTION["PICO_ADD"]
121+ status ["setDataBuffers" ] = ps .psospaSetDataBuffers (chandle , channelA , ctypes .byref (bufferAMax ), ctypes .byref (bufferAMin ), nSamples , dataType , waveform , downSampleMode , action )
122+ assert_pico_ok (status ["setDataBuffers" ])
123+ waveform1 = 1
124+ status ["setDataBuffers1" ] = ps .psospaSetDataBuffers (chandle , channelA , ctypes .byref (bufferAMax1 ), ctypes .byref (bufferAMin1 ), nSamples , dataType , waveform1 , downSampleMode , add )
125+ assert_pico_ok (status ["setDataBuffers1" ])
126+ waveform2 = 2
127+ status ["setDataBuffers2" ] = ps .psospaSetDataBuffers (chandle , channelA , ctypes .byref (bufferAMax2 ), ctypes .byref (bufferAMin2 ), nSamples , dataType , waveform2 , downSampleMode , add )
128+ assert_pico_ok (status ["setDataBuffers2" ])
129+ waveform3 = 3
130+ status ["setDataBuffers3" ] = ps .psospaSetDataBuffers (chandle , channelA , ctypes .byref (bufferAMax3 ), ctypes .byref (bufferAMin3 ), nSamples , dataType , waveform3 , downSampleMode , add )
131+ assert_pico_ok (status ["setDataBuffers3" ])
132+ waveform4 = 4
133+ status ["setDataBuffers4" ] = ps .psospaSetDataBuffers (chandle , channelA , ctypes .byref (bufferAMax4 ), ctypes .byref (bufferAMin4 ), nSamples , dataType , waveform4 , downSampleMode , add )
134+ assert_pico_ok (status ["setDataBuffers4" ])
135+ waveform5 = 5
136+ status ["setDataBuffers5" ] = ps .psospaSetDataBuffers (chandle , channelA , ctypes .byref (bufferAMax5 ), ctypes .byref (bufferAMin5 ), nSamples , dataType , waveform5 , downSampleMode , add )
137+ assert_pico_ok (status ["setDataBuffers5" ])
138+ waveform6 = 6
139+ status ["setDataBuffers6" ] = ps .psospaSetDataBuffers (chandle , channelA , ctypes .byref (bufferAMax6 ), ctypes .byref (bufferAMin6 ), nSamples , dataType , waveform6 , downSampleMode , add )
140+ assert_pico_ok (status ["setDataBuffers6" ])
141+ waveform7 = 7
142+ status ["setDataBuffers7" ] = ps .psospaSetDataBuffers (chandle , channelA , ctypes .byref (bufferAMax7 ), ctypes .byref (bufferAMin7 ), nSamples , dataType , waveform7 , downSampleMode , add )
143+ assert_pico_ok (status ["setDataBuffers7" ])
144+ waveform8 = 8
145+ status ["setDataBuffers8" ] = ps .psospaSetDataBuffers (chandle , channelA , ctypes .byref (bufferAMax8 ), ctypes .byref (bufferAMin8 ), nSamples , dataType , waveform8 , downSampleMode , add )
146+ assert_pico_ok (status ["setDataBuffers8" ])
147+ waveform9 = 9
148+ status ["setDataBuffers9" ] = ps .psospaSetDataBuffers (chandle , channelA , ctypes .byref (bufferAMax9 ), ctypes .byref (bufferAMin9 ), nSamples , dataType , waveform9 , downSampleMode , add )
149+ assert_pico_ok (status ["setDataBuffers9" ])
150+
151+ # Run block capture
152+ # handle = chandle
153+ # timebase = timebase
154+ timeIndisposedMs = ctypes .c_double (0 )
155+ # segmentIndex = 0
156+ # lpReady = None Using IsReady rather than a callback
157+ # pParameter = None
158+ status ["runBlock" ] = ps .psospaRunBlock (chandle , noOfPreTriggerSamples , noOfPostTriggerSamples , timebase , ctypes .byref (timeIndisposedMs ), 0 , None , None )
159+ assert_pico_ok (status ["runBlock" ])
160+
161+ # Check for data collection to finish using psospaIsReady
162+ ready = ctypes .c_int16 (0 )
163+ check = ctypes .c_int16 (0 )
164+ while ready .value == check .value :
165+ status ["isReady" ] = ps .psospaIsReady (chandle , ctypes .byref (ready ))
166+
167+ # Get data from scope
168+ # handle = chandle
169+ # startIndex = 0
170+ noOfSamples = ctypes .c_uint64 (nSamples )
171+ # downSampleRatio = 1
172+ # segmentIndex = 0
173+ # Creates a overflow location for each segment
174+ overflow = (ctypes .c_int16 * 10 )()
175+ status ["getValues" ] = ps .psospaGetValuesBulk (chandle , 0 , ctypes .byref (noOfSamples ),0 , 9 , 1 , downSampleMode , ctypes .byref (overflow ))
176+ assert_pico_ok (status ["getValues" ])
177+
178+ # convert ADC counts data to mV
179+ adc2mVChAMax = adc2mVV2 (bufferAMax , rangeMax , maxADC )
180+ adc2mVChAMax1 = adc2mVV2 (bufferAMax1 , rangeMax , maxADC )
181+ adc2mVChAMax2 = adc2mVV2 (bufferAMax2 , rangeMax , maxADC )
182+ adc2mVChAMax3 = adc2mVV2 (bufferAMax3 , rangeMax , maxADC )
183+ adc2mVChAMax4 = adc2mVV2 (bufferAMax4 , rangeMax , maxADC )
184+ adc2mVChAMax5 = adc2mVV2 (bufferAMax5 , rangeMax , maxADC )
185+ adc2mVChAMax6 = adc2mVV2 (bufferAMax6 , rangeMax , maxADC )
186+ adc2mVChAMax7 = adc2mVV2 (bufferAMax7 , rangeMax , maxADC )
187+ adc2mVChAMax8 = adc2mVV2 (bufferAMax8 , rangeMax , maxADC )
188+ adc2mVChAMax9 = adc2mVV2 (bufferAMax9 , rangeMax , maxADC )
189+
190+ # Create time data
191+ time = np .linspace (0 , (nSamples - 1 ) * timeInterval .value * 1000000000 , nSamples )
192+
193+ # plot data from channel A and B
194+ plt .plot (time , adc2mVChAMax [:])
195+ plt .plot (time , adc2mVChAMax1 [:])
196+ plt .plot (time , adc2mVChAMax2 [:])
197+ plt .plot (time , adc2mVChAMax3 [:])
198+ plt .plot (time , adc2mVChAMax4 [:])
199+ plt .plot (time , adc2mVChAMax5 [:])
200+ plt .plot (time , adc2mVChAMax6 [:])
201+ plt .plot (time , adc2mVChAMax7 [:])
202+ plt .plot (time , adc2mVChAMax8 [:])
203+ plt .plot (time , adc2mVChAMax9 [:])
204+ plt .xlabel ('Time (ns)' )
205+ plt .ylabel ('Voltage (mV)' )
206+ plt .show ()
207+
208+ # Close the scope
209+ status ["closeunit" ] = ps .psospaCloseUnit (chandle )
210+ assert_pico_ok (status ["closeunit" ])
211+
212+ print (status )
0 commit comments