make recorder configurable
This commit is contained in:
parent
5f4199c122
commit
6055d50eaf
@ -4,7 +4,7 @@ project(pico-radio C)
|
|||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS true)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS true)
|
||||||
|
|
||||||
include_directories(include /opt/picoscope/include)
|
include_directories(include /opt/picoscope/include third-party/c-flags/single-header)
|
||||||
link_directories(/opt/picoscope/lib)
|
link_directories(/opt/picoscope/lib)
|
||||||
|
|
||||||
add_subdirectory(src/pico-radio)
|
add_subdirectory(src/recorder)
|
||||||
|
37
Readme.md
37
Readme.md
@ -1,7 +1,34 @@
|
|||||||
# Pico Radio
|
# Pico Radio
|
||||||
|
|
||||||
## Fast-streaming buffer format
|
## recorder
|
||||||
1. Channel A min
|
### Arguments
|
||||||
2. Channel A max
|
```
|
||||||
3. Channel B min
|
--type, -t
|
||||||
4. Channel B max
|
Description: type for output
|
||||||
|
Default: float
|
||||||
|
|
||||||
|
--range, -r
|
||||||
|
Description: voltage range
|
||||||
|
Default: 10V
|
||||||
|
|
||||||
|
--channel, -c
|
||||||
|
Description: channel
|
||||||
|
Default: 0
|
||||||
|
|
||||||
|
--buffersize, -b
|
||||||
|
Description: buffersize
|
||||||
|
Default: 10000
|
||||||
|
|
||||||
|
--max_buffersize, -mb
|
||||||
|
Description: max buffersize the driver stores
|
||||||
|
Default: 50000
|
||||||
|
|
||||||
|
--sample_interval, -s
|
||||||
|
Description: sample interval
|
||||||
|
Default: 1000
|
||||||
|
|
||||||
|
--time_units, -u
|
||||||
|
Description: time units
|
||||||
|
Default: ns
|
||||||
|
|
||||||
|
```
|
@ -1,7 +0,0 @@
|
|||||||
file(GLOB_RECURSE SOURCES "./*.c")
|
|
||||||
add_executable(pico-radio ${SOURCES})
|
|
||||||
target_compile_options(pico-radio PRIVATE -Wall -Wextra)
|
|
||||||
target_link_libraries(pico-radio ps2000)
|
|
||||||
set_target_properties(pico-radio PROPERTIES
|
|
||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
|
|
||||||
)
|
|
@ -1,80 +0,0 @@
|
|||||||
#include <signal.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <libps2000/ps2000.h>
|
|
||||||
|
|
||||||
bool stop = false;
|
|
||||||
|
|
||||||
void capture_stop(int signal) {
|
|
||||||
(void)signal;
|
|
||||||
stop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint32_t buffersize = 10000;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
fprintf(stderr, "nValues: %u\n", nValues);
|
|
||||||
|
|
||||||
static float floatbuff[10000]; // TODO variable
|
|
||||||
for (unsigned i = 0; i < nValues; i++) {
|
|
||||||
floatbuff[i] = overviewBuffers[0][i];
|
|
||||||
floatbuff[i] /= 32768; // TODO limit.h
|
|
||||||
}
|
|
||||||
fwrite(floatbuff, sizeof(float), nValues, stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
(void)argc;
|
|
||||||
(void)argv;
|
|
||||||
|
|
||||||
int16_t unit = ps2000_open_unit();
|
|
||||||
|
|
||||||
if (ps2000_set_channel(unit, PS2000_CHANNEL_A, true, false, PS2000_10V) == 0) {
|
|
||||||
fprintf(stderr, "set_channel failed!\n");
|
|
||||||
ps2000_close_unit(unit);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ps2000_set_trigger(unit, PS2000_NONE, 0, 0, 0, 0) == 0) {
|
|
||||||
fprintf(stderr, "set_trigger failed!\n");
|
|
||||||
ps2000_close_unit(unit);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ps2000_run_streaming_ns(unit, 1000, PS2000_NS, buffersize, false, 1, 50000) == 0) {
|
|
||||||
fprintf(stderr, "run_streaming_ns failed!\n");
|
|
||||||
ps2000_close_unit(unit);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
signal(SIGINT, &capture_stop);
|
|
||||||
|
|
||||||
while (!stop) {
|
|
||||||
if (ps2000_get_streaming_last_values(unit, &get_overview_buffers) == 0) {
|
|
||||||
// fprintf(stderr, "callback won't be called!\n");
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
int16_t overrun = 0;
|
|
||||||
if (ps2000_overview_buffer_status(unit, &overrun) != 0) {
|
|
||||||
fprintf(stderr, "failed to check overrun!\n");
|
|
||||||
} else if (overrun) {
|
|
||||||
fprintf(stderr, "overrun!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// usleep(0);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
ps2000_stop(unit);
|
|
||||||
ps2000_close_unit(unit);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
7
src/recorder/CMakeLists.txt
Normal file
7
src/recorder/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
file(GLOB_RECURSE SOURCES "./*.c")
|
||||||
|
add_executable(recorder ${SOURCES})
|
||||||
|
target_compile_options(recorder PRIVATE -Wall -Wextra)
|
||||||
|
target_link_libraries(recorder ps2000)
|
||||||
|
set_target_properties(recorder PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||||
|
)
|
194
src/recorder/main.c
Normal file
194
src/recorder/main.c
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.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 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;
|
||||||
|
|
||||||
|
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"))
|
||||||
|
return PS2000_FS;
|
||||||
|
if (strcmp(unit, "ps"))
|
||||||
|
return PS2000_PS;
|
||||||
|
if (strcmp(unit, "ns"))
|
||||||
|
return PS2000_US;
|
||||||
|
if (strcmp(unit, "us"))
|
||||||
|
return PS2000_US;
|
||||||
|
if (strcmp(unit, "ms"))
|
||||||
|
return PS2000_MS;
|
||||||
|
if (strcmp(unit, "s"))
|
||||||
|
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);
|
||||||
|
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_units = parse_units(*time_units);
|
||||||
|
if (selected_units == 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, false, 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_units, *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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user