PicoScope 7 Software
Available on Windows, Mac and Linux
Code: Select all
#define _GNU_SOURCE
/* Headers for Linux */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* Definition of PS2000 driver routines on Linux */
#include
#define __stdcall
#define Sleep(x) usleep(1000*(x))
enum BOOL {FALSE,TRUE};
/* End of Linux-specific definitions */
typedef enum {
MODEL_NONE = 0,
MODEL_PS2104 = 2104,
MODEL_PS2105 = 2105,
MODEL_PS2202 = 2202,
MODEL_PS2203 = 2203,
MODEL_PS2204 = 2204,
MODEL_PS2205 = 2205
} MODEL_TYPE;
typedef struct
{
PS2000_THRESHOLD_DIRECTION channelA;
PS2000_THRESHOLD_DIRECTION channelB;
PS2000_THRESHOLD_DIRECTION channelC;
PS2000_THRESHOLD_DIRECTION channelD;
PS2000_THRESHOLD_DIRECTION ext;
} DIRECTIONS;
typedef struct
{
PS2000_PWQ_CONDITIONS * conditions;
int16_t nConditions;
PS2000_THRESHOLD_DIRECTION direction;
uint32_t lower;
uint32_t upper;
PS2000_PULSE_WIDTH_TYPE type;
} PULSE_WIDTH_QUALIFIER;
typedef struct
{
PS2000_CHANNEL channel;
float threshold;
int16_t direction;
float delay;
} SIMPLE;
typedef struct
{
int16_t hysterisis;
DIRECTIONS directions;
int16_t nProperties;
PS2000_TRIGGER_CONDITIONS * conditions;
PS2000_TRIGGER_CHANNEL_PROPERTIES * channelProperties;
PULSE_WIDTH_QUALIFIER pwq;
uint32_t totalSamples;
int16_t autoStop;
int16_t triggered;
} ADVANCED;
typedef struct
{
SIMPLE simple;
ADVANCED advanced;
} TRIGGER_CHANNEL;
typedef struct {
int16_t DCcoupled;
int16_t range;
int16_t enabled;
} CHANNEL_SETTINGS;
typedef struct {
int16_t handle;
MODEL_TYPE model;
PS2000_RANGE firstRange;
PS2000_RANGE lastRange;
TRIGGER_CHANNEL trigger;
int16_t maxTimebase;
int16_t timebases;
int16_t noOfChannels;
CHANNEL_SETTINGS channelSettings[PS2000_MAX_CHANNELS];
int16_t hasAdvancedTriggering;
int16_t hasFastStreaming;
int16_t hasEts;
int16_t hasSignalGenerator;
} UNIT_MODEL;
UNIT_MODEL unitOpened;
uint16_t calBackFinished = 0; // call back semaphore,
uint32_t calBackCounter = 0;
uint32_t loopCounter1 = 0;
uint32_t loopCounter2 = 0;
#define BUFF_SIZE 100000
int16_t SCLData[BUFF_SIZE];
int16_t SDAData[BUFF_SIZE];
int16_t SCLDataLog[BUFF_SIZE];
int16_t SDADataLog[BUFF_SIZE];
clock_t calBackTimestamp[5000];
clock_t loopTimestampBefore[5000];
clock_t loopTimestampAfter[5000];
uint32_t sampleBuff[5000];
void __stdcall ps2000FastStreamingReady(int16_t **overviewBuffers, int16_t overflow, uint32_t triggerdAt, int16_t triggered, int16_t auto_stop, uint32_t nValues)
{
//memcpy(&(SCLData[unitOpened.trigger.advanced.totalSamples]), overviewBuffers[0], nValues*sizeof(SCLData[0]));
//memcpy(&(SDAData[unitOpened.trigger.advanced.totalSamples]), overviewBuffers[1], nValues*sizeof(SDAData[0]));
unitOpened.trigger.advanced.totalSamples += nValues;
unitOpened.trigger.advanced.autoStop = auto_stop;
calBackFinished = 1;
if (5000 > calBackCounter) {
calBackTimestamp[calBackCounter] = clock();
sampleBuff[calBackCounter] = nValues;
calBackCounter++;
}
}
int main(int argc, char **argv)
{
int32_t ok;
int16_t overflow;
int16_t triggered;
uint32_t triggerAt;
clock_t firstBlockTime;
clock_t lastBlockTime;
int16_t firstCaptured = 0;
PS2000_CHANNEL chan;
double startTime = 0;
double duration_us;
loopTimestampBefore[0] = clock();
loopTimestampAfter[0] = clock();
loopCounter1++;
calBackTimestamp[0] = clock();
sampleBuff[0] = 0;
calBackCounter++;
unitOpened.trigger.advanced.autoStop = 0;
unitOpened.trigger.advanced.totalSamples = 0;
for (chan=PS2000_CHANNEL_A; chan <= PS2000_CHANNEL_B; chan++) {
unitOpened.channelSettings[chan].enabled = TRUE;
unitOpened.channelSettings[chan].DCcoupled = TRUE;
unitOpened.channelSettings[chan].range = PS2000_5V;
}
unitOpened.handle = ps2000_open_unit();
if (0 < unitOpened.handle) {
ok = ps2000_set_ets(unitOpened.handle, PS2000_ETS_OFF, 0, 0);
if (0 == ok) {
fprintf(stdout, "ETS is disabled\n");
} else {
fprintf(stdout, "failed to disable ETS with call ps2000_set_ets\n");
}
for (chan=PS2000_CHANNEL_A; chan <= PS2000_CHANNEL_B; chan++) {
ok = ps2000_set_channel(unitOpened.handle, chan, unitOpened.channelSettings[chan].enabled, unitOpened.channelSettings[chan].DCcoupled, unitOpened.channelSettings[chan].range);
if (0 == ok) {
fprintf(stdout, "function call ps2000_set_channel for channel %d failed\n", chan);
}
}
ok = ps2000_set_trigger(unitOpened.handle, PS2000_CHANNEL_B, 500, PS2000_FALLING, 0, 0);
if (0 == ok) {
fprintf(stdout, "function call: ps2000_set_trigger failed\n");
}
ok = ps2000_run_streaming_ns(unitOpened.handle, 500, PS2000_NS, BUFF_SIZE, TRUE, 1, BUFF_SIZE);
if (0 == ok) {
fprintf(stdout, "function call: ps2000_run_streaming_ns failed\n");
}
while(0 == unitOpened.trigger.advanced.autoStop) {
ok = 0;
if (5000 > loopCounter1) {
loopTimestampBefore[loopCounter1]=clock();
}
calBackFinished = 0;
while(0 == ok) {
ok = ps2000_get_streaming_last_values(unitOpened.handle, ps2000FastStreamingReady);
loopCounter2++;
}
if (0 == firstCaptured) {
firstBlockTime = clock();
firstCaptured = 1;
}
if (5000 > loopCounter1) {
loopTimestampAfter[loopCounter1]=clock();
loopCounter1++;
}
}
lastBlockTime = clock();
duration_us = 1000000*((double) (lastBlockTime - firstBlockTime))/CLOCKS_PER_SEC;
ps2000_stop(unitOpened.handle);
ps2000_get_streaming_values_no_aggregation(unitOpened.handle, &startTime, SCLDataLog, SDADataLog, NULL, NULL, &overflow, &triggerAt, &triggered, BUFF_SIZE);
// Write data to file
// Close the unit
ps2000_close_unit(unitOpened.handle);
} else {
fprintf(stdout, "function call ps2000_open_unit failed\n");
}
}
Code: Select all
ok = ps2000_set_trigger(unitOpened.handle, PS2000_CHANNEL_B, 500, PS2000_FALLING, 0, 0);
Code: Select all
delay, the delay, as a percentage of the requested number of data
points, between the trigger event and the start of the block. It
should be in the range -100% to +100%. Thus, 0% means that the
trigger event is at the first data value in the block, and -50% means
that it is in the middle of the block. If you wish to specify the delay
as a floating-point value,
auto_trigger_ms, the delay in milliseconds after which the
oscilloscope will collect samples if no trigger event occurs. If this is
set to zero the oscilloscope will wait for a trigger indefinitely.
Code: Select all
/****************************************************************************
*
* Streaming callback
*
* This demonstrates how to copy data to application buffers
*
****************************************************************************/
void __stdcall ps2000FastStreamingReady2( int16_t **overviewBuffers,
int16_t overflow,
uint32_t triggeredAt,
int16_t triggered,
int16_t auto_stop,
uint32_t nValues)
{
int16_t channel = 0;
unitOpened.trigger.advanced.totalSamples += nValues;
unitOpened.trigger.advanced.autoStop = auto_stop;
g_triggered = triggered;
g_triggeredAt = triggeredAt;
g_overflow = overflow;
if(nValues > 0 && g_appBufferFull == 0)
{
for(channel = (int16_t) PS2000_CHANNEL_A; channel < DUAL_SCOPE; channel++)
{
if(bufferInfo.unit.channelSettings[channel].enabled)
{
if(unitOpened.trigger.advanced.totalSamples <= bufferInfo.bufferSizes[channel * 2] && !g_appBufferFull)
{
g_nValues = nValues;
}
else if(g_startIndex < bufferInfo.bufferSizes[channel * 2])
{
g_nValues = bufferInfo.bufferSizes[channel * 2] - (g_startIndex + 1); // Only copy data into application buffer up to end
unitOpened.trigger.advanced.totalSamples = bufferInfo.bufferSizes[channel * 2]; // Total samples limited to application buffer
g_appBufferFull = 1;
}
else
{
// g_startIndex might be >= buffer length
g_nValues = 0;
unitOpened.trigger.advanced.totalSamples = bufferInfo.bufferSizes[channel * 2];
g_appBufferFull = 1;
}
// Copy data...
// Max buffers
if(overviewBuffers[channel * 2] && bufferInfo.appBuffers[channel * 2])
{
memcpy_s((void *) (bufferInfo.appBuffers[channel * 2] + g_startIndex), g_nValues * sizeof(int16_t),
(void *) (overviewBuffers[channel * 2]), g_nValues * sizeof(int16_t));
}
// Min buffers
if(overviewBuffers[channel * 2 + 1] && bufferInfo.appBuffers[channel * 2 + 1])
{
memcpy_s((void *) (bufferInfo.appBuffers[channel * 2 + 1] + g_startIndex), g_nValues * sizeof(int16_t),
(void *) (overviewBuffers[channel * 2 + 1]), g_nValues * sizeof(int16_t));
}
}
}
g_prevStartIndex = g_startIndex;
g_startIndex = unitOpened.trigger.advanced.totalSamples;
}
}
Code: Select all
// Simple trigger, 500mV, rising
ok = ps2000_set_trigger(unitOpened.handle, PS2000_CHANNEL_A,
mv_to_adc(500, unitOpened.channelSettings[PS2000_CHANNEL_A].range), PS2000_RISING, 0, 0);
unitOpened.trigger.advanced.autoStop = 0;
unitOpened.trigger.advanced.totalSamples = 0;
unitOpened.trigger.advanced.triggered = 0;
//Reset global values
g_nValues = 0;
g_triggered = 0;
g_triggeredAt = 0;
g_startIndex = 0;
g_prevStartIndex = 0;
g_appBufferFull = 0;
bufferInfo.unit = unitOpened;
// Allocate memory for data arrays
// Max A buffer at index 0, min buffer at index 1
bufferInfo.appBuffers[PS2000_CHANNEL_A * 2] = (int16_t *) calloc(appBufferSize, sizeof(int16_t));
bufferInfo.bufferSizes[PS2000_CHANNEL_A * 2] = appBufferSize;
if(unitOpened.channelSettings[PS2000_CHANNEL_B].enabled)
{
// Max B buffer at index 2, min buffer at index 3
bufferInfo.appBuffers[PS2000_CHANNEL_B * 2] = (int16_t *) calloc(appBufferSize, sizeof(int16_t));
bufferInfo.bufferSizes[PS2000_CHANNEL_B * 2] = appBufferSize;
}
/* Collect data at 10us intervals
* 100000 points with an aggregation of 100 : 1
* Auto stop after the 100000 samples
* Start it collecting,
*/
//ok = ps2000_run_streaming_ns ( unitOpened.handle, 10, PS2000_US, NUM_STREAMING_SAMPLES, 1, 100, overviewBufferSize );
/* Collect data at 1us intervals
* 1000000 points after trigger with 0 aggregation
* Auto stop after the 1000000 samples
* Start it collecting,
* NOTE: The actual sampling interval used by the driver might not be that which is specified below. Use the sampling intervals
* returned by the ps2000_get_timebase function to work out the most appropriate sampling interval to use. As these are low memory
* devices, the fastest sampling intervals may result in lost data.
*/
ok = ps2000_run_streaming_ns ( unitOpened.handle, 1, PS2000_US, NUM_STREAMING_SAMPLES, 1, 1, overviewBufferSize ); // No aggregation
printf ( "OK: %d\n", ok );
/* From here on, we can get data whenever we want...*/
while (!_kbhit() && !unitOpened.trigger.advanced.autoStop && !g_appBufferFull)
{
ps2000_get_streaming_last_values (unitOpened.handle, ps2000FastStreamingReady2);
if (nPreviousValues != unitOpened.trigger.advanced.totalSamples)
{
sample_count = unitOpened.trigger.advanced.totalSamples - nPreviousValues;
//Printing to console can take up resources
//printf ("Values collected: %ld, Total samples: %ld ", sample_count, unitOpened.trigger.advanced.totalSamples);
/*if(g_triggered)
{
printf("Triggered at index: %lu, overall %lu", g_triggeredAt, nPreviousValues + g_triggeredAt);
}*/
nPreviousValues = unitOpened.trigger.advanced.totalSamples;
//printf("\n");
if(g_appBufferFull)
{
unitOpened.trigger.advanced.totalSamples = appBufferSize;
printf("\nApplication buffer full - stopping data collection.\n");
}
}
}
ps2000_stop (unitOpened.handle);