Files
sicspsi/utils/picoscope/PS2000Acon.c
Koennecke Mark 0294b7ad95 Added the small support driver for the picoscope
Added a deploysics script
The Tcl data and time functions were moved to the SICS kernel
2015-07-07 12:33:02 +02:00

2473 lines
69 KiB
C

/***********************************************************************************************************************************************
*
* Filename: PS2000Acon.c
*
* Copyright: Pico Technology Limited 2010
*
* Author: RPM
*
* Description:
* This is a console mode program that demonstrates how to use the
* PicoScope 2000a series API.
*
* Examples:
* Collect a block of samples immediately
* Collect a block of samples when a trigger event occurs
* Collect a stream of data immediately
* Collect a stream of data when a trigger event occurs
* Set Signal Generator, using standard or custom signals
*
* Digital Examples (MSO variants only):
* Collect a block of digital samples immediately
* Collect a block of digital samples when a trigger event occurs
* Collect a block of analogue & digital samples when analogue AND digital trigger events occurs
* Collect a block of analogue & digital samples when analogue OR digital trigger events occurs
* Collect a stream of digital data immediately
* Collect a stream of digital data and show aggregated values
*
*
*
* To build this application:
* Set up a project for a 32-bit console mode application
* Add this file to the project
* Add PS2000A.lib to the project
* Add ps2000aApi.h and picoStatus.h to the project
* Build the project
*
******************************************************************************************************************************************************/
#include <stdio.h>
/* Headers for Windows */
#ifdef _WIN32
#include "windows.h"
#include <conio.h>
#include "..\ps2000aApi.h"
#else
#include <sys/types.h>
#include <string.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <libps2000a-1.1/ps2000aApi.h>
#ifndef PICO_STATUS
#include <libps2000a-1.1/PicoStatus.h>
#endif
#define Sleep(a) usleep(1000*a)
#define scanf_s scanf
#define fscanf_s fscanf
#define memcpy_s(a,b,c,d) memcpy(a,c,d)
typedef enum enBOOL
{
FALSE, TRUE
} BOOL;
/* A function to detect a keyboard press on Linux */
int32_t _getch()
{
struct termios oldt, newt;
int32_t ch;
int32_t bytesWaiting;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
setbuf(stdin, NULL);
do
{
ioctl(STDIN_FILENO, FIONREAD, &bytesWaiting);
if (bytesWaiting)
getchar();
} while (bytesWaiting);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return ch;
}
int32_t _kbhit()
{
struct termios oldt, newt;
int32_t bytesWaiting;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
setbuf(stdin, NULL);
ioctl(STDIN_FILENO, FIONREAD, &bytesWaiting);
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return bytesWaiting;
}
int32_t fopen_s(FILE ** a, const char * b, const char * c)
{
FILE * fp = fopen(b, c);
*a = fp;
return (fp > 0) ? 0 : -1;
}
/* A function to get a single character on Linux */
#define max(a,b) ((a) > (b) ? a : b)
#define min(a,b) ((a) < (b) ? a : b)
#endif
#define PREF4 __stdcall
int32_t cycles = 0;
#define BUFFER_SIZE 1024
#define QUAD_SCOPE 4
#define DUAL_SCOPE 2
typedef enum
{
ANALOGUE, DIGITAL, AGGREGATED, MIXED
} MODE;
typedef struct
{
int16_t DCcoupled;
int16_t range;
int16_t enabled;
} CHANNEL_SETTINGS;
typedef enum
{
MODEL_NONE = 0,
MODEL_PS2205 = 0x2205,
MODEL_PS2205MSO = 0xE205,
MODEL_PS2206 = 0x2206,
MODEL_PS2207 = 0x2207,
MODEL_PS2208 = 0x2208,
MODEL_PS2206A = 0xA206,
MODEL_PS2207A = 0xA207,
MODEL_PS2208A = 0xA208,
} MODEL_TYPE;
typedef struct tTriggerDirections
{
PS2000A_THRESHOLD_DIRECTION channelA;
PS2000A_THRESHOLD_DIRECTION channelB;
PS2000A_THRESHOLD_DIRECTION channelC;
PS2000A_THRESHOLD_DIRECTION channelD;
PS2000A_THRESHOLD_DIRECTION ext;
PS2000A_THRESHOLD_DIRECTION aux;
} TRIGGER_DIRECTIONS;
typedef struct tPwq
{
PS2000A_PWQ_CONDITIONS * conditions;
int16_t nConditions;
PS2000A_THRESHOLD_DIRECTION direction;
uint32_t lower;
uint32_t upper;
PS2000A_PULSE_WIDTH_TYPE type;
} PWQ;
typedef struct
{
int16_t handle;
MODEL_TYPE model;
char modelString[8];
char serial[10];
int16_t complete;
int16_t openStatus;
int16_t openProgress;
PS2000A_RANGE firstRange;
PS2000A_RANGE lastRange;
int16_t channelCount;
int16_t maxValue;
int16_t signalGenerator;
int16_t ETS;
int16_t AWGFileSize;
CHANNEL_SETTINGS channelSettings [PS2000A_MAX_CHANNELS];
int16_t digitalPorts;
}UNIT;
// Global Variables
uint32_t timebase = 8;
int16_t oversample = 1;
BOOL scaleVoltages = TRUE;
uint16_t inputRanges[PS2000A_MAX_RANGES] =
{ 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000 };
BOOL g_ready = FALSE;
int64_t g_times[PS2000A_MAX_CHANNELS];
int16_t g_timeUnit;
int32_t g_sampleCount;
uint32_t g_startIndex;
int16_t g_autoStopped;
int16_t g_trig = 0;
uint32_t g_trigAt = 0;
int16_t g_overflow = 0;
char BlockFile[20] = "block.txt";
char StreamFile[20] = "stream.txt";
/****************************************************************************
* Callback
* used by PS2000A data streaimng collection calls, on receipt of data.
* used to set global flags etc checked by user routines
****************************************************************************/
void PREF4 CallBackStreaming(int16_t handle, int32_t noOfSamples,
uint32_t startIndex, int16_t overflow, uint32_t triggerAt,
int16_t triggered, int16_t autoStop, void *pParameter)
{
// used for streaming
g_sampleCount = noOfSamples;
g_startIndex = startIndex;
g_autoStopped = autoStop;
// flag to say done reading data
g_ready = TRUE;
// flags to show if & where a trigger has occurred
g_trig = triggered;
g_trigAt = triggerAt;
}
/****************************************************************************
* Callback
* used by PS2000A data block collection calls, on receipt of data.
* used to set global flags etc checked by user routines
****************************************************************************/
void PREF4 CallBackBlock(int16_t handle, PICO_STATUS status, void * pParameter)
{
if (status != PICO_CANCELLED)
g_ready = TRUE;
}
/****************************************************************************
* CloseDevice
****************************************************************************/
void CloseDevice(UNIT *unit)
{
ps2000aCloseUnit(unit->handle);
}
/****************************************************************************
* SetDefaults - restore default settings
****************************************************************************/
void SetDefaults(UNIT * unit)
{
PICO_STATUS status;
int32_t i;
status = ps2000aSetEts(unit->handle, PS2000A_ETS_OFF, 0, 0, NULL); // Turn off ETS
for (i = 0; i < unit->channelCount; i++) // reset channels to most recent settings
{
status
= ps2000aSetChannel(
unit->handle,
(PS2000A_CHANNEL) PS2000A_CHANNEL_A + i,
unit->channelSettings[PS2000A_CHANNEL_A + i].enabled,
(PS2000A_COUPLING) unit->channelSettings[PS2000A_CHANNEL_A
+ i].DCcoupled,
(PS2000A_RANGE) unit->channelSettings[PS2000A_CHANNEL_A
+ i].range, 0);
}
}
/****************************************************************************
* SetDigitals - enable or disable Digital Channels
****************************************************************************/
PICO_STATUS SetDigitals(UNIT *unit, int16_t state)
{
PICO_STATUS status;
int16_t logicLevel;
float logicVoltage = 1.5;
int16_t maxLogicVoltage = 5;
int16_t timebase = 1;
int16_t port;
// Set logic threshold
logicLevel = (int16_t) ((logicVoltage / maxLogicVoltage)
* PS2000A_MAX_LOGIC_LEVEL);
// Enable or Disable Digital ports
for (port = PS2000A_DIGITAL_PORT0; port <= PS2000A_DIGITAL_PORT1; port++)
{
status = ps2000aSetDigitalPort(unit->handle,
(PS2000A_DIGITAL_PORT) port, state, logicLevel);
printf(
status
? "SetDigitals:PS2000ASetDigitalPort(Port 0x%X) ------ 0x%08lx \n"
: "", port, status);
}
return status;
}
/****************************************************************************
* DisableAnalogue - Disable Analogue Channels
****************************************************************************/
PICO_STATUS DisableAnalogue(UNIT *unit)
{
PICO_STATUS status;
int16_t ch;
// Turn off analogue channels
for (ch = 0; ch < unit->channelCount; ch++)
{
if ((status = ps2000aSetChannel(unit->handle, (PS2000A_CHANNEL) ch, 0,
PS2000A_DC, PS2000A_50MV, 0)) != PICO_OK)
printf(
"DisableAnalogue:ps2000aSetChannel(channel %d) ------ 0x%08lx \n",
ch, status);
}
return status;
}
/****************************************************************************
* adc_to_mv
*
* Convert an 16-bit ADC count into millivolts
****************************************************************************/
int32_t adc_to_mv(int32_t raw, int32_t ch, UNIT * unit)
{
return (raw * inputRanges[ch]) / unit->maxValue;
}
/****************************************************************************
* mv_to_adc
*
* Convert a millivolt value into a 16-bit ADC count
*
* (useful for setting trigger thresholds)
****************************************************************************/
int16_t mv_to_adc(int16_t mv, int16_t ch, UNIT * unit)
{
return (mv * unit->maxValue) / inputRanges[ch];
}
/****************************************************************************
* ClearDataBuffers
*
* stops GetData writing values to memory that has been released
****************************************************************************/
PICO_STATUS ClearDataBuffers(UNIT * unit)
{
int32_t i;
PICO_STATUS status;
for (i = 0; i < unit->channelCount; i++)
{
if ((status = ps2000aSetDataBuffers(unit->handle, (int16_t) i, NULL,
NULL, 0, 0, PS2000A_RATIO_MODE_NONE)) != PICO_OK)
printf(
"ClearDataBuffers:ps2000aSetDataBuffers(channel %d) ------ 0x%08lx \n",
i, status);
}
for (i = 0; i < unit->digitalPorts; i++)
{
if ((status = ps2000aSetDataBuffer(unit->handle, (PS2000A_CHANNEL) (i
+ PS2000A_DIGITAL_PORT0), NULL, 0, 0, PS2000A_RATIO_MODE_NONE))
!= PICO_OK)
printf(
"ClearDataBuffers:ps2000aSetDataBuffer(port 0x%X) ------ 0x%08lx \n",
i + PS2000A_DIGITAL_PORT0, status);
}
return status;
}
/****************************************************************************
* BlockDataHandler
* - Used by all block data routines
* - acquires data (user sets trigger mode before calling), displays 10 items
* and saves all to data.txt
* Input :
* - unit : the unit to use.
* - text : the text to display before the display of data slice
* - offset : the offset into the data buffer to start the display's slice.
****************************************************************************/
void BlockDataHandler(UNIT * unit, char * text, int32_t offset, MODE mode)
{
int32_t i, j;
int32_t timeInterval;
int32_t sampleCount = BUFFER_SIZE;
FILE * fp = NULL;
int32_t maxSamples;
int16_t * buffers[PS2000A_MAX_CHANNEL_BUFFERS];
int16_t * digiBuffer[PS2000A_MAX_DIGITAL_PORTS];
int32_t timeIndisposed;
uint16_t digiValue;
PICO_STATUS status;
if (mode == ANALOGUE || mode == MIXED) // Analogue or (MSO Only) MIXED
{
for (i = 0; i < unit->channelCount; i++)
{
buffers[i * 2] = (int16_t*) malloc(sampleCount * sizeof(int16_t));
buffers[i * 2 + 1] = (int16_t*) malloc(sampleCount * sizeof(int16_t));
status = ps2000aSetDataBuffers(unit->handle, (int16_t) i, buffers[i
* 2], buffers[i * 2 + 1], sampleCount, 0,
PS2000A_RATIO_MODE_NONE);
printf(
status
? "BlockDataHandler:ps2000aSetDataBuffers(channel %d) ------ 0x%08lx \n"
: "", i, status);
}
}
if (mode == DIGITAL || mode == MIXED) // (MSO Only) Digital or MIXED
{
for (i = 0; i < unit->digitalPorts; i++)
{
digiBuffer[i] = (int16_t*) malloc(sampleCount * sizeof(int16_t));
status = ps2000aSetDataBuffer(unit->handle, (PS2000A_CHANNEL) (i
+ PS2000A_DIGITAL_PORT0), digiBuffer[i], sampleCount, 0,
PS2000A_RATIO_MODE_NONE);
printf(
status
? "BlockDataHandler:ps2000aSetDataBuffer(port 0x%X) ------ 0x%08lx \n"
: "", i + PS2000A_DIGITAL_PORT0, status);
}
}
/* find the maximum number of samples, the time interval (in timeUnits),
* the most suitable time units, and the maximum oversample at the current timebase*/
while (ps2000aGetTimebase(unit->handle, timebase, sampleCount,
&timeInterval, oversample, &maxSamples, 0))
{
timebase++;
}
printf("\nTimebase: %lu SampleInterval: %ldnS oversample: %hd\n",
timebase, timeInterval, oversample);
/* Start it collecting, then wait for completion*/
g_ready = FALSE;
status = ps2000aRunBlock(unit->handle, 0, sampleCount, timebase,
oversample, &timeIndisposed, 0, CallBackBlock, NULL);
printf(status ? "BlockDataHandler:ps2000aRunBlock ------ 0x%08lx \n" : "",
status);
printf("Waiting for trigger...Press a key to abort\n");
while (!g_ready && !_kbhit())
{
Sleep(0);
}
if (g_ready)
{
status = ps2000aGetValues(unit->handle, 0,
(uint32_t*) &sampleCount, 1, PS2000A_RATIO_MODE_NONE, 0,
NULL);
printf(
status
? "BlockDataHandler:ps2000aGetValues ------ 0x%08lx \n"
: "", status);
/* Print out the first 10 readings, converting the readings to mV if required */
printf("%s\n", text);
if (mode == ANALOGUE || mode == MIXED) // if we're doing analogue or MIXED
{
printf("Channels are in (%s)\n", (scaleVoltages)
? ("mV")
: ("ADC Counts"));
for (j = 0; j < unit->channelCount; j++)
{
if (unit->channelSettings[j].enabled)
printf("Channel%c:\t", 'A' + j);
}
}
if (mode == DIGITAL || mode == MIXED) // if we're doing digital or MIXED
printf("Digital");
printf("\n");
for (i = offset; i < offset + 10; i++)
{
if (mode == ANALOGUE || mode == MIXED) // if we're doing analogue or MIXED
{
for (j = 0; j < unit->channelCount; j++)
{
if (unit->channelSettings[j].enabled)
{
printf(" %6d ",
scaleVoltages ? adc_to_mv(buffers[j * 2][i],
unit->channelSettings[PS2000A_CHANNEL_A
+ j].range, unit) // If scaleVoltages, print mV value
: buffers[j * 2][i]); // else print ADC Count
}
}
}
if (mode == DIGITAL || mode == MIXED) // if we're doing digital or MIXED
{
digiValue = 0x00ff & digiBuffer[1][i];
digiValue <<= 8;
digiValue |= digiBuffer[0][i];
printf("0x%04X", digiValue);
}
printf("\n");
}
if (mode == ANALOGUE || mode == MIXED) // if we're doing analogue or MIXED
{
sampleCount = min(sampleCount, BUFFER_SIZE);
fopen_s(&fp, BlockFile, "w");
if (fp != NULL)
{
fprintf(fp, "Block Data log\n\n");
fprintf(
fp,
"Results shown for each of the %d Channels are......\n",
unit->channelCount);
fprintf(
fp,
"Maximum Aggregated value ADC Count & mV, Minimum Aggregated value ADC Count & mV\n\n");
fprintf(fp, "Time ");
for (i = 0; i < unit->channelCount; i++)
fprintf(fp, " Ch Max ADC Max mV Min ADC Min mV ");
fprintf(fp, "\n");
for (i = 0; i < sampleCount; i++)
{
fprintf(fp, "%5lld ", g_times[0] + (int64_t) (i
* timeInterval));
for (j = 0; j < unit->channelCount; j++)
{
if (unit->channelSettings[j].enabled)
{
fprintf(
fp,
"Ch%C %5d = %+5dmV, %5d = %+5dmV ",
(char) ('A' + j),
buffers[j * 2][i],
adc_to_mv(
buffers[j * 2][i],
unit->channelSettings[PS2000A_CHANNEL_A
+ j].range, unit),
buffers[j * 2 + 1][i],
adc_to_mv(
buffers[j * 2 + 1][i],
unit->channelSettings[PS2000A_CHANNEL_A
+ j].range, unit));
}
}
fprintf(fp, "\n");
}
}
else
{
printf("Cannot open the file block.txt for writing.\n"
"Please ensure that you have permission to access.\n");
}
}
}
else
{
printf("data collection aborted\n");
_getch();
}
status = ps2000aStop(unit->handle);
printf(status ? "BlockDataHandler:ps2000aStop ------ 0x%08lx \n" : "",
status);
if (fp != NULL)
fclose(fp);
if (mode == ANALOGUE || mode == MIXED) // Only if we allocated these buffers
{
for (i = 0; i < unit->channelCount * 2; i++)
{
free(buffers[i]);
}
}
if (mode == DIGITAL || mode == MIXED) // Only if we allocated these buffers
{
for (i = 0; i < unit->digitalPorts; i++)
{
free(digiBuffer[i]);
}
}
ClearDataBuffers(unit);
}
/****************************************************************************
* Stream Data Handler
* - Used by the two stream data examples - untriggered and triggered
* Inputs:
* - unit - the unit to sample on
* - preTrigger - the number of samples in the pre-trigger phase
* (0 if no trigger has been set)
***************************************************************************/
void StreamDataHandler(UNIT * unit, uint32_t preTrigger, MODE mode)
{
int64_t i, j;
uint32_t sampleCount = BUFFER_SIZE * 10; /* *10 is to make sure buffer large enough */
FILE * fp = NULL;
int16_t * buffers[PS2000A_MAX_CHANNEL_BUFFERS];
int16_t * digiBuffers[PS2000A_MAX_DIGITAL_PORTS];
PICO_STATUS status;
uint32_t sampleInterval;
int32_t index = 0;
int32_t totalSamples;
uint32_t postTrigger;
int16_t autostop;
uint32_t downsampleRatio;
uint32_t triggeredAt = 0;
int32_t bit;
uint16_t portValue, portValueOR, portValueAND;
PS2000A_TIME_UNITS timeUnits;
PS2000A_RATIO_MODE ratioMode;
if (mode == ANALOGUE) // Analogue
{
for (i = 0; i < unit->channelCount; i++)
{
buffers[i * 2] = (int16_t*) malloc(sampleCount * sizeof(int16_t));
buffers[i * 2 + 1] = (int16_t*) malloc(sampleCount * sizeof(int16_t));
status = ps2000aSetDataBuffers(unit->handle, (int16_t) i, buffers[i
* 2], buffers[i * 2 + 1], sampleCount, 0,
PS2000A_RATIO_MODE_AGGREGATE);
printf(
status
? "StreamDataHandler:ps2000aSetDataBuffers(channel %ld) ------ 0x%08lx \n"
: "", i, status);
}
downsampleRatio = 1000;
timeUnits = PS2000A_US;
sampleInterval = 1;
ratioMode = PS2000A_RATIO_MODE_AGGREGATE;
postTrigger = 1000000;
autostop = TRUE;
}
if (mode == AGGREGATED) // (MSO Only) AGGREGATED
{
for (i = 0; i < unit->digitalPorts; i++)
{
digiBuffers[i * 2] = (int16_t*) malloc(sampleCount * sizeof(int16_t));
digiBuffers[i * 2 + 1] = (int16_t*) malloc(sampleCount
* sizeof(int16_t));
status = ps2000aSetDataBuffers(unit->handle, (PS2000A_CHANNEL) (i
+ PS2000A_DIGITAL_PORT0), digiBuffers[i * 2], digiBuffers[i
* 2 + 1], sampleCount, 0, PS2000A_RATIO_MODE_AGGREGATE);
printf(
status
? "StreamDataHandler:ps2000aSetDataBuffer(channel %ld) ------ 0x%08lx \n"
: "", i, status);
}
downsampleRatio = 10;
timeUnits = PS2000A_MS;
sampleInterval = 10;
ratioMode = PS2000A_RATIO_MODE_AGGREGATE;
postTrigger = 10;
autostop = FALSE;
}
if (mode == DIGITAL) // (MSO Only) Digital
{
for (i = 0; i < unit->digitalPorts; i++)
{
digiBuffers[i] = (int16_t*) malloc(sampleCount * sizeof(int16_t));
status = ps2000aSetDataBuffer(unit->handle, (PS2000A_CHANNEL) (i
+ PS2000A_DIGITAL_PORT0), digiBuffers[i], sampleCount, 0,
PS2000A_RATIO_MODE_NONE);
printf(
status
? "StreamDataHandler:ps2000aSetDataBuffer(channel %ld) ------ 0x%08lx \n"
: "", i, status);
}
downsampleRatio = 1;
timeUnits = PS2000A_MS;
sampleInterval = 10;
ratioMode = PS2000A_RATIO_MODE_NONE;
postTrigger = 10;
autostop = FALSE;
}
if (autostop)
{
printf("\nStreaming Data for %lu samples", postTrigger
/ downsampleRatio);
if (preTrigger) // we pass 0 for preTrigger if we're not setting up a trigger
printf(
" after the trigger occurs\nNote: %lu Pre Trigger samples before Trigger arms\n\n",
preTrigger / downsampleRatio);
else
printf("\n\n");
}
else
printf("\nStreaming Data continually\n\n");
g_autoStopped = FALSE;
status = ps2000aRunStreaming(unit->handle, &sampleInterval, timeUnits,
preTrigger, postTrigger - preTrigger, autostop, downsampleRatio,
ratioMode, sampleCount);
printf("Streaming data...Press a key to stop\n");
if (mode == ANALOGUE)
{
fopen_s(&fp, StreamFile, "w");
if (fp != NULL)
{
fprintf(fp, "For each of the %d Channels, results shown are....\n",
unit->channelCount);
fprintf(
fp,
"Maximum Aggregated value ADC Count & mV, Minimum Aggregated value ADC Count & mV\n\n");
for (i = 0; i < unit->channelCount; i++)
fprintf(fp, " Max ADC Max mV Min ADC Min mV");
fprintf(fp, "\n");
}
}
totalSamples = 0;
while (!_kbhit() && !g_autoStopped && !g_overflow)
{
/* Poll until data is received. Until then, GetStreamingLatestValues wont call the callback */
Sleep(100);
g_ready = FALSE;
status = ps2000aGetStreamingLatestValues(unit->handle,
CallBackStreaming, NULL);
index++;
if (g_ready && g_sampleCount > 0) /* can be ready and have no data, if autoStop has fired */
{
if (g_trig)
triggeredAt = totalSamples += g_trigAt; // calculate where the trigger occurred in the total samples collected
totalSamples += g_sampleCount;
printf(
"\nCollected %3li samples, index = %5lu, Total: %6d samples ",
g_sampleCount, g_startIndex, totalSamples);
if (g_trig)
printf("Trig. at index %lu", triggeredAt); // show where trigger occurred
for (i = g_startIndex; i < (int64_t) (g_startIndex + g_sampleCount); i++)
{
if (mode == ANALOGUE)
{
if (fp != NULL)
{
for (j = 0; j < unit->channelCount; j++)
{
if (unit->channelSettings[j].enabled)
{
fprintf(
fp,
"Ch%C %5d = %+5dmV, %5d = %+5dmV ",
(char) ('A' + j),
buffers[j * 2][i],
adc_to_mv(
buffers[j * 2][i],
unit->channelSettings[PS2000A_CHANNEL_A
+ j].range, unit),
buffers[j * 2 + 1][i],
adc_to_mv(
buffers[j * 2 + 1][i],
unit->channelSettings[PS2000A_CHANNEL_A
+ j].range, unit));
}
}
fprintf(fp, "\n");
}
else
printf("Cannot open the file stream.txt for writing.\n");
}
if (mode == DIGITAL)
{
portValue = 0x00ff & digiBuffers[1][i];
portValue <<= 8;
portValue |= 0x00ff & digiBuffers[0][i];
printf("\nIndex=%04lu: Value = 0x%04X = ", i, portValue);
for (bit = 0; bit < 16; bit++)
{
printf((0x8000 >> bit) & portValue ? "1 " : "0 ");
}
}
if (mode == AGGREGATED)
{
portValueOR = 0x00ff & digiBuffers[2][i];
portValueOR <<= 8;
portValueOR |= 0x00ff & digiBuffers[0][i];
portValueAND = 0x00ff & digiBuffers[3][i];
portValueAND <<= 8;
portValueAND |= 0x00ff & digiBuffers[1][i];
printf(
"\nIndex=%04lu: Bitwise OR of last %ld readings = 0x%04X ",
i, downsampleRatio, portValueOR);
printf(
"\nIndex=%04lu: Bitwise AND of last %ld readings = 0x%04X ",
i, downsampleRatio, portValueAND);
}
}
}
}
ps2000aStop(unit->handle);
if (!g_autoStopped)
{
printf("\ndata collection aborted\n");
_getch();
}
if (g_overflow)
{
printf(
"\nStreaming overflow. Not able to keep up with streaming data rate\n");
}
if (fp != NULL)
fclose(fp);
if (mode == ANALOGUE) // Only if we allocated these buffers
{
for (i = 0; i < unit->channelCount * 2; i++)
{
free(buffers[i]);
}
}
if (mode == DIGITAL) // Only if we allocated these buffers
{
for (i = 0; i < unit->digitalPorts; i++)
{
free(digiBuffers[i]);
}
}
if (mode == AGGREGATED) // Only if we allocated these buffers
{
for (i = 0; i < unit->digitalPorts * 2; i++)
{
free(digiBuffers[i]);
}
}
ClearDataBuffers(unit);
}
/****************************************************************************
* SetTrigger
*
* Parameters
* - *unit - pointer to the UNIT structure
* - *channelProperties - pointer to the PS2000A_TRIGGER_CHANNEL_PROPERTIES structure
* - nChannelProperties - the number of PS2000A_TRIGGER_CHANNEL_PROPERTIES elements in channelProperties
* - *triggerConditions - pointer to the PS2000A_TRIGGER_CONDITIONS structure
* - nTriggerConditions - the number of PS2000A_TRIGGER_CONDITIONS elements in triggerConditions
* - *directions - pointer to the TRIGGER_DIRECTIONS structure
* - *pwq - pointer to the pwq (Pulse Width Qualifier) structure
* - delay - Delay time between trigger & first sample
* - auxOutputEnable - Not used
* - autoTriggerMs - timeout period if no trigger occurs
* - *digitalDirections - pointer to the PS2000A_DIGITAL_CHANNEL_DIRECTIONS structure
* - nDigitalDirections - the number of PS2000A_DIGITAL_CHANNEL_DIRECTIONS elements in digitalDirections
*
* Returns - PICO_STATUS - to show success or if an error occurred
*
***************************************************************************/
PICO_STATUS SetTrigger(UNIT * unit,
PS2000A_TRIGGER_CHANNEL_PROPERTIES * channelProperties,
int16_t nChannelProperties,
PS2000A_TRIGGER_CONDITIONS * triggerConditions,
int16_t nTriggerConditions, TRIGGER_DIRECTIONS * directions, PWQ * pwq,
uint32_t delay, int16_t auxOutputEnabled, int64_t autoTriggerMs,
PS2000A_DIGITAL_CHANNEL_DIRECTIONS * digitalDirections,
int16_t nDigitalDirections)
{
PICO_STATUS status;
if ((status = ps2000aSetTriggerChannelProperties(unit->handle,
channelProperties, nChannelProperties, auxOutputEnabled,
autoTriggerMs)) != PICO_OK)
{
printf(
"SetTrigger:ps2000aSetTriggerChannelProperties ------ Ox%8lx \n",
status);
return status;
}
if ((status = ps2000aSetTriggerChannelConditions(unit->handle,
triggerConditions, nTriggerConditions)) != PICO_OK)
{
printf(
"SetTrigger:ps2000aSetTriggerChannelConditions ------ 0x%8lx \n",
status);
return status;
}
if ((status = ps2000aSetTriggerChannelDirections(unit->handle,
directions->channelA, directions->channelB, directions->channelC,
directions->channelD, directions->ext, directions->aux)) != PICO_OK)
{
printf(
"SetTrigger:ps2000aSetTriggerChannelDirections ------ 0x%08lx \n",
status);
return status;
}
if ((status = ps2000aSetTriggerDelay(unit->handle, delay)) != PICO_OK)
{
printf("SetTrigger:ps2000aSetTriggerDelay ------ 0x%08lx \n", status);
return status;
}
if ((status
= ps2000aSetPulseWidthQualifier(unit->handle, pwq->conditions,
pwq->nConditions, pwq->direction, pwq->lower, pwq->upper,
pwq->type)) != PICO_OK)
{
printf("SetTrigger:ps2000aSetPulseWidthQualifier ------ 0x%08lx \n",
status);
return status;
}
if (unit->digitalPorts) // ps2000aSetTriggerDigitalPortProperties function only applies to MSO
{
if ((status = ps2000aSetTriggerDigitalPortProperties(unit->handle,
digitalDirections, nDigitalDirections)) != PICO_OK)
{
printf(
"SetTrigger:ps2000aSetTriggerDigitalPortProperties ------ 0x%08lx \n",
status);
return status;
}
}
return status;
}
/****************************************************************************
* CollectBlockImmediate
* this function demonstrates how to collect a single block of data
* from the unit (start collecting immediately)
****************************************************************************/
void CollectBlockImmediate(UNIT * unit)
{
PWQ pulseWidth;
TRIGGER_DIRECTIONS directions;
memset(&directions, 0, sizeof(TRIGGER_DIRECTIONS));
memset(&pulseWidth, 0, sizeof(PWQ));
printf("Collect block immediate\n");
printf("Data is written to disk file (%s)\n", BlockFile);
printf("Press a key to start...\n");
_getch();
SetDefaults(unit);
/* Trigger disabled */
SetTrigger(unit, NULL, 0, NULL, 0, &directions, &pulseWidth, 0, 0, 0, 0, 0);
BlockDataHandler(unit, "First 10 readings\n", 0, ANALOGUE);
}
/****************************************************************************
* CollectBlockEts
* this function demonstrates how to collect a block of
* data using equivalent time sampling (ETS).
****************************************************************************/
void CollectBlockEts(UNIT * unit)
{
PICO_STATUS status;
int64_t ets_sampletime;
int16_t triggerVoltage = mv_to_adc(1000,
unit->channelSettings[PS2000A_CHANNEL_A].range, unit);
uint32_t delay = 0;
struct tPwq pulseWidth;
struct tTriggerDirections directions;
PS2000A_TRIGGER_CHANNEL_PROPERTIES sourceDetails =
{ triggerVoltage, 256 * 10, triggerVoltage, 256 * 10, PS2000A_CHANNEL_A,
PS2000A_LEVEL };
PS2000A_TRIGGER_CONDITIONS conditions =
{ PS2000A_CONDITION_TRUE, PS2000A_CONDITION_DONT_CARE,
PS2000A_CONDITION_DONT_CARE, PS2000A_CONDITION_DONT_CARE,
PS2000A_CONDITION_DONT_CARE, PS2000A_CONDITION_DONT_CARE,
PS2000A_CONDITION_DONT_CARE, PS2000A_CONDITION_DONT_CARE };
memset(&pulseWidth, 0, sizeof(struct tPwq));
memset(&directions, 0, sizeof(struct tTriggerDirections));
directions.channelA = PS2000A_RISING;
printf("Collect ETS block...\n");
printf("Collects when value rises past %d",
scaleVoltages ? adc_to_mv(sourceDetails.thresholdUpper,
unit->channelSettings[PS2000A_CHANNEL_A].range, unit) // If scaleVoltages, print mV value
: sourceDetails.thresholdUpper); // else print ADC Count
printf(scaleVoltages ? "mV\n" : "ADC Counts\n");
printf("Press a key to start...\n");
_getch();
SetDefaults(unit);
//Trigger enabled
//Rising edge
//Threshold = 1000mV
status = SetTrigger(unit, &sourceDetails, 1, &conditions, 1, &directions,
&pulseWidth, delay, 0, 0, 0, 0);
if ((status = ps2000aSetEts(unit->handle, PS2000A_ETS_FAST, 20, 4,
&ets_sampletime)) != PICO_OK)
printf("CollectBlockEts:ps2000aSetEts ------ 0x%08lx \n", status);
printf("ETS Sample Time is: %ld\n", ets_sampletime);
BlockDataHandler(unit, "Ten readings after trigger\n",
BUFFER_SIZE / 10 - 5, ANALOGUE); // 10% of data is pre-trigger
}
/****************************************************************************
* CollectBlockTriggered
* this function demonstrates how to collect a single block of data from the
* unit, when a trigger event occurs.
****************************************************************************/
void CollectBlockTriggered(UNIT * unit)
{
int16_t triggerVoltage = mv_to_adc(1000,
unit->channelSettings[PS2000A_CHANNEL_A].range, unit);
PS2000A_TRIGGER_CHANNEL_PROPERTIES sourceDetails =
{ triggerVoltage, 256 * 10, triggerVoltage, 256 * 10, PS2000A_CHANNEL_A,
PS2000A_LEVEL };
PS2000A_TRIGGER_CONDITIONS conditions =
{ PS2000A_CONDITION_TRUE, // Channel A
PS2000A_CONDITION_DONT_CARE, // Channel B
PS2000A_CONDITION_DONT_CARE, // Channel C
PS2000A_CONDITION_DONT_CARE, // Channel D
PS2000A_CONDITION_DONT_CARE, // external
PS2000A_CONDITION_DONT_CARE, // aux
PS2000A_CONDITION_DONT_CARE, // PWQ
PS2000A_CONDITION_DONT_CARE }; // digital
TRIGGER_DIRECTIONS directions =
{ PS2000A_RISING, // Channel A
PS2000A_NONE, // Channel B
PS2000A_NONE, // Channel C
PS2000A_NONE, // Channel D
PS2000A_NONE, // ext
PS2000A_NONE }; // aux
PWQ pulseWidth;
memset(&pulseWidth, 0, sizeof(PWQ));
printf("Collect block triggered\n");
printf("Data is written to disk file (%s)\n", BlockFile);
printf("Collects when value rises past %d",
scaleVoltages ? adc_to_mv(sourceDetails.thresholdUpper,
unit->channelSettings[PS2000A_CHANNEL_A].range, unit) // If scaleVoltages, print mV value
: sourceDetails.thresholdUpper); // else print ADC Count
printf(scaleVoltages ? "mV\n" : "ADC Counts\n");
printf("Press a key to start...\n");
_getch();
SetDefaults(unit);
/* Trigger enabled
* Rising edge
* Threshold = 1000mV */
SetTrigger(unit, &sourceDetails, 1, &conditions, 1, &directions,
&pulseWidth, 0, 0, 0, 0, 0);
BlockDataHandler(unit, "Ten readings after trigger\n", 0, ANALOGUE);
}
/****************************************************************************
* CollectRapidBlock
* this function demonstrates how to collect a set of captures using
* rapid block mode.
****************************************************************************/
void CollectRapidBlock(UNIT * unit)
{
uint16_t nCaptures;
int64_t nMaxSamples;
uint32_t nSamples = 1000;
int64_t timeIndisposed;
int16_t capture, channel;
int16_t ***rapidBuffers;
int16_t *overflow;
PICO_STATUS status;
int16_t i;
uint32_t nCompletedCaptures;
int16_t triggerVoltage = mv_to_adc(100,
unit->channelSettings[PS2000A_CHANNEL_A].range, unit);
struct tPS2000ATriggerChannelProperties sourceDetails =
{ triggerVoltage, 256 * 10, triggerVoltage, 256 * 10, PS2000A_CHANNEL_A,
PS2000A_LEVEL };
struct tPS2000ATriggerConditions conditions =
{ PS2000A_CONDITION_TRUE, // Channel A
PS2000A_CONDITION_DONT_CARE, // Channel B
PS2000A_CONDITION_DONT_CARE, // Channel C
PS2000A_CONDITION_DONT_CARE, // Channel D
PS2000A_CONDITION_DONT_CARE, // external
PS2000A_CONDITION_DONT_CARE, // aux
PS2000A_CONDITION_DONT_CARE, // PWQ
PS2000A_CONDITION_DONT_CARE }; // digital
struct tPwq pulseWidth;
struct tTriggerDirections directions =
{ PS2000A_RISING, // Channel A
PS2000A_NONE, // Channel B
PS2000A_NONE, // Channel C
PS2000A_NONE, // Channel D
PS2000A_NONE, // ext
PS2000A_NONE }; // aux
memset(&pulseWidth, 0, sizeof(struct tPwq));
printf("Collect rapid block triggered...\n");
printf("Collects when value rises past %d",
scaleVoltages ? adc_to_mv(sourceDetails.thresholdUpper,
unit->channelSettings[PS2000A_CHANNEL_A].range, unit) // If scaleVoltages, print mV value
: sourceDetails.thresholdUpper); // else print ADC Count
printf(scaleVoltages ? "mV\n" : "ADC Counts\n");
printf("Press any key to abort\n");
SetDefaults(unit);
// Trigger enabled
SetTrigger(unit, &sourceDetails, 1, &conditions, 1, &directions,
&pulseWidth, 0, 0, 0, 0, 0);
//Set the number of captures
nCaptures = 10;
//Segment the memory
status = ps2000aMemorySegments(unit->handle, nCaptures, &nMaxSamples);
//Set the number of captures
status = ps2000aSetNoOfCaptures(unit->handle, nCaptures);
//Run
timebase = 160; //1 MS/s
status = ps2000aRunBlock(unit->handle, 0, nSamples, timebase, 1,
&timeIndisposed, 0, CallBackBlock, NULL);
//Wait until data ready
g_ready = 0;
while (!g_ready && !_kbhit())
{
Sleep(0);
}
if (!g_ready)
{
_getch();
status = ps2000aStop(unit->handle);
status = ps2000aGetNoOfCaptures(unit->handle, &nCompletedCaptures);
printf("Rapid capture aborted. %lu complete blocks were captured\n",
nCompletedCaptures);
printf("\nPress any key...\n\n");
_getch();
if (nCompletedCaptures == 0)
return;
//Only display the blocks that were captured
nCaptures = (uint16_t) nCompletedCaptures;
}
//Allocate memory
rapidBuffers = calloc(unit->channelCount, sizeof(int16_t*));
overflow = calloc(unit->channelCount * nCaptures, sizeof(int16_t));
for (channel = 0; channel < unit->channelCount; channel++)
{
rapidBuffers[channel] = calloc(nCaptures, sizeof(int16_t*));
}
for (channel = 0; channel < unit->channelCount; channel++)
{
if (unit->channelSettings[channel].enabled)
{
for (capture = 0; capture < nCaptures; capture++)
{
rapidBuffers[channel][capture]
= calloc(nSamples, sizeof(int16_t));
}
}
}
for (channel = 0; channel < unit->channelCount; channel++)
{
if (unit->channelSettings[channel].enabled)
{
for (capture = 0; capture < nCaptures; capture++)
{
status = ps2000aSetDataBuffer(unit->handle, channel,
rapidBuffers[channel][capture], nSamples, capture,
PS2000A_RATIO_MODE_NONE);
}
}
}
//Get data
status = ps2000aGetValuesBulk(unit->handle, &nSamples, 0, nCaptures - 1, 1,
PS2000A_RATIO_MODE_NONE, overflow);
//Stop
status = ps2000aStop(unit->handle);
//print first 10 samples from each capture
for (capture = 0; capture < nCaptures; capture++)
{
printf("\nCapture %d\n", capture + 1);
for (channel = 0; channel < unit->channelCount; channel++)
{
printf("Channel %c\t", 'A' + channel);
}
printf("\n");
for (i = 0; i < 10; i++)
{
for (channel = 0; channel < unit->channelCount; channel++)
{
if (unit->channelSettings[channel].enabled)
{
printf("%d\t\t", rapidBuffers[channel][capture][i]);
}
}
printf("\n");
}
}
//Free memory
free(overflow);
for (channel = 0; channel < unit->channelCount; channel++)
{
if (unit->channelSettings[channel].enabled)
{
for (capture = 0; capture < nCaptures; capture++)
{
free(rapidBuffers[channel][capture]);
}
}
}
for (channel = 0; channel < unit->channelCount; channel++)
{
free(rapidBuffers[channel]);
}
free(rapidBuffers);
}
/****************************************************************************
* Initialise unit' structure with Variant specific defaults
****************************************************************************/
void set_info(UNIT * unit)
{
int16_t r = 0;
char line [8] = {0};
int32_t variant;
PICO_STATUS status = PICO_OK;
if (unit->handle)
{
// info = 3 - PICO_VARIANT_INFO
ps2000aGetUnitInfo(unit->handle, line, sizeof (line), &r, 3);
variant = atoi(line);
memcpy(&(unit->modelString),line,sizeof(unit->modelString)==7?7:sizeof(unit->modelString));
//To identify variants.....
if (strlen(line) == 5) // A variant unit
{
line[4] = toupper(line[4]);
if (line[4] == 'A') // i.e 2207A -> 0xA207
variant += 0x9968;
} else
variant += 0x1968; // 2206 -> 0x2206
if (strlen(line) == 7)
{
line[4] = toupper(line[4]);
line[5] = toupper(line[5]);
line[6] = toupper(line[6]);
if(strcmp(line+4, "MSO") == 0)
variant += 0xC000; // 2205MSO -> 0xE205
}
// info = 4 - PICO_BATCH_AND_SERIAL
ps2000aGetUnitInfo(unit->handle, unit->serial, sizeof (unit->serial), &r, 4);
}
switch (variant)
{
case MODEL_PS2205MSO:
unit->model = variant;
unit->signalGenerator = TRUE;
unit->ETS = FALSE;
unit->firstRange = PS2000A_50MV;
unit->lastRange = PS2000A_20V;
unit->channelCount = DUAL_SCOPE;
unit->digitalPorts = 2;
break;
case MODEL_PS2206:
unit->model = variant;
unit->signalGenerator = TRUE;
unit->ETS = FALSE;
unit->firstRange = PS2000A_50MV;
unit->lastRange = PS2000A_20V;
unit->channelCount = DUAL_SCOPE;
unit->digitalPorts = 0;
break;
case MODEL_PS2207:
unit->model = variant;
unit->signalGenerator = TRUE;
unit->ETS = FALSE;
unit->firstRange = PS2000A_50MV;
unit->lastRange = PS2000A_20V;
unit->channelCount = DUAL_SCOPE;
unit->digitalPorts = 0;
break;
case MODEL_PS2208:
unit->model = variant;
unit->signalGenerator = TRUE;
unit->ETS = TRUE;
unit->firstRange = PS2000A_50MV;
unit->lastRange = PS2000A_20V;
unit->channelCount = DUAL_SCOPE;
unit->digitalPorts = 0;
break;
case MODEL_PS2206A:
unit->model = variant;
unit->signalGenerator = TRUE;
unit->ETS = FALSE;
unit->firstRange = PS2000A_50MV;
unit->lastRange = PS2000A_20V;
unit->channelCount = DUAL_SCOPE;
unit->digitalPorts = 0;
break;
case MODEL_PS2207A:
unit->model = variant;
unit->signalGenerator = TRUE;
unit->ETS = FALSE;
unit->firstRange = PS2000A_50MV;
unit->lastRange = PS2000A_20V;
unit->channelCount = DUAL_SCOPE;
unit->digitalPorts = 0;
break;
case MODEL_PS2208A:
unit->model = variant;
unit->signalGenerator = TRUE;
unit->ETS = TRUE;
unit->firstRange = PS2000A_50MV;
unit->lastRange = PS2000A_20V;
unit->channelCount = DUAL_SCOPE;
unit->digitalPorts = 0;
break;
default:
break;
}
}
/****************************************************************************
* Select input voltage ranges for channels
****************************************************************************/
void SetVoltages(UNIT * unit)
{
int32_t i, ch;
int32_t count = 0;
/* See what ranges are available... */
for (i = unit->firstRange; i <= unit->lastRange; i++)
{
printf("%d -> %d mV\n", i, inputRanges[i]);
}
do
{
/* Ask the user to select a range */
printf("Specify voltage range (%d..%d)\n", unit->firstRange,
unit->lastRange);
printf("99 - switches channel off\n");
for (ch = 0; ch < unit->channelCount; ch++)
{
printf("\n");
do
{
printf("Channel %c: ", 'A' + ch);
fflush(stdin);
scanf_s("%hd", &unit->channelSettings[ch].range);
} while (unit->channelSettings[ch].range != 99
&& (unit->channelSettings[ch].range < unit->firstRange
|| unit->channelSettings[ch].range
> unit->lastRange));
if (unit->channelSettings[ch].range != 99)
{
printf(" - %d mV\n",
inputRanges[unit->channelSettings[ch].range]);
unit->channelSettings[ch].enabled = TRUE;
count++;
}
else
{
printf("Channel Switched off\n");
unit->channelSettings[ch].enabled = FALSE;
unit->channelSettings[ch].range = PS2000A_MAX_RANGES - 1;
}
}
printf(count == 0
? "\n** At least 1 channel must be enabled **\n\n"
: "");
} while (count == 0); // must have at least one channel enabled
SetDefaults(unit); // Put these changes into effect
}
/****************************************************************************
*
* Select timebase, set oversample to on and time units as nano seconds
*
****************************************************************************/
void SetTimebase(UNIT *unit)
{
int64_t timeInterval;
int64_t maxSamples;
printf("Specify desired timebase: ");
fflush(stdin);
scanf_s("%lu", &timebase);
while (ps2000aGetTimebase(unit->handle, timebase, BUFFER_SIZE,
&timeInterval, 1, &maxSamples, 0))
{
timebase++; // Increase timebase if the one specified can't be used.
}
printf("Timebase %lu used = %ld ns\n", timebase, timeInterval);
oversample = TRUE;
}
/****************************************************************************
* Sets the signal generator
* - allows user to set frequency and waveform
* - allows for custom waveform (values -32768..32767) of up to 8192 samples int64_t
***************************************************************************/
void SetSignalGenerator(UNIT *unit)
{
PICO_STATUS status;
int16_t waveform;
int64_t frequency;
char fileName[128];
FILE * fp = NULL;
int16_t arbitraryWaveform[8192];
int16_t waveformSize = 0;
uint32_t pkpk = 1000000;
int64_t offset = 0;
char ch;
int16_t choice;
memset(&arbitraryWaveform, 0, 8192);
while (_kbhit()) // use up keypress
_getch();
do
{
printf("\nSignal Generator\n================\n");
printf("0 - SINE 1 - SQUARE\n");
printf("2 - TRIANGLE 3 - DC VOLTAGE\n");
printf("4 - RAMP UP 5 - RAMP DOWN\n");
printf("6 - SINC 7 - GAUSSIAN\n");
printf("8 - HALF SINE A - AWG WAVEFORM\n");
printf("F - SigGen Off\n\n");
ch = _getch();
if (ch >= '0' && ch <= '9')
choice = ch - '0';
else
ch = toupper(ch);
} while (ch != 'A' && ch != 'F' && (ch < '0' || ch > '8'));
if (ch == 'F') // If we're going to turn off siggen
{
printf("Signal generator Off\n");
waveform = 8; // DC Voltage
pkpk = 0; // 0V
waveformSize = 0;
}
else if (ch == 'A') // Set the AWG
{
waveformSize = 0;
printf("Select a waveform file to load: ");
scanf_s("%s", fileName, 128);
if (fopen_s(&fp, fileName, "r") == 0)
{ // Having opened file, read in data - one number per line (at most 8192 lines), with values in (-32768 to 32767)
while (EOF != fscanf_s(fp, "%hi",
(arbitraryWaveform + waveformSize)) && waveformSize++
< 8191)
;
fclose(fp);
printf("File successfully loaded\n");
}
else
{
printf("Invalid filename\n");
return;
}
}
else // Set one of the built in waveforms
{
switch (choice)
{
case 0:
waveform = PS2000A_SINE;
break;
case 1:
waveform = PS2000A_SQUARE;
break;
case 2:
waveform = PS2000A_TRIANGLE;
break;
case 3:
waveform = PS2000A_DC_VOLTAGE;
do
{
printf("\nEnter offset in uV: (0 to 2500000)\n"); // Ask user to enter DC offset level;
scanf_s("%llu", &offset);
} while (offset < 0 || offset > 10000000);
break;
case 4:
waveform = PS2000A_RAMP_UP;
break;
case 5:
waveform = PS2000A_RAMP_DOWN;
break;
case 6:
waveform = PS2000A_SINC;
break;
case 7:
waveform = PS2000A_GAUSSIAN;
break;
case 8:
waveform = PS2000A_HALF_SINE;
break;
default:
waveform = PS2000A_SINE;
break;
}
}
if (waveform < 8 || ch == 'A') // Find out frequency if required
{
do
{
printf("\nEnter frequency in Hz: (1 to 1000000)\n"); // Ask user to enter signal frequency;
scanf_s("%lu", &frequency);
} while (frequency <= 0 || frequency > 1000000);
}
if (waveformSize > 0)
{
double delta = ((1.0 * frequency * waveformSize) / 8192.0)
* 4294967296.0 * 5e-8; // delta >= 10
status = ps2000aSetSigGenArbitrary(unit->handle, 0, 1000000,
(uint32_t) delta, (uint32_t) delta, 0, 0,
arbitraryWaveform, waveformSize, 0, 0, PS2000A_SINGLE, 0, 0,
PS2000A_SIGGEN_RISING, PS2000A_SIGGEN_NONE, 0);
printf(status
? "\nps2000aSetSigGenArbitrary: Status Error 0x%x \n"
: "", (uint32_t) status); // If status != 0, show the error
}
else
{
status
= ps2000aSetSigGenBuiltIn(unit->handle, offset, pkpk, waveform,
(float) frequency, (float) frequency, 0, 0, 0, 0, 0, 0,
0, 0, 0);
printf(status ? "\nps2000aSetSigGenBuiltIn: Status Error 0x%x \n" : "",
(uint32_t) status); // If status != 0, show the error
}
}
/****************************************************************************
* CollectStreamingImmediate
* this function demonstrates how to collect a stream of data
* from the unit (start collecting immediately)
***************************************************************************/
void CollectStreamingImmediate(UNIT * unit)
{
struct tPwq pulseWidth;
struct tTriggerDirections directions;
memset(&pulseWidth, 0, sizeof(struct tPwq));
memset(&directions, 0, sizeof(struct tTriggerDirections));
SetDefaults(unit);
printf("Collect streaming...\n");
printf("Data is written to disk file (%s)\n", StreamFile);
printf("Press a key to start...\n");
_getch();
/* Trigger disabled */
SetTrigger(unit, NULL, 0, NULL, 0, &directions, &pulseWidth, 0, 0, 0, 0, 0);
StreamDataHandler(unit, 0, ANALOGUE);
}
/****************************************************************************
* CollectStreamingTriggered
* this function demonstrates how to collect a stream of data
* from the unit (start collecting on trigger)
***************************************************************************/
void CollectStreamingTriggered(UNIT * unit)
{
int16_t triggerVoltage = mv_to_adc(1000,
unit->channelSettings[PS2000A_CHANNEL_A].range, unit); // ChannelInfo stores ADC counts
struct tPwq pulseWidth;
struct tPS2000ATriggerChannelProperties sourceDetails =
{ triggerVoltage, 256 * 10, triggerVoltage, 256 * 10, PS2000A_CHANNEL_A,
PS2000A_LEVEL };
struct tPS2000ATriggerConditions conditions =
{ PS2000A_CONDITION_TRUE, // Channel A
PS2000A_CONDITION_DONT_CARE, // Channel B
PS2000A_CONDITION_DONT_CARE, // Channel C
PS2000A_CONDITION_DONT_CARE, // Channel D
PS2000A_CONDITION_DONT_CARE, // Exteranl
PS2000A_CONDITION_DONT_CARE, // aux
PS2000A_CONDITION_DONT_CARE, // PWQ
PS2000A_CONDITION_DONT_CARE }; // digital
struct tTriggerDirections directions =
{ PS2000A_RISING, // Channel A
PS2000A_NONE, // Channel B
PS2000A_NONE, // Channel C
PS2000A_NONE, // Channel D
PS2000A_NONE, // External
PS2000A_NONE }; // Aux
memset(&pulseWidth, 0, sizeof(struct tPwq));
printf("Collect streaming triggered...\n");
printf("Data is written to disk file (%s)\n", StreamFile);
printf("Indicates when value rises past %d",
scaleVoltages ? adc_to_mv(sourceDetails.thresholdUpper,
unit->channelSettings[PS2000A_CHANNEL_A].range, unit) // If scaleVoltages, print mV value
: sourceDetails.thresholdUpper); // else print ADC Count
printf(scaleVoltages ? "mV\n" : "ADC Counts\n");
printf("Press a key to start...\n");
_getch();
SetDefaults(unit);
/* Trigger enabled
* Rising edge
* Threshold = 1000mV */
SetTrigger(unit, &sourceDetails, 1, &conditions, 1, &directions,
&pulseWidth, 0, 0, 0, 0, 0);
StreamDataHandler(unit, 100000, ANALOGUE);
}
/****************************************************************************
* OpenDevice
* Parameters
* - unit pointer to the UNIT structure, where the handle will be stored
* - serial pointer to the char array containing serial number
*
* Returns
* - PICO_STATUS to indicate success, or if an error occurred
***************************************************************************/
PICO_STATUS OpenDevice(UNIT *unit, char *serial)
{
PICO_STATUS status;
if (serial == NULL)
status = ps2000aOpenUnit(&unit->handle, NULL);
else
status = ps2000aOpenUnit(&unit->handle, serial);
unit->openStatus = status;
unit->complete = 1;
return status;
}
/****************************************************************************
* HandleDevice
* Parameters
* - unit pointer to the UNIT structure, where the handle will be stored
*
* Returns
* - PICO_STATUS to indicate success, or if an error occurred
***************************************************************************/
PICO_STATUS HandleDevice(UNIT * unit)
{
int16_t value = 0;
int32_t i;
struct tPwq pulseWidth;
struct tTriggerDirections directions;
printf("Handle: %d\n", unit->handle);
if (unit->openStatus != PICO_OK)
{
printf("Unable to open device\n");
printf("Error code : 0x%08x\n", (uint32_t)unit->openStatus);
while(!_kbhit());
exit(99); // exit program
}
printf("Device opened successfully, cycle %d\n\n", ++cycles);
// setup device info - unless it's set already
if (unit->model == MODEL_NONE)
set_info(unit);
timebase = 1;
PICO_STATUS status = ps2000aMaximumValue(unit->handle, &value);
unit->maxValue = value;
for (i = 0; i < unit->channelCount; i++)
{
unit->channelSettings[i].enabled = TRUE;
unit->channelSettings[i].DCcoupled = TRUE;
unit->channelSettings[i].range = PS2000A_5V;
}
memset(&directions, 0, sizeof(struct tTriggerDirections));
memset(&pulseWidth, 0, sizeof(struct tPwq));
SetDefaults(unit);
/* Trigger disabled */
SetTrigger(unit, NULL, 0, NULL, 0, &directions, &pulseWidth, 0, 0, 0, 0, 0);
return status;
}
/****************************************************************************
* DisplaySettings
* Displays information about the user configurable settings in this example
* Parameters
* - unit pointer to the UNIT structure
*
* Returns none
***************************************************************************/
void DisplaySettings(UNIT *unit)
{
int32_t ch;
int32_t voltage;
printf("\n\nReadings will be scaled in (%s)\n",
(scaleVoltages) ? ("mV") : ("ADC counts"));
for (ch = 0; ch < unit->channelCount; ch++)
{
if (!(unit->channelSettings[ch].enabled))
printf("Channel %c Voltage Range = Off\n", 'A' + ch);
else
{
voltage = inputRanges[unit->channelSettings[ch].range];
printf("Channel %c Voltage Range = ", 'A' + ch);
if (voltage < 1000)
printf("%dmV\n", voltage);
else
printf("%dV\n", voltage / 1000);
}
}
printf("\n");
}
/****************************************************************************
* ANDAnalogueDigital
* This function shows how to collect a block of data from the analogue
* ports and the digital ports at the same time, triggering when the
* digital conditions AND the analogue conditions are met
*
* Returns none
***************************************************************************/
void ANDAnalogueDigitalTriggered(UNIT * unit)
{
int16_t triggerVoltage = mv_to_adc(1000,
unit->channelSettings[PS2000A_CHANNEL_A].range, unit);
PS2000A_TRIGGER_CHANNEL_PROPERTIES sourceDetails =
{ triggerVoltage, // thresholdUpper
256 * 10, // thresholdUpper Hysteresis
triggerVoltage, // thresholdLower
256 * 10, // thresholdLower Hysteresis
PS2000A_CHANNEL_A, // channel
PS2000A_LEVEL }; // mode
PS2000A_TRIGGER_CONDITIONS conditions =
{ PS2000A_CONDITION_TRUE, // Channel A
PS2000A_CONDITION_DONT_CARE, // Channel B
PS2000A_CONDITION_DONT_CARE, // Channel C
PS2000A_CONDITION_DONT_CARE, // Channel D
PS2000A_CONDITION_DONT_CARE, // external
PS2000A_CONDITION_DONT_CARE, // aux
PS2000A_CONDITION_DONT_CARE, // pwq
PS2000A_CONDITION_TRUE }; // digital
TRIGGER_DIRECTIONS directions =
{ PS2000A_ABOVE, // Channel A
PS2000A_NONE, // Channel B
PS2000A_NONE, // Channel C
PS2000A_NONE, // Channel D
PS2000A_NONE, // external
PS2000A_NONE }; // aux
PS2000A_DIGITAL_CHANNEL_DIRECTIONS digDirections[2]; // Array size can be up to 16, an entry for each digital bit
PWQ pulseWidth;
memset(&pulseWidth, 0, sizeof(PWQ));
// Set the Digital trigger so it will trigger when bit 0 is Rising and bit 4 is HIGH
// All non-declared bits are taken as PS2000A_DIGITAL_DONT_CARE
//
digDirections[0].channel = PS2000A_DIGITAL_CHANNEL_0;
digDirections[0].direction = PS2000A_DIGITAL_DIRECTION_RISING;
digDirections[1].channel = PS2000A_DIGITAL_CHANNEL_4;
digDirections[1].direction = PS2000A_DIGITAL_DIRECTION_HIGH;
printf("\nCombination Block Triggered\n");
printf("Collects when value is above %d",
scaleVoltages ? adc_to_mv(sourceDetails.thresholdUpper,
unit->channelSettings[PS2000A_CHANNEL_A].range, unit) // If scaleVoltages, print mV value
: sourceDetails.thresholdUpper); // else print ADC Count
printf(scaleVoltages ? "mV\n" : "ADC Counts\n");
printf("AND \n");
printf("Digital Channel 0 --- Rising\n");
printf("Digital Channel 4 --- High\n");
printf("Other Digital Channels - Don't Care\n");
printf("Press a key to start...\n");
_getch();
SetDefaults(unit); // Enable Analogue channels.
/* Trigger enabled
* Rising edge
* Threshold = 100mV */
if (SetTrigger(unit, &sourceDetails, 1, &conditions, 1, &directions,
&pulseWidth, 0, 0, 0, digDirections, 2) == PICO_OK)
{
BlockDataHandler(unit, "First 10 readings\n", 0, MIXED);
}
DisableAnalogue(unit); // Disable Analogue ports when finished;
}
/****************************************************************************
* ORAnalogueDigital
* This function shows how to collect a block of data from the analogue
* ports and the digital ports at the same time, triggering when either the
* digital conditions OR the analogue conditions are met
*
* Returns none
***************************************************************************/
void ORAnalogueDigitalTriggered(UNIT * unit)
{
int16_t triggerVoltage = mv_to_adc(1000,
unit->channelSettings[PS2000A_CHANNEL_A].range, unit);
PS2000A_TRIGGER_CHANNEL_PROPERTIES sourceDetails =
{ triggerVoltage, // thresholdUpper
256 * 10, // thresholdUpper Hysteresis
triggerVoltage, // thresholdLower
256 * 10, // thresholdLower Hysteresis
PS2000A_CHANNEL_A, // channel
PS2000A_LEVEL }; // mode
PS2000A_TRIGGER_CONDITIONS conditions[2];
TRIGGER_DIRECTIONS directions =
{ PS2000A_RISING, // Channel A
PS2000A_NONE, // Channel B
PS2000A_NONE, // Channel C
PS2000A_NONE, // Channel D
PS2000A_NONE, // external
PS2000A_NONE }; // aux
PS2000A_DIGITAL_CHANNEL_DIRECTIONS digDirections[2]; // Array size can be up to 16, an entry for each digital bit
PWQ pulseWidth;
conditions[0].channelA = PS2000A_CONDITION_TRUE; // Channel A
conditions[0].channelB = PS2000A_CONDITION_DONT_CARE; // Channel B
conditions[0].channelC = PS2000A_CONDITION_DONT_CARE; // Channel C
conditions[0].channelD = PS2000A_CONDITION_DONT_CARE; // Channel D
conditions[0].external = PS2000A_CONDITION_DONT_CARE; // external
conditions[0].aux = PS2000A_CONDITION_DONT_CARE; // aux
conditions[0].pulseWidthQualifier = PS2000A_CONDITION_DONT_CARE; // pwq
conditions[0].digital = PS2000A_CONDITION_DONT_CARE; // digital
conditions[1].channelA = PS2000A_CONDITION_DONT_CARE; // Channel A
conditions[1].channelB = PS2000A_CONDITION_DONT_CARE; // Channel B
conditions[1].channelC = PS2000A_CONDITION_DONT_CARE; // Channel C
conditions[1].channelD = PS2000A_CONDITION_DONT_CARE; // Channel D
conditions[1].external = PS2000A_CONDITION_DONT_CARE; // external
conditions[1].aux = PS2000A_CONDITION_DONT_CARE; // aux
conditions[1].pulseWidthQualifier = PS2000A_CONDITION_DONT_CARE; // pwq
conditions[1].digital = PS2000A_CONDITION_TRUE; // digital
memset(&pulseWidth, 0, sizeof(PWQ));
// Set the Digital trigger so it will trigger when bit 0 is Rising and bit 4 is HIGH
// All non-declared bits are taken as PS2000A_DIGITAL_DONT_CARE
//
digDirections[0].channel = PS2000A_DIGITAL_CHANNEL_0;
digDirections[0].direction = PS2000A_DIGITAL_DIRECTION_RISING;
digDirections[1].channel = PS2000A_DIGITAL_CHANNEL_4;
digDirections[1].direction = PS2000A_DIGITAL_DIRECTION_HIGH;
printf("\nCombination Block Triggered\n");
printf("Collects when value rises past %d",
scaleVoltages ? adc_to_mv(sourceDetails.thresholdUpper,
unit->channelSettings[PS2000A_CHANNEL_A].range, unit) // If scaleVoltages, print mV value
: sourceDetails.thresholdUpper); // else print ADC Count
printf(scaleVoltages ? "mV\n" : "ADC Counts\n");
printf("OR \n");
printf("Digital Channel 0 --- Rising\n");
printf("Digital Channel 4 --- High\n");
printf("Other Digital Channels - Don't Care\n");
printf("Press a key to start...\n");
_getch();
SetDefaults(unit); // enable analogue ports
/* Trigger enabled
* Rising edge
* Threshold = 1000mV */
if (SetTrigger(unit, &sourceDetails, 1, conditions, 2, &directions,
&pulseWidth, 0, 0, 0, digDirections, 2) == PICO_OK)
{
BlockDataHandler(unit, "First 10 readings\n", 0, MIXED);
}
DisableAnalogue(unit); // Disable Analogue ports when finished;
}
/****************************************************************************
* DigitalBlockTriggered
* This function shows how to collect a block of data from the digital ports
* with triggering enabled
*
* Returns none
***************************************************************************/
void DigitalBlockTriggered(UNIT * unit)
{
PWQ pulseWidth;
TRIGGER_DIRECTIONS directions;
PS2000A_DIGITAL_CHANNEL_DIRECTIONS digDirections[2]; // Array size can be up to 16, an entry for each digital bit
PS2000A_TRIGGER_CONDITIONS conditions =
{ PS2000A_CONDITION_DONT_CARE, // Channel A
PS2000A_CONDITION_DONT_CARE, // Channel B
PS2000A_CONDITION_DONT_CARE, // Channel C
PS2000A_CONDITION_DONT_CARE, // Channel D
PS2000A_CONDITION_DONT_CARE, // external
PS2000A_CONDITION_DONT_CARE, // aux
PS2000A_CONDITION_DONT_CARE, // pwq
PS2000A_CONDITION_TRUE }; // digital
printf("\nDigital Block Triggered\n");
memset(&directions, 0, sizeof(TRIGGER_DIRECTIONS));
memset(&pulseWidth, 0, sizeof(PWQ));
printf("Collect block of data when the trigger occurs...\n");
printf("Digital Channel 0 --- Rising\n");
printf("Digital Channel 4 --- High\n");
printf("Other Digital Channels - Don't Care\n");
digDirections[0].channel = PS2000A_DIGITAL_CHANNEL_0;
digDirections[0].direction = PS2000A_DIGITAL_DIRECTION_RISING;
digDirections[1].channel = PS2000A_DIGITAL_CHANNEL_4;
digDirections[1].direction = PS2000A_DIGITAL_DIRECTION_HIGH;
if (SetTrigger(unit, NULL, 0, &conditions, 1, &directions, &pulseWidth, 0,
0, 0, digDirections, 2) == PICO_OK)
{
printf("Press a key to start...\n");
_getch();
BlockDataHandler(unit, "First 10 readings\n", 0, DIGITAL);
}
}
/****************************************************************************
* DigitalBlockImmediate
* This function shows how to collect a block of data from the digital ports
* with triggering disabled
*
* Returns none
***************************************************************************/
void DigitalBlockImmediate(UNIT *unit)
{
PWQ pulseWidth;
TRIGGER_DIRECTIONS directions;
PS2000A_DIGITAL_CHANNEL_DIRECTIONS digDirections;
printf("\nDigital Block Immediate\n");
memset(&directions, 0, sizeof(TRIGGER_DIRECTIONS));
memset(&pulseWidth, 0, sizeof(PWQ));
memset(&digDirections, 0, sizeof(PS2000A_DIGITAL_CHANNEL_DIRECTIONS));
SetTrigger(unit, NULL, 0, NULL, 0, &directions, &pulseWidth, 0, 0, 0,
&digDirections, 0);
printf("Press a key to start...\n");
_getch();
BlockDataHandler(unit, "First 10 readings\n", 0, DIGITAL);
}
/****************************************************************************
* DigitalStreamingAggregated
* this function demonstrates how to collect a stream of Aggregated data
* from the unit's Digital inputs (start collecting immediately)
***************************************************************************/
void DigitalStreamingAggregated(UNIT * unit)
{
struct tPwq pulseWidth;
struct tTriggerDirections directions;
memset(&pulseWidth, 0, sizeof(struct tPwq));
memset(&directions, 0, sizeof(struct tTriggerDirections));
printf("Digital streaming with Aggregation...\n");
printf("Press a key to start...\n");
_getch();
/* Trigger disabled */
SetTrigger(unit, NULL, 0, NULL, 0, &directions, &pulseWidth, 0, 0, 0, 0, 0);
StreamDataHandler(unit, 0, AGGREGATED);
}
/****************************************************************************
* DigitalStreamingImmediate
* this function demonstrates how to collect a stream of data
* from the unit's Digital inputs (start collecting immediately)
***************************************************************************/
void DigitalStreamingImmediate(UNIT * unit)
{
struct tPwq pulseWidth;
struct tTriggerDirections directions;
memset(&pulseWidth, 0, sizeof(struct tPwq));
memset(&directions, 0, sizeof(struct tTriggerDirections));
printf("Digital streaming...\n");
printf("Press a key to start...\n");
_getch();
/* Trigger disabled */
SetTrigger(unit, NULL, 0, NULL, 0, &directions, &pulseWidth, 0, 0, 0, 0, 0);
StreamDataHandler(unit, 0, DIGITAL);
}
/****************************************************************************
* DigitalMenu
* Displays digital examples available
* Parameters
* - unit pointer to the UNIT structure
*
* Returns none
***************************************************************************/
void DigitalMenu(UNIT *unit)
{
char ch;
int16_t enabled = TRUE;
int16_t disabled = !enabled;
DisableAnalogue(unit); // Disable Analogue ports;
SetDigitals(unit, enabled); // Enable Digital ports
ch = ' ';
while (ch != 'X')
{
printf("\n");
printf("\nDigital Port Menu\n\n");
printf("B - Digital Block Immediate\n");
printf("T - Digital Block Triggered\n");
printf("A - Analogue 'AND' Digital Triggered Block\n");
printf("O - Analogue 'OR' Digital Triggered Block\n");
printf("S - Digital Streaming Mode\n");
printf("V - Digital Streaming Aggregated\n");
printf("X - Return to previous menu\n\n");
printf("Operation:");
ch = toupper(_getch());
printf("\n\n");
switch (ch)
{
case 'B':
DigitalBlockImmediate(unit);
break;
case 'T':
DigitalBlockTriggered(unit);
break;
case 'A':
ANDAnalogueDigitalTriggered(unit);
break;
case 'O':
ORAnalogueDigitalTriggered(unit);
break;
case 'S':
DigitalStreamingImmediate(unit);
break;
case 'V':
DigitalStreamingAggregated(unit);
break;
}
}
SetDigitals(unit, disabled); // Disable Digital ports when finished
}
/****************************************************************************
* MainMenu
* Controls default functions of the seelected unit
* Parameters
* - unit pointer to the UNIT structure
*
* Returns none
***************************************************************************/
void MainMenu(UNIT *unit)
{
char ch = '.';
while (ch != 'X')
{
DisplaySettings(unit);
printf("\n");
printf(
"B - Immediate block V - Set voltages\n");
printf(
"T - Triggered block I - Set timebase\n");
printf(
"E - Collect a block of data using ETS A - ADC counts/mV\n");
printf(
"R - Collect set of rapid captures G - Signal generator\n");
printf("S - Immediate streaming\n");
printf("W - Triggered streaming\n");
printf(unit->digitalPorts ? "D - Digital Ports menu\n" : "");
printf(" X - Exit\n\n");
printf("Operation:");
ch = toupper(_getch());
printf("\n\n");
switch (ch)
{
case 'B':
CollectBlockImmediate(unit);
break;
case 'T':
CollectBlockTriggered(unit);
break;
case 'R':
CollectRapidBlock(unit);
break;
case 'S':
CollectStreamingImmediate(unit);
break;
case 'W':
CollectStreamingTriggered(unit);
break;
case 'E':
if(unit->ETS == FALSE)
{
printf("This model does not support ETS\n\n");
break;
}
CollectBlockEts(unit);
break;
case 'G':
if(unit->signalGenerator == FALSE)
{
printf("This model does not have a signal generator\n\n");
break;
}
SetSignalGenerator(unit);
break;
case 'V':
SetVoltages(unit);
break;
case 'I':
SetTimebase(unit);
break;
case 'A':
scaleVoltages = !scaleVoltages;
break;
case 'D':
if (unit->digitalPorts)
DigitalMenu(unit);
break;
case 'X':
break;
default:
printf("Invalid operation\n");
break;
}
}
}
/****************************************************************************
* main
*
***************************************************************************/
int main(void)
{
#define MAX_PICO_DEVICES 64
#define TIMED_LOOP_STEP 500
char ch;
uint16_t devCount = 0, listIter = 0, openIter = 0;
//device indexer - 64 chars - 64 is maximum number of picoscope devices handled by driver
char devChars[] =
"1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#";
PICO_STATUS status = PICO_OK;
UNIT allUnits[MAX_PICO_DEVICES];
printf("PS2000A driver example program\n");
printf("\nEnumerating Units...\n");
do
{
memset(&(allUnits[devCount]),0,sizeof (UNIT));
status = OpenDevice(&(allUnits[devCount]),NULL);
if(status == PICO_OK || status == PICO_POWER_SUPPLY_NOT_CONNECTED || status == PICO_USB3_0_DEVICE_NON_USB3_0_PORT)
{
allUnits[devCount++].openStatus = status;
}
} while(status != PICO_NOT_FOUND);
if (devCount == 0)
{
printf("Picoscope devices not found\n");
return 1;
}
// if there is only one device, open and handle it here
if (devCount == 1)
{
printf("Found one device, opening...\n\n");
status = allUnits[0].openStatus;
if (status == PICO_OK || status == PICO_POWER_SUPPLY_NOT_CONNECTED
|| status == PICO_USB3_0_DEVICE_NON_USB3_0_PORT)
status = HandleDevice(&allUnits[0]);
if (status != PICO_OK)
{
printf("Picoscope devices open failed, error code 0x%x\n",(uint32_t)status);
return 1;
}
printf("Model\t: %7s\nS/N\t: %s\n", allUnits[0].modelString, allUnits[0].serial);
MainMenu(&allUnits[0]);
CloseDevice(&allUnits[0]);
printf("Exit...\n");
return 0;
}
else
{
// more than one unit
printf("Found %d devices, initializing...\n\n", devCount);
for (listIter = 0; listIter < devCount; listIter++)
{
if ((allUnits[listIter].openStatus == PICO_OK
|| allUnits[listIter].openStatus
== PICO_POWER_SUPPLY_NOT_CONNECTED
|| allUnits[listIter].openStatus
== PICO_USB3_0_DEVICE_NON_USB3_0_PORT))
{
set_info(&allUnits[listIter]);
openIter++;
}
}
}
// None
if (openIter == 0)
{
printf("Picoscope devices init failed\n");
return 1;
}
// Just one - handle it here
if (openIter == 1)
{
for (listIter = 0; listIter < devCount; listIter++)
{
if (!(allUnits[listIter].openStatus == PICO_OK
|| allUnits[listIter].openStatus
== PICO_POWER_SUPPLY_NOT_CONNECTED
|| allUnits[listIter].openStatus
== PICO_USB3_0_DEVICE_NON_USB3_0_PORT))
break;
}
printf("One device openned successfuly\n");
printf("Model\t: %s\nS/N\t: %s\n", allUnits[listIter].modelString, allUnits[listIter].serial);
status = HandleDevice(&allUnits[listIter]);
if (status != PICO_OK)
{
printf("Picoscope device open failed, error code 0x%x\n", (uint32_t)status);
return 1;
}
MainMenu(&allUnits[listIter]);
CloseDevice(&allUnits[listIter]);
printf("Exit...\n");
return 0;
}
printf("Found %d devices, pick one to open from the list:\n", devCount);
for (listIter = 0; listIter < devCount; listIter++)
{
printf("%c) Picoscope %7s S/N: %s\n", devChars[listIter],
allUnits[listIter].modelString, allUnits[listIter].serial);
}
printf("ESC) Cancel\n");
ch = '.';
//if escape
while (ch != 27)
{
ch = _getch();
//if escape
if (ch == 27)
continue;
for (listIter = 0; listIter < devCount; listIter++)
{
if (ch == devChars[listIter])
{
printf("Option %c) selected, opening Picoscope %7s S/N: %s\n",
devChars[listIter], allUnits[listIter].modelString,
allUnits[listIter].serial);
if ((allUnits[listIter].openStatus == PICO_OK
|| allUnits[listIter].openStatus
== PICO_POWER_SUPPLY_NOT_CONNECTED
|| allUnits[listIter].openStatus
== PICO_USB3_0_DEVICE_NON_USB3_0_PORT))
status = HandleDevice(&allUnits[listIter]);
if (status != PICO_OK)
{
printf("Picoscope devices open failed, error code 0x%x\n", (uint32_t)status);
return 1;
}
MainMenu(&allUnits[listIter]);
printf("Found %d devices, pick one to open from the list:\n",devCount);
for (listIter = 0; listIter < devCount; listIter++)
{
printf("%c) Picoscope %7s S/N: %s\n", devChars[listIter],
allUnits[listIter].modelString,
allUnits[listIter].serial);
}
printf("ESC) Cancel\n");
}
}
}
for (listIter = 0; listIter < devCount; listIter++)
{
CloseDevice(&allUnits[listIter]);
}
printf("Exit...\n");
return 0;
}