#include #include #include #include #include #include #include const char* DEFAULT_TYPE = "float"; const char* DEFAULT_RANGE = "10V"; const uint8_t DEFAULT_CHANNEL = 0; const bool DEFAULT_DC_MODE = false; const uint32_t DEFAULT_BUFFERSIZE = 10000; const uint32_t DEFAULT_MAX_BUFFERSIZE = DEFAULT_BUFFERSIZE * 5; const uint32_t DEFAULT_SAMPLE_INTERVAL = 1000; const char* DEFAULT_TIME_UNITS = "ns"; bool stop = false; uint8_t* channel; uint32_t* max_buffersize; // ctrl+c -> stop void capture_stop(int signal) { (void)signal; stop = true; } void get_overview_buffers_float(int16_t** overviewBuffers, int16_t overflow, uint32_t triggeredAt, int16_t triggered, int16_t auto_stop, uint32_t nValues) { (void)overflow; (void)triggeredAt; (void)triggered; (void)auto_stop; /* this buffer lives the whole lifetime of the application and so doesn't need to be cleaned up, the os will do it for us */ static float* float_buffer = NULL; if (float_buffer == NULL) { float_buffer = (float*)malloc(sizeof(float) * *max_buffersize); if (float_buffer == NULL) { fprintf(stderr, "failed to allocate buffers\n"); stop = true; return; } } // int16 -> float for (uint32_t i = 0; i < nValues; i++) { float_buffer[i] = overviewBuffers[*channel][i]; float_buffer[i] /= INT16_MAX; } fwrite(float_buffer, sizeof(float), nValues, stdout); } void get_overview_buffers_int16(int16_t** overviewBuffers, int16_t overflow, uint32_t triggeredAt, int16_t triggered, int16_t auto_stop, uint32_t nValues) { (void)overflow; (void)triggeredAt; (void)triggered; (void)auto_stop; fwrite(overviewBuffers[*channel], sizeof(int16_t), nValues, stdout); } PS2000_RANGE parse_range(char* range) { if (strcmp(range, "10mV") == 0) return PS2000_10MV; if (strcmp(range, "20mV") == 0) return PS2000_20MV; if (strcmp(range, "50mV") == 0) return PS2000_50MV; if (strcmp(range, "100mV") == 0) return PS2000_100MV; if (strcmp(range, "200mV") == 0) return PS2000_200MV; if (strcmp(range, "500mV") == 0) return PS2000_500MV; if (strcmp(range, "1V") == 0) return PS2000_1V; if (strcmp(range, "2V") == 0) return PS2000_2V; if (strcmp(range, "5V") == 0) return PS2000_5V; if (strcmp(range, "10V") == 0) return PS2000_10V; if (strcmp(range, "20V") == 0) return PS2000_20V; if (strcmp(range, "50V") == 0) return PS2000_50V; return PS2000_MAX_RANGES; } PS2000_TIME_UNITS parse_units(char* unit) { if (strcmp(unit, "fs") == 0) return PS2000_FS; if (strcmp(unit, "ps") == 0) return PS2000_PS; if (strcmp(unit, "ns") == 0) return PS2000_US; if (strcmp(unit, "us") == 0) return PS2000_US; if (strcmp(unit, "ms") == 0) return PS2000_MS; if (strcmp(unit, "s") == 0) return PS2000_S; return PS2000_MAX_TIME_UNITS; } void cleanup(int16_t unit) { ps2000_stop(unit); ps2000_close_unit(unit); } int main(int argc, char** argv) { // parse arguments if (argc > 0) c_flags_set_application_name(argv[0]); char** type = c_flag_string("type", "t", "type for output", DEFAULT_TYPE); char** range = c_flag_string("range", "r", "voltage range", DEFAULT_RANGE); channel = c_flag_uint8("channel", "c", "channel", DEFAULT_CHANNEL); bool* dc = c_flag_bool("dc", "dc", "dc mode", DEFAULT_DC_MODE); uint32_t* buffersize = c_flag_uint32("buffersize", "b", "buffersize", DEFAULT_BUFFERSIZE); max_buffersize = c_flag_uint32("max_buffersize", "mb", "max buffersize the driver stores", DEFAULT_MAX_BUFFERSIZE); uint32_t* sample_interval = c_flag_uint32("sample_interval", "s", "sample interval", DEFAULT_SAMPLE_INTERVAL); char** time_units = c_flag_string("time_units", "u", "time units", DEFAULT_TIME_UNITS); c_flags_parse(&argc, &argv, true); // validate arguments GetOverviewBuffersMaxMin get_overview_buffers_func; if (strcmp(*type, "float") == 0) { get_overview_buffers_func = get_overview_buffers_float; } else if (strcmp(*type, "int16")) { get_overview_buffers_func = get_overview_buffers_int16; } else { fprintf(stderr, "unknown output type: %s\n", *type); return -1; } PS2000_RANGE selected_range = parse_range(*range); if (selected_range == PS2000_MAX_RANGES) { fprintf(stderr, "invalid voltage range: %s\n", *range); return -1; } PS2000_TIME_UNITS selected_unit = parse_units(*time_units); if (selected_unit == PS2000_MAX_TIME_UNITS) { fprintf(stderr, "invalid time unit: %s\n", *time_units); return -1; } if (*channel > 1) { fprintf(stderr, "channel out of range: %u\n", *channel); return -1; } if (*max_buffersize <= *buffersize) { fprintf(stderr, "max buffersize needs to be bigger than buffersize\n"); return -1; } // configure picoscope int16_t unit = ps2000_open_unit(); if (ps2000_set_channel(unit, PS2000_CHANNEL_A + *channel, true, *dc, selected_range) == 0) { fprintf(stderr, "set_channel failed!\n"); cleanup(unit); return -1; } // disable interrupts if (ps2000_set_trigger(unit, PS2000_NONE, 0, 0, 0, 0) == 0) { fprintf(stderr, "set_trigger failed!\n"); cleanup(unit); return -1; } // start data capture without aggregation if (ps2000_run_streaming_ns(unit, *sample_interval, selected_unit, *buffersize, false, 1, *max_buffersize) == 0) { fprintf(stderr, "run_streaming_ns failed!\n"); cleanup(unit); return -1; } // start reading data signal(SIGINT, &capture_stop); while (!stop) { ps2000_get_streaming_last_values(unit, get_overview_buffers_func); } cleanup(unit); return 0; }