refactor for IQ recording
This commit is contained in:
parent
00efdf84f1
commit
384c189b82
24
include/recorder/config.h
Normal file
24
include/recorder/config.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef RECORDER_CONFIG_H
|
||||
#define RECORDER_CONFIG_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libps2000/ps2000.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t buffersize;
|
||||
uint32_t max_buffersize;
|
||||
uint32_t sample_interval;
|
||||
PS2000_RANGE range;
|
||||
PS2000_TIME_UNITS time_units;
|
||||
bool iq_mode;
|
||||
bool dc_mode;
|
||||
} config;
|
||||
|
||||
PS2000_RANGE parse_range(char* range);
|
||||
PS2000_TIME_UNITS parse_units(char* unit);
|
||||
|
||||
config* get_config(int argc, char** argv);
|
||||
|
||||
#endif
|
15
include/recorder/config_defaults.h
Normal file
15
include/recorder/config_defaults.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef RECORDER_CONFIG_DEFAULTS_H
|
||||
#define RECORDER_CONFIG_DEFAULTS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
const char* DEFAULT_RANGE = "10V";
|
||||
const bool DEFAULT_IQ_MODE = true;
|
||||
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";
|
||||
|
||||
#endif
|
93
src/recorder/config.c
Normal file
93
src/recorder/config.c
Normal file
@ -0,0 +1,93 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <c-flags.h>
|
||||
|
||||
#include <recorder/config.h>
|
||||
#include <recorder/config_defaults.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
config* get_config(int argc, char** argv) {
|
||||
if (argc > 0)
|
||||
c_flags_set_application_name(argv[0]);
|
||||
|
||||
char** range = c_flag_string("range", "r", "voltage range", DEFAULT_RANGE);
|
||||
bool* dc_mode = c_flag_bool("dc", "dc", "dc mode", DEFAULT_DC_MODE);
|
||||
bool* iq_mode = c_flag_bool("iq_mode", "iq", "IQ mode", DEFAULT_IQ_MODE);
|
||||
uint32_t* buffersize = c_flag_uint32("buffersize", "b", "buffersize", DEFAULT_BUFFERSIZE);
|
||||
uint32_t* 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);
|
||||
|
||||
config* cfg = (config*)malloc(sizeof(config));
|
||||
cfg->dc_mode = *dc_mode;
|
||||
cfg->iq_mode = *iq_mode;
|
||||
cfg->buffersize = *buffersize;
|
||||
cfg->max_buffersize = *max_buffersize;
|
||||
cfg->sample_interval = *sample_interval;
|
||||
|
||||
// validate arguments
|
||||
cfg->range = parse_range(*range);
|
||||
if (cfg->range == PS2000_MAX_RANGES) {
|
||||
fprintf(stderr, "invalid voltage range: %s\n", *range);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cfg->time_units = parse_units(*time_units);
|
||||
if (cfg->time_units == PS2000_MAX_TIME_UNITS) {
|
||||
fprintf(stderr, "invalid time unit: %s\n", *time_units);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*max_buffersize <= *buffersize) {
|
||||
fprintf(stderr, "max buffersize needs to be bigger than buffersize\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cfg;
|
||||
}
|
@ -2,23 +2,16 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <c-flags.h>
|
||||
#include <libps2000/ps2000.h>
|
||||
|
||||
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";
|
||||
#include <recorder/config.h>
|
||||
|
||||
bool stop = false;
|
||||
uint8_t* channel;
|
||||
uint32_t* max_buffersize;
|
||||
config* cfg;
|
||||
float* buffer;
|
||||
|
||||
// ctrl+c -> stop
|
||||
void capture_stop(int signal) {
|
||||
@ -26,150 +19,68 @@ void capture_stop(int 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 get_overview_buffers(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;
|
||||
if (cfg->iq_mode) {
|
||||
for (uint32_t i = 0; i < nValues; i++) {
|
||||
buffer[(i * 2) + 0] = overviewBuffers[0][i] / (float)INT16_MAX;
|
||||
buffer[(i * 2) + 1] = overviewBuffers[2][i] / (float)INT16_MAX;
|
||||
}
|
||||
|
||||
fwrite(buffer, sizeof(float), nValues * 2, stdout);
|
||||
} else {
|
||||
for (uint32_t i = 0; i < nValues; i++) {
|
||||
buffer[i] = overviewBuffers[0][i] / (float)INT16_MAX;
|
||||
}
|
||||
|
||||
fwrite(buffer, sizeof(float), nValues, stdout);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
if (buffer != NULL) {
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
free(cfg);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
cfg = get_config(argc, argv);
|
||||
|
||||
// configure picoscope
|
||||
int16_t unit = ps2000_open_unit();
|
||||
if (unit == -1) {
|
||||
fprintf(stderr, "failed to open a unit!\n");
|
||||
return -1;
|
||||
} else if (unit == 0) {
|
||||
fprintf(stderr, "no units to open!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ps2000_set_channel(unit, PS2000_CHANNEL_A + *channel, true, *dc, selected_range) == 0) {
|
||||
fprintf(stderr, "set_channel failed!\n");
|
||||
// configure channels
|
||||
if (ps2000_set_channel(unit, PS2000_CHANNEL_A, true, cfg->dc_mode, cfg->range) == 0) {
|
||||
fprintf(stderr, "set_channel A failed!\n");
|
||||
cleanup(unit);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cfg->iq_mode) {
|
||||
if (ps2000_set_channel(unit, PS2000_CHANNEL_B, true, cfg->dc_mode, cfg->range) == 0) {
|
||||
fprintf(stderr, "set_channel B 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");
|
||||
@ -177,8 +88,11 @@ int main(int argc, char** argv) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// allocate buffer
|
||||
buffer = (float*)malloc(sizeof(float) * (cfg->max_buffersize) * (cfg->iq_mode ? 2 : 1));
|
||||
|
||||
// start data capture without aggregation
|
||||
if (ps2000_run_streaming_ns(unit, *sample_interval, selected_unit, *buffersize, false, 1, *max_buffersize) == 0) {
|
||||
if (ps2000_run_streaming_ns(unit, cfg->sample_interval, cfg->time_units, cfg->buffersize, false, 1, cfg->max_buffersize) == 0) {
|
||||
fprintf(stderr, "run_streaming_ns failed!\n");
|
||||
cleanup(unit);
|
||||
return -1;
|
||||
@ -188,7 +102,7 @@ int main(int argc, char** argv) {
|
||||
signal(SIGINT, &capture_stop);
|
||||
|
||||
while (!stop) {
|
||||
ps2000_get_streaming_last_values(unit, get_overview_buffers_func);
|
||||
ps2000_get_streaming_last_values(unit, &get_overview_buffers);
|
||||
}
|
||||
|
||||
cleanup(unit);
|
||||
|
Loading…
Reference in New Issue
Block a user