PicoScope 7 Software
Available on Windows, Mac and Linux
Code: Select all
unsafe extern "C" fn callback(handle: i16, status: PicoStatus, flag: *mut ::std::os::raw::c_void) {
*(flag as *mut _ as *mut bool) = true;
}
fn main() {
/*
First I have to connect to the picoscope (model is 5203).
I use ps5000OpenUnit call which provides me a handle uniquely identifying connected device to the API.
*/
let mut handle: i16 = 0;
unsafe {
// Connect to the oscilloscope, model 5203
assert_eq!(ps5000OpenUnit(&mut handle), PicoOk);
}
/*
ETS stands for equivalent time sampling.
It is used to aggregate multiple cycles of repeating signal in order to improve approximated signal.
I disable it as in this case signal is not repeating due to occasional noise spikes, etc
*/
unsafe {
// Disable ETS as I need unprocessed signal
assert_eq!(ps5000SetEts(handle, ETSOff, 0, 0, null_mut()), PicoOk);
}
/*
I only use channel A to which antenna is connected. Therefore I disable channel B.
I know that 2v range is sufficent for my task as this is the range PicoScope 7 client chooses when range is set to auto.
*/
unsafe {
assert_eq!(ps5000SetChannel(handle, ChannelA, 1, 1, R2V), PicoOk);
assert_eq!(ps5000SetChannel(handle, ChannelB, 0, 1, R2V), PicoOk);
}
/*
Set simple trigger to fire when abnormally high (1.5v) pulse is detected on A channel.
The trigger fires on rising edge of the pulse.
The triger will not timeout and wait indefinetly because auto_trigger_ms is set to 0.
*/
unsafe {
assert_eq!(ps5000SetSimpleTrigger(handle,
1,
ChannelA,
mv_to_adc(1500, R2V) as i16,
Rising,
0,
0),
PicoOk);
}
/*
I need to sample at 125Mhz which is 125_000_000Hz.
I need to record at least one full frame.
I can only record one full frame as when using PicoScope 7 with required samping rate in SR priority mode I only had
2 waveforms of data which only had 2 voltage spikes meaning there was only one full frame. Assuming PicoScope 7
doesnt reduce buffer size unless forced to its the hardware limit I cannot overcome.
At 60 fps, 1 frame takes 1/60 s.
125_000_000 / 60 = 2083333.3
Since I cannot have fractional samples and that fps is not percisely 60 but fluctuates I round up number of samples
to 2083400 in hopes this is sufficent to record whole frame while still allowed by hardware limitations.
*/
let mut buffer: Vec = vec![0;2083400];
unsafe {
assert_eq!(ps5000SetDataBuffer(handle, ChannelA, buffer.as_mut_ptr(), 2083400), PicoOk);
}
/*
I do not fully understand what a timebase is.
The way I understood, function ps5000GetTimebase takes sample rate encoded as timebase value as stated in programing guide
as well as required number of samples. It then returns PicoOk if this combination of sampling rate and number samples is within
hardware limits. Otherwise it returns one of the error codes.
In either case it sets sampling rate and number samples parameters passed as pointers to the closest permissible values.
I assume oversampling refers to subdividing each sample into multiple samples and averaging them. Therefore, due to
already tight situation with buffer size I set it to one, which means samples wont be subdivided.
*/
let mut sampling_rate: i32 = 0;
let mut number_samples: i32 = 0;
unsafe {
ps5000GetTimebase(
handle,
3, // period of 8ns which means signal has frequency of 125Mhz
2083400,
&mut sampling_rate,
1, // no oversampling since otherwise I wont be able to store whole HDMI frame
&mut number_samples,
0
);
}
/*
Here I call RunBlock requesting the capture to begin with the triger, that is no samples before trigger would be stored.
I pass user defined callback which upon capture complete will be called on the parameter passed via p_parameter.
here, my callback simply sets flag to true.
*/
let mut flag: bool = false;
unsafe {
ps5000RunBlock(
handle,
0, // begin at the trigger, do not sample before
2083400, // sample whole frame after trigger
3,
1,
null_mut(),
0,
Some(callback),
&mut flag as *mut bool as *mut _
);
}
// poll untill capture complete
while !flag {
;
}
/*
Call to ps5000GetValues dumps everything to the buffer passed earlier on.
Downsample ratio allows to downsample signal stored in oscilloscope memory before transfering it to the PC.
By setting mode to None I choose not to downsample and get each sample recorded.
Samples returned will be populated by the actual number of samples recorded. I do not know why it may differ, but I take it's asanity check.
*/
let mut samples_returned: u32 = 0;
unsafe {
assert_eq!(ps5000GetValues(handle,
0,
&mut samples_returned,
1,
RatioModeNone,
0,
null_mut()), PicoOk);
}
/*
At the end, I gracefully disconnect from the picoscope using call to ps5000CloseUnit.
*/
unsafe {
assert_eq!(ps5000CloseUnit(handle), PicoOk);
}
}
Code: Select all
pub fn mv_to_adc(mv: i16, pr: PicoRange) -> i16 {
static INPUT_RANGE: [u16; 12] = [ 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000];
return ((mv as i32 * 32512) / INPUT_RANGE[pr as i32 as usize] as i32) as i16;
}
pub type ps5000BlockReady = Option<
unsafe extern "C" fn(handle: i16, status: PicoStatus, p_parameter: *mut ::std::os::raw::c_void),
>;
#[derive(PartialEq, Debug, Copy, Clone)]
#[repr(C)]
pub enum PicoStatus {
PicoOk = 0,
PicoInvalidHandle = 12,
PicoNullParameter = 22,
PicoInvalidInfo = 41,
PicoInfoUnavailable = 42,
PicoOsNotSupported = 11,
PicoOpenOperationInProgress = 5,
PicoEepromCorrupt = 10,
PicoKernelDriverTooOld = 9,
PicoFwFail = 4,
PicoMaxUnitsOpened = 1,
PicoNotFound = 3,
PicoNotResponding = 7,
PicoUserCallback = 35,
PicoInvalidParameter = 13,
PicoInvalidChannel = 16,
PicoInvalidVoltageRange = 15,
PicoDriverFunction = 67,
PicoInvalidTimebase = 14,
PicoTooManySamples = 29,
PicoSegmentOutOfRange = 38,
PicoInvalidTriggerChannel = 17,
PicoInvalidConditionChannel = 18,
PicoConfigFail = 8,
PicoWarningAuxOutputConflict = 52,
PicoWarningExtThresholdConflict = 51,
PicoTriggerError = 44,
PicoNoSamplesAvailable = 37,
PicoDeviceSampling = 36,
PicoDataNotAvailable = 24,
PicoStartindexInvalid = 40,
PicoInvalidSampleratio = 64,
PicoInvalidCall = 60,
PicoMemory = 45,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub enum PicoInfo {
PicoDriverVersion = 0,
PicoUsbVersion = 1,
PicoHardwareVersion = 2,
PicoVariantInfo = 3,
PicoBatchAndSerial = 4,
PicoCalDate = 5,
PicoKernelVersion = 6
}
#[repr(C)]
pub enum PicoETSMode {
ETSOff = 0,
ETSFast = 1,
ETSSlow = 2,
ETSModesMax = 3
}
#[repr(C)]
pub enum PicoChannel {
ChannelA = 0,
ChannelB = 1
}
#[repr(C)]
pub enum PicoRange {
R10MV = 0,
R20MV = 1,
R50MV = 2,
R100MV = 3,
R200MV = 4,
R500MV = 5,
R1V = 6,
R2V = 7,
R5V = 8,
R10V = 9,
R20V = 10,
R50V = 11,
RMaxRanges = 12,
}
#[repr(C)]
pub enum ThresholdDirection {
Above = 0,
Below = 1,
Rising = 2,
Falling = 3,
RisingOrFalling = 4
}
#[repr(C)]
pub enum RatioMode {
RatioModeNone = 0,
RatioModeAggregate = 1,
RatioModeDecimate = 2,
RatioModeAverage = 4,
RatioModeDistribution = 8
}
#[link_name = "ps5000.lib"]
extern "C" {
pub fn ps5000OpenUnit(p_handle: *mut i16) -> PicoStatus;
pub fn ps5000CloseUnit(handle: i16) -> PicoStatus;
pub fn ps5000GetUnitInfo(
handle: i16,
buf: *mut u8,
buf_len: i16,
required_len: *mut i16,
info: PicoInfo,
) -> PicoStatus;
pub fn ps5000SetEts(
handle: i16,
mode: PicoETSMode,
ets_cycles: i16,
ets_interleave: i16,
sample_time_picoseconds: *mut i32,
) -> PicoStatus;
pub fn ps5000SetChannel(
handle: i16,
channel: PicoChannel,
enabled: i16,
dc: i16,
range: PicoRange,
) -> PicoStatus;
pub fn ps5000SetSimpleTrigger(
handle: i16,
enable: i16,
source: PicoChannel,
threshold: i16,
direction: ThresholdDirection,
delay: u32,
auto_trigger_ms: i16,
) -> PicoStatus;
pub fn ps5000SetDataBuffer(
handle: i16,
channel: PicoChannel,
buffer: *mut i16,
buffer_len: i32,
) -> PicoStatus;
pub fn ps5000GetTimebase(
handle: i16,
timebase: u32,
no_samples: i32,
time_interval_nanoseconds: *mut i32,
oversample: i16,
max_samples: *mut i32,
segment_index: u16,
) -> PicoStatus;
pub fn ps5000RunBlock(
handle: i16,
no_of_pre_trigger_samples: i32,
no_of_post_trigger_samples: i32,
timebase: u32,
oversample: i16,
time_indisposed_ms: *mut i32,
segment_index: u16,
lp_ready: ps5000BlockReady,
p_parameter: *mut ::std::os::raw::c_void,
) -> PicoStatus;
pub fn ps5000GetValues(
handle: i16,
start_index: u32,
no_of_samples: *mut u32,
down_sample_ratio: u32,
down_sample_ratio_mode: RatioMode,
segment_index: u16,
overflow: *mut i16,
) -> PicoStatus;
}