Added a deploysics script The Tcl data and time functions were moved to the SICS kernel
2473 lines
69 KiB
C
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;
|
|
}
|