From 75d830a778cf99767e9f55d529ac6320993b1c16 Mon Sep 17 00:00:00 2001 From: profezzorn <hubbe@hubbe.net> Date: Mon, 31 Jan 2022 19:07:18 -0800 Subject: [PATCH 01/13] fix read32 byte order --- Software/libthunderscopehw/library/thunderscopehw_internals.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Software/libthunderscopehw/library/thunderscopehw_internals.c b/Software/libthunderscopehw/library/thunderscopehw_internals.c index 2a0ed246..2547ca6f 100644 --- a/Software/libthunderscopehw/library/thunderscopehw_internals.c +++ b/Software/libthunderscopehw/library/thunderscopehw_internals.c @@ -210,7 +210,7 @@ uint32_t thunderscopehw_read32(struct ThunderScopeHW* ts, size_t addr) { uint8_t bytes[4]; thunderscopehw_read_handle(ts, ts->user_handle, bytes, addr, 4); - return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; + return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]; } enum ThunderScopeHWStatus thunderscopehw_write32(struct ThunderScopeHW* ts, size_t addr, uint32_t value) From 61120acf3043ac8e16f60178d0fab203d59a05a2 Mon Sep 17 00:00:00 2001 From: Aleksa <abjelogr@uwaterloo.ca> Date: Mon, 31 Jan 2022 22:40:17 -0500 Subject: [PATCH 02/13] Changed FIFO_ISR Value to use uppermost byte --- Software/libthunderscopehw/library/thunderscopehw_internals.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Software/libthunderscopehw/library/thunderscopehw_internals.c b/Software/libthunderscopehw/library/thunderscopehw_internals.c index 2547ca6f..6e1af1d6 100644 --- a/Software/libthunderscopehw/library/thunderscopehw_internals.c +++ b/Software/libthunderscopehw/library/thunderscopehw_internals.c @@ -37,7 +37,7 @@ enum ThunderScopeHWStatus thunderscopehw_fifo_write(struct ThunderScopeHW* ts, u // write to TLR (the size of the packet) THUNDERSCOPEHW_RUN(write32(ts, SERIAL_FIFO_TLR_ADDRESS, (uint32_t)(bytes * 4))); // read ISR for a done value - while ((thunderscopehw_read32(ts, SERIAL_FIFO_ISR_ADDRESS) & 0xff) != 8) { + while ((thunderscopehw_read32(ts, SERIAL_FIFO_ISR_ADDRESS) >> 24) != 8) { #ifdef WIN32 Sleep(1); #else From 79acd473eed02e7cd5caac6d9aa8d70f2b125c51 Mon Sep 17 00:00:00 2001 From: profezzorn <hubbe@hubbe.net> Date: Mon, 31 Jan 2022 22:57:56 -0800 Subject: [PATCH 03/13] several bugfixes, now getting ramp data --- .../thunderscopehwdump/thunderscopehwdump.c | 16 +++++++++------- .../libthunderscopehw/library/thunderscopehw.c | 3 +-- .../library/thunderscopehw_internals.c | 7 ++++++- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c b/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c index 3d6c493a..00967ab4 100644 --- a/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c +++ b/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c @@ -82,7 +82,8 @@ int mygetopt(int argc, char** argv) { optind++; return options[i].return_value; } - return -1; + fprintf(stderr, "Unknown option: %s\n", argv[optind]); + exit(1); } int main(int argc, char** argv) { @@ -252,22 +253,23 @@ int main(int argc, char** argv) { exit(1); } +#define BUFFER_SIZE (1<<20) uint8_t* buffer; #ifdef _WIN32 - buffer = _aligned_malloc(1 << 20, 4096); -#else - posix_memalign((void**)&buffer, 4096, 1 << 20); + buffer = _aligned_malloc(BUFFER_SIZE, 4096); +#else + posix_memalign((void**)&buffer, 4096, BUFFER_SIZE); #endif while (samples) { int64_t to_copy = samples; - if (to_copy > sizeof(buffer)) to_copy = sizeof(buffer); - ret = thunderscopehw_read(ts, buffer, sizeof(buffer)); + if (to_copy > BUFFER_SIZE) to_copy = BUFFER_SIZE; + ret = thunderscopehw_read(ts, buffer, to_copy); if (ret != THUNDERSCOPEHW_STATUS_OK) { fprintf(stderr, "Thunderscope read error, error = %s\n", thunderscopehw_describe_error(ret)); exit(1); } - if (fwrite(buffer, 1, sizeof(buffer), outfile) != sizeof(buffer)) { + if (fwrite(buffer, 1, to_copy, outfile) != to_copy) { perror("fwrite"); exit(1); } diff --git a/Software/libthunderscopehw/library/thunderscopehw.c b/Software/libthunderscopehw/library/thunderscopehw.c index 2764d026..da0fb62a 100644 --- a/Software/libthunderscopehw/library/thunderscopehw.c +++ b/Software/libthunderscopehw/library/thunderscopehw.c @@ -119,7 +119,6 @@ static enum ThunderScopeHWStatus thunderscopehw_update_buffer_head(struct Thunde uint32_t overflow_cycles = (transfer_counter >> 16) & 0x3FFF; if (overflow_cycles) { - fprintf(stderr, "TRANSFER COUNTER = %llx\n", (long long)transfer_counter); return THUNDERSCOPEHW_STATUS_PIPELINE_OVERFLOW; } @@ -168,7 +167,7 @@ enum ThunderScopeHWStatus thunderscopehw_read(struct ThunderScopeHW* ts, uint8_t if (pages_to_read > ts->ram_size_pages - buffer_read_pos) pages_to_read = ts->ram_size_pages - buffer_read_pos; if (pages_to_read > ts->ram_size_pages / 4) pages_to_read = ts->ram_size_pages / 4; - thunderscopehw_read_handle(ts, ts->user_handle, data, buffer_read_pos << 12, pages_to_read << 12); + THUNDERSCOPEHW_RUN(read_handle(ts, ts->c2h0_handle, data, buffer_read_pos << 12, pages_to_read << 12)); data += pages_to_read << 12; length -= pages_to_read << 12; diff --git a/Software/libthunderscopehw/library/thunderscopehw_internals.c b/Software/libthunderscopehw/library/thunderscopehw_internals.c index 6e1af1d6..eab907e6 100644 --- a/Software/libthunderscopehw/library/thunderscopehw_internals.c +++ b/Software/libthunderscopehw/library/thunderscopehw_internals.c @@ -1,6 +1,8 @@ #include "thunderscopehw_private.h" #include <math.h> +#include <stdio.h> +#include <stdlib.h> #ifdef WIN32 #else @@ -209,7 +211,10 @@ enum ThunderScopeHWStatus thunderscopehw_configure_channel(struct ThunderScopeHW uint32_t thunderscopehw_read32(struct ThunderScopeHW* ts, size_t addr) { uint8_t bytes[4]; - thunderscopehw_read_handle(ts, ts->user_handle, bytes, addr, 4); + if (thunderscopehw_read_handle(ts, ts->user_handle, bytes, addr, 4) != THUNDERSCOPEHW_STATUS_OK) { + fprintf(stderr, "Error in thunderscopehw_read32\n"); + exit(1); + } return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]; } From 06c0310e37a98a4d535c0fba0e3e94f981c63996 Mon Sep 17 00:00:00 2001 From: Aleksa <abjelogr@uwaterloo.ca> Date: Tue, 1 Feb 2022 22:16:09 -0500 Subject: [PATCH 04/13] Fix return value on windows read_handle function --- Software/libthunderscopehw/library/thunderscopehw_win.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Software/libthunderscopehw/library/thunderscopehw_win.c b/Software/libthunderscopehw/library/thunderscopehw_win.c index e8a9ff68..187887cb 100644 --- a/Software/libthunderscopehw/library/thunderscopehw_win.c +++ b/Software/libthunderscopehw/library/thunderscopehw_win.c @@ -153,7 +153,7 @@ enum ThunderScopeHWStatus thunderscopehw_read_handle(struct ThunderScopeHW* ts, fprintf(stderr, "read handle failed, win32 error code: %d\n", GetLastError()); return THUNDERSCOPEHW_STATUS_READ_ERROR; } - return true; + return THUNDERSCOPEHW_STATUS_OK; } enum ThunderScopeHWStatus thunderscopehw_write_handle(struct ThunderScopeHW* ts, HANDLE h, uint8_t* data, uint64_t addr, int64_t bytes) From 91a88f978e06e75f974459b4ef4958b3343b2bf9 Mon Sep 17 00:00:00 2001 From: Aleksa <abjelogr@uwaterloo.ca> Date: Sun, 6 Feb 2022 14:15:34 -0500 Subject: [PATCH 05/13] Some register fixes, still stalls on read with ThunderScope board though --- Software/libthunderscopehw/library/thunderscopehw_adc.c | 2 +- Software/libthunderscopehw/library/thunderscopehw_private.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Software/libthunderscopehw/library/thunderscopehw_adc.c b/Software/libthunderscopehw/library/thunderscopehw_adc.c index 89ea7803..03709be8 100644 --- a/Software/libthunderscopehw/library/thunderscopehw_adc.c +++ b/Software/libthunderscopehw/library/thunderscopehw_adc.c @@ -25,7 +25,7 @@ enum ThunderScopeHWStatus thunderscopehw_configure_adc(struct ThunderScopeHW* ts THUNDERSCOPEHW_RUN(adc_power(ts, false)); // invert channels - THUNDERSCOPEHW_RUN(adc_set_reg(ts, THUNDERSCOPEHW_ADC_REG_INVERT, 0x0074)); + THUNDERSCOPEHW_RUN(adc_set_reg(ts, THUNDERSCOPEHW_ADC_REG_INVERT, 0x007F)); // Adjust full scale value THUNDERSCOPEHW_RUN(adc_set_reg(ts, THUNDERSCOPEHW_ADC_REG_FS_CNTRL, 0x0010)); diff --git a/Software/libthunderscopehw/library/thunderscopehw_private.h b/Software/libthunderscopehw/library/thunderscopehw_private.h index 4820a0df..4de3a98a 100644 --- a/Software/libthunderscopehw/library/thunderscopehw_private.h +++ b/Software/libthunderscopehw/library/thunderscopehw_private.h @@ -102,7 +102,7 @@ enum ThunderScopeHWAdcRegister { THUNDERSCOPEHW_ADC_REG_CHNUM_CLKDIV = 0x31, THUNDERSCOPEHW_ADC_REG_GAIN_CFG = 0x33, THUNDERSCOPEHW_ADC_REG_INSEL12 = 0x3A, - THUNDERSCOPEHW_ADC_REG_INSEL34 = 0x3A, + THUNDERSCOPEHW_ADC_REG_INSEL34 = 0x3B, THUNDERSCOPEHW_ADC_REG_FS_CNTRL = 0x55, }; enum ThunderScopeHWStatus thunderscopehw_adc_set_reg(struct ThunderScopeHW* ts, enum ThunderScopeHWAdcRegister reg, uint16_t value); From 3d89cb41f1199df0614c9869e4b373be669dad73 Mon Sep 17 00:00:00 2001 From: profezzorn <hubbe@hubbe.net> Date: Sun, 6 Feb 2022 19:18:13 -0800 Subject: [PATCH 06/13] adc bugfixes --- Software/libthunderscopehw/library/thunderscopehw_adc.c | 2 +- Software/libthunderscopehw/library/thunderscopehw_private.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Software/libthunderscopehw/library/thunderscopehw_adc.c b/Software/libthunderscopehw/library/thunderscopehw_adc.c index 03709be8..308f36d2 100644 --- a/Software/libthunderscopehw/library/thunderscopehw_adc.c +++ b/Software/libthunderscopehw/library/thunderscopehw_adc.c @@ -14,7 +14,7 @@ enum ThunderScopeHWStatus thunderscopehw_adc_power(struct ThunderScopeHW* ts, bo { return thunderscopehw_adc_set_reg(ts, THUNDERSCOPEHW_ADC_REG_POWER, - on ? 0x0200 : 0x0000); + on ? 0x0000 : 0x0200); } enum ThunderScopeHWStatus thunderscopehw_configure_adc(struct ThunderScopeHW* ts) diff --git a/Software/libthunderscopehw/library/thunderscopehw_private.h b/Software/libthunderscopehw/library/thunderscopehw_private.h index 4de3a98a..612aae7c 100644 --- a/Software/libthunderscopehw/library/thunderscopehw_private.h +++ b/Software/libthunderscopehw/library/thunderscopehw_private.h @@ -33,7 +33,7 @@ #define SPI_FRONT_END_CHANNEL_3 0xFA #define SPI_FRONT_END_CHANNEL_4 0xFB -#define SPI_BYTE_ADC 0xFC +#define SPI_BYTE_ADC 0xFD #define I2C_BYTE_PLL 0xFF From ff6df7e2ea729a9fd284e890204da14a4fc8db7e Mon Sep 17 00:00:00 2001 From: profezzorn <hubbe@hubbe.net> Date: Sun, 6 Feb 2022 21:58:24 -0800 Subject: [PATCH 07/13] invert relay --- Software/libthunderscopehw/library/thunderscopehw_internals.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Software/libthunderscopehw/library/thunderscopehw_internals.c b/Software/libthunderscopehw/library/thunderscopehw_internals.c index eab907e6..e03eb1df 100644 --- a/Software/libthunderscopehw/library/thunderscopehw_internals.c +++ b/Software/libthunderscopehw/library/thunderscopehw_internals.c @@ -65,19 +65,17 @@ enum ThunderScopeHWStatus thunderscopehw_set_datamover_reg(struct ThunderScopeHW if (ts->datamover_en) datamover_reg |= 0x1; if (ts->fpga_adc_en) datamover_reg |= 0x2; -#if 1 for (int channel = 0; channel < 4; channel++) { if (ts->channels[channel].on == true) { num_channels_on++; } - if (ts->channels[channel].vdiv > 100) { + if (ts->channels[channel].vdiv <= 100) { datamover_reg |= 1 << (16 + channel); } if (ts->channels[channel].coupling == THUNDERSCOPEHW_COUPLING_DC) { datamover_reg |= 1 << (20 + channel); } } -#endif switch (num_channels_on) { case 0: case 1: break; // do nothing From dd17422182d36c3e48faa58ade3234183dbfe2cf Mon Sep 17 00:00:00 2001 From: profezzorn <hubbe@hubbe.net> Date: Sun, 6 Feb 2022 22:12:21 -0800 Subject: [PATCH 08/13] convert signed bytes to unsigned bytes since 8-bit wav files are unsigned --- .../examples/thunderscopehwdump/thunderscopehwdump.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c b/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c index 00967ab4..4bfe6b38 100644 --- a/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c +++ b/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c @@ -269,6 +269,10 @@ int main(int argc, char** argv) { fprintf(stderr, "Thunderscope read error, error = %s\n", thunderscopehw_describe_error(ret)); exit(1); } + // Convert signed output to unsigned output + for (size_t i = 0; i < BUFFER_SIZE; i++) { + buffer[i] += 0x80; + } if (fwrite(buffer, 1, to_copy, outfile) != to_copy) { perror("fwrite"); exit(1); From 454052c05046766ba690a0eb57e99adb3fa6b21a Mon Sep 17 00:00:00 2001 From: profezzorn <hubbe@hubbe.net> Date: Sun, 13 Feb 2022 01:04:00 -0800 Subject: [PATCH 09/13] start calibration program --- Software/libthunderscopehw/CMakeLists.txt | 1 + .../thunderscopehwcalibrate/CMakeLists.txt | 4 + .../thunderscopehwcalibrate.c | 150 ++++++++++++++++++ .../thunderscopehwdump/thunderscopehwdump.c | 77 +++++---- .../include/thunderscopehw.h | 2 + .../library/thunderscopehw.c | 6 + .../library/thunderscopehw_internals.c | 9 +- 7 files changed, 214 insertions(+), 35 deletions(-) create mode 100644 Software/libthunderscopehw/examples/thunderscopehwcalibrate/CMakeLists.txt create mode 100644 Software/libthunderscopehw/examples/thunderscopehwcalibrate/thunderscopehwcalibrate.c diff --git a/Software/libthunderscopehw/CMakeLists.txt b/Software/libthunderscopehw/CMakeLists.txt index 546ecaa4..0890d133 100644 --- a/Software/libthunderscopehw/CMakeLists.txt +++ b/Software/libthunderscopehw/CMakeLists.txt @@ -6,6 +6,7 @@ project(thunderscopehwlib VERSION ${PROJECT_VERSION}) add_subdirectory(library) add_subdirectory(examples/thunderscopehwdump) +add_subdirectory(examples/thunderscopehwcalibrate) enable_testing() add_subdirectory(test) diff --git a/Software/libthunderscopehw/examples/thunderscopehwcalibrate/CMakeLists.txt b/Software/libthunderscopehw/examples/thunderscopehwcalibrate/CMakeLists.txt new file mode 100644 index 00000000..f168201c --- /dev/null +++ b/Software/libthunderscopehw/examples/thunderscopehwcalibrate/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(thunderscopehwcalibrate + thunderscopehwcalibrate.c) +target_link_libraries(thunderscopehwcalibrate + thunderscopehwlib) diff --git a/Software/libthunderscopehw/examples/thunderscopehwcalibrate/thunderscopehwcalibrate.c b/Software/libthunderscopehw/examples/thunderscopehwcalibrate/thunderscopehwcalibrate.c new file mode 100644 index 00000000..7976afe9 --- /dev/null +++ b/Software/libthunderscopehw/examples/thunderscopehwcalibrate/thunderscopehwcalibrate.c @@ -0,0 +1,150 @@ +#include "thunderscopehw.h" + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> + +#ifndef WIN32 +#include <unistd.h> +#endif + +struct Option { + const char* name; + bool needs_argument; + int return_value; +}; + +struct Option options[] = { + {"device", true, 1 }, +}; + +#define TS_RUN(X) do { \ + enum ThunderScopeHWStatus ret = thunderscopehw_##X; \ + if (ret != THUNDERSCOPEHW_STATUS_OK) { \ + fprintf(stderr, "thunderscope_%s failed @ line %d, error = %s\n", #X, __LINE__, thunderscopehw_describe_error(ret)); \ + exit(1); \ + } \ +} while(0) + +char* optarg; +int optind = 1; +int mygetopt(int argc, char** argv) { + if (optind >= argc) return -1; + if (!argv[optind][0] == '-' || argv[optind][1] != '-') return -1; + char *arg = strchr(argv[optind], '='); + for (size_t i = 0; i < sizeof(options) / sizeof(options[0]); i++) { + size_t len = strlen(options[i].name); + if (strncmp(options[i].name, argv[optind] + 2, len)) continue; + if (options[i].needs_argument) { + if (!arg) continue; + if (argv[optind] + 2 + len != arg) continue; + optarg = arg + 1; + } else { + if (arg) continue; + if (argv[optind][2 + len]) continue; + optarg = NULL; + } + optind++; + return options[i].return_value; + } + fprintf(stderr, "Unknown option: %s\n", argv[optind]); + exit(1); +} + +int main(int argc, char** argv) { + uint64_t scope_id = 0; + uint64_t samples = 0; + int samplerate = 0; + while (1) { + switch (mygetopt(argc, argv)) { + case 1: + if (!sscanf(optarg, "%" PRIx64, &scope_id)) { + fprintf(stderr, "Scope ID must be hexadecimal.\n"); + exit(1); + } + continue; + default: + continue; + case -1: + break; + } + break; + } + + if (scope_id == 0) { + uint64_t scope_ids[32]; + int scopes = thunderscopehw_scan(scope_ids, 32); + if (scopes == 0) { + fprintf(stderr, "No thunderscopehw hardware found.\n"); + exit(1); + } + if (scopes > 1) { + fprintf(stderr, "Multiple scopes found, please select one with --device.\n"); + for (int i = 0; i < scopes; i++) { + fprintf(stderr, " %0" PRIx64 "\n", scope_ids[i]); + } + exit(1); + } + scope_id = scope_ids[0]; + } + +#define BUFFER_SIZE (1<<20) + uint8_t* buffer; +#ifdef _WIN32 + buffer = _aligned_malloc(BUFFER_SIZE, 4096); +#else + posix_memalign((void**)&buffer, 4096, BUFFER_SIZE); +#endif + + struct ThunderScopeHW *ts = thunderscopehw_create(); + enum ThunderScopeHWStatus ret; + TS_RUN(connect(ts, scope_id)); + + for (int channel = 0; channel < 4; channel++) { + TS_RUN(enable_channel(ts, channel)); + // 1mV / div + TS_RUN(voltage_division_set(ts, channel, 1)); +#ifdef WIN32 + Sleep(500); +#else + usleep(500000); +#endif + + double minoffset = -0.5; + double maxoffset = 0.5; + + for (int i =0; i < 1000; i++) { + for (int j = 0; j < 20; j++) { + double midoffset = (minoffset + maxoffset) / 2; + TS_RUN(voltage_offset_set(ts, channel, midoffset)); + TS_RUN(start(ts)); + TS_RUN(read(ts, buffer, BUFFER_SIZE)); + // Convert signed output to unsigned output + for (size_t i = 0; i < BUFFER_SIZE; i++) { + buffer[i] += 0x80; + } + TS_RUN(stop(ts)); + int high = 0; + int low = 0; + uint64_t sum = 0; + for (size_t i = 0; i < BUFFER_SIZE; i++) { + if (buffer[i] > 0x80) high++; + if (buffer[i] < 0x80) low++; + sum += buffer[i]; + } +// fprintf(stderr," min = %8.4f max = %8.4f mid = %8.4f high=%d low=%d avg=%f\n", +// minoffset, maxoffset, midoffset, +// high, low, +// sum / (double)BUFFER_SIZE); + if (high > low) { + minoffset = midoffset; + } else { + maxoffset = midoffset; + } + } + printf("Channel %d calibration = %f\n", channel + 1, (minoffset + maxoffset) / 2); + } + TS_RUN(disable_channel(ts, channel)); + } +} diff --git a/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c b/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c index 4bfe6b38..94869fa7 100644 --- a/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c +++ b/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c @@ -21,44 +21,45 @@ struct Option { }; struct Option options[] = { - {"device", true, 1 }, - {"samples", true, 2 }, + {"device", true, 1 }, + {"samples", true, 2 }, + {"output-samplerate", true, 3 }, - {"bw-all", true, 0x10 }, - {"bw1", true, 0x11 }, - {"bw2", true, 0x12 }, - {"bw3", true, 0x13 }, - {"bw4", true, 0x14 }, + {"bw-all", true, 0x10 }, + {"bw1", true, 0x11 }, + {"bw2", true, 0x12 }, + {"bw3", true, 0x13 }, + {"bw4", true, 0x14 }, - {"vdiv-all", true, 0x20 }, - {"vdiv1", true, 0x21 }, - {"vdiv2", true, 0x22 }, - {"vdiv3", true, 0x23 }, - {"vdiv4", true, 0x24 }, + {"vdiv-all", true, 0x20 }, + {"vdiv1", true, 0x21 }, + {"vdiv2", true, 0x22 }, + {"vdiv3", true, 0x23 }, + {"vdiv4", true, 0x24 }, - {"voffset-all", true, 0x30 }, - {"voffset1", true, 0x31 }, - {"voffset2", true, 0x32 }, - {"voffset3", true, 0x33 }, - {"voffset4", true, 0x34 }, + {"voffset-all", true, 0x30 }, + {"voffset1", true, 0x31 }, + {"voffset2", true, 0x32 }, + {"voffset3", true, 0x33 }, + {"voffset4", true, 0x34 }, - {"ac-all", false, 0x40 }, - {"ac1", false, 0x41 }, - {"ac2", false, 0x42 }, - {"ac3", false, 0x43 }, - {"ac4", false, 0x44 }, + {"ac-all", false, 0x40 }, + {"ac1", false, 0x41 }, + {"ac2", false, 0x42 }, + {"ac3", false, 0x43 }, + {"ac4", false, 0x44 }, - {"dc-all", false, 0x50 }, - {"ac1", false, 0x51 }, - {"ac2", false, 0x52 }, - {"ac3", false, 0x53 }, - {"ac4", false, 0x54 }, + {"dc-all", false, 0x50 }, + {"ac1", false, 0x51 }, + {"ac2", false, 0x52 }, + {"ac3", false, 0x53 }, + {"ac4", false, 0x54 }, - {"enable-all", false, 0x60 }, - {"enable1", false, 0x61 }, - {"enable2", false, 0x62 }, - {"enable3", false, 0x63 }, - {"enable4", false, 0x64 }, + {"enable-all", false, 0x60 }, + {"enable1", false, 0x61 }, + {"enable2", false, 0x62 }, + {"enable3", false, 0x63 }, + {"enable4", false, 0x64 }, }; char* optarg; @@ -89,6 +90,7 @@ int mygetopt(int argc, char** argv) { int main(int argc, char** argv) { uint64_t scope_id = 0; uint64_t samples = 0; + int samplerate = 0; while (1) { switch (mygetopt(argc, argv)) { case 1: @@ -102,6 +104,11 @@ int main(int argc, char** argv) { fprintf(stderr, "Number of samples must be a number.\n"); exit(1); } + case 3: + if (!sscanf(optarg, "%d", &samplerate)) { + fprintf(stderr, "Output samplerate must be a number.\n"); + exit(1); + } default: continue; case -1: @@ -232,7 +239,11 @@ int main(int argc, char** argv) { struct Fmt fmt; fmt.pcm = 1; fmt.channels = num_channels; - fmt.rate = 1000000000 / fmt.channels; + if (samplerate) { + fmt.rate = samplerate; + } else { + fmt.rate = 1000000000 / fmt.channels; + } fmt.byterate = 1000000000; fmt.block_align = 0; fmt.bits_per_sample = 8; diff --git a/Software/libthunderscopehw/include/thunderscopehw.h b/Software/libthunderscopehw/include/thunderscopehw.h index e214666c..9f6225f8 100644 --- a/Software/libthunderscopehw/include/thunderscopehw.h +++ b/Software/libthunderscopehw/include/thunderscopehw.h @@ -25,6 +25,8 @@ enum ThunderScopeHWStatus { THUNDERSCOPEHW_STATUS_ALREADY_STARTED, THUNDERSCOPEHW_STATUS_NOT_STARTED, THUNDERSCOPEHW_STATUS_ALREADY_STOPPED, + THUNDERSCOPEHW_STATUS_OFFSET_TOO_LOW, + THUNDERSCOPEHW_STATUS_OFFSET_TOO_HIGH, }; // Return's number of scopes. diff --git a/Software/libthunderscopehw/library/thunderscopehw.c b/Software/libthunderscopehw/library/thunderscopehw.c index da0fb62a..4bbd50da 100644 --- a/Software/libthunderscopehw/library/thunderscopehw.c +++ b/Software/libthunderscopehw/library/thunderscopehw.c @@ -93,6 +93,8 @@ enum ThunderScopeHWStatus thunderscopehw_start(struct ThunderScopeHW* ts) { return THUNDERSCOPEHW_STATUS_ALREADY_STARTED; ts->datamover_en = true; ts->fpga_adc_en = true; + ts->buffer_head = 0; + ts->buffer_tail = 0; return thunderscopehw_set_datamover_reg(ts); } @@ -220,6 +222,10 @@ const char* thunderscopehw_describe_error(enum ThunderScopeHWStatus err) { return "not started"; case THUNDERSCOPEHW_STATUS_ALREADY_STOPPED: return "already stopped"; + case THUNDERSCOPEHW_STATUS_OFFSET_TOO_LOW: + return "voffset too low"; + case THUNDERSCOPEHW_STATUS_OFFSET_TOO_HIGH: + return "voffset too high"; } return "unkonwn error"; } diff --git a/Software/libthunderscopehw/library/thunderscopehw_internals.c b/Software/libthunderscopehw/library/thunderscopehw_internals.c index e03eb1df..f178ae54 100644 --- a/Software/libthunderscopehw/library/thunderscopehw_internals.c +++ b/Software/libthunderscopehw/library/thunderscopehw_internals.c @@ -126,7 +126,12 @@ enum ThunderScopeHWStatus thunderscopehw_set_dac(struct ThunderScopeHW* ts, int { // value is 12-bit // Is this right?? Or is it rounding wrong? - unsigned int dac_value = (unsigned int)round((ts->channels[channel].voffset + 0.5) * 4095); + int dac_value = (unsigned int)round((ts->channels[channel].voffset + 0.5) * 4095); + if (dac_value < 0) + return THUNDERSCOPEHW_STATUS_OFFSET_TOO_LOW; + if (dac_value > 0xFFF) + return THUNDERSCOPEHW_STATUS_OFFSET_TOO_HIGH; + uint8_t fifo[5]; fifo[0] = 0xFF; // I2C fifo[1] = 0xC2; // DAC? @@ -151,7 +156,7 @@ enum ThunderScopeHWStatus thunderscopehw_configure_channels(struct ThunderScopeH switch (num_channels_on) { case 0: - return false; + return THUNDERSCOPEHW_STATUS_NO_CHANNELS; case 1: on_channels[1] = on_channels[2] = on_channels[3] = on_channels[0]; From b6c9e37abd7324b356f1eb54e5eba0fd470e50af Mon Sep 17 00:00:00 2001 From: profezzorn <hubbe@hubbe.net> Date: Wed, 16 Feb 2022 10:21:41 -0800 Subject: [PATCH 10/13] fix dc couple options --- .../examples/thunderscopehwdump/thunderscopehwdump.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c b/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c index 94869fa7..2c28cb3e 100644 --- a/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c +++ b/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c @@ -50,10 +50,10 @@ struct Option options[] = { {"ac4", false, 0x44 }, {"dc-all", false, 0x50 }, - {"ac1", false, 0x51 }, - {"ac2", false, 0x52 }, - {"ac3", false, 0x53 }, - {"ac4", false, 0x54 }, + {"dc1", false, 0x51 }, + {"dc2", false, 0x52 }, + {"dc3", false, 0x53 }, + {"dc4", false, 0x54 }, {"enable-all", false, 0x60 }, {"enable1", false, 0x61 }, From f33a25602e5ed6caabe92e5e60ad0ebd6e8a8aff Mon Sep 17 00:00:00 2001 From: profezzorn <hubbe@hubbe.net> Date: Wed, 16 Feb 2022 21:10:30 -0800 Subject: [PATCH 11/13] various updates --- .../thunderscopehwcalibrate.c | 40 ++++++++++++++----- .../thunderscopehwdump/thunderscopehwdump.c | 11 ++++- .../library/thunderscopehw_internals.c | 4 +- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/Software/libthunderscopehw/examples/thunderscopehwcalibrate/thunderscopehwcalibrate.c b/Software/libthunderscopehw/examples/thunderscopehwcalibrate/thunderscopehwcalibrate.c index 7976afe9..bf1e27f8 100644 --- a/Software/libthunderscopehw/examples/thunderscopehwcalibrate/thunderscopehwcalibrate.c +++ b/Software/libthunderscopehw/examples/thunderscopehwcalibrate/thunderscopehwcalibrate.c @@ -17,12 +17,14 @@ struct Option { struct Option options[] = { {"device", true, 1 }, + {"verbose", false, 2 }, + {"retries", true, 3 }, }; #define TS_RUN(X) do { \ enum ThunderScopeHWStatus ret = thunderscopehw_##X; \ if (ret != THUNDERSCOPEHW_STATUS_OK) { \ - fprintf(stderr, "thunderscope_%s failed @ line %d, error = %s\n", #X, __LINE__, thunderscopehw_describe_error(ret)); \ + fprintf(stderr, "thunderscopehw_%s failed @ line %d, error = %s\n", #X, __LINE__, thunderscopehw_describe_error(ret)); \ exit(1); \ } \ } while(0) @@ -53,6 +55,8 @@ int mygetopt(int argc, char** argv) { } int main(int argc, char** argv) { + int verbose = 0; + int retries = 1; uint64_t scope_id = 0; uint64_t samples = 0; int samplerate = 0; @@ -64,6 +68,15 @@ int main(int argc, char** argv) { exit(1); } continue; + case 2: + verbose++; + continue; + case 3: + if (!sscanf(optarg, "%d", &retries)) { + fprintf(stderr, "--retries needs a number.\n"); + exit(1); + } + continue; default: continue; case -1: @@ -111,15 +124,20 @@ int main(int argc, char** argv) { usleep(500000); #endif - double minoffset = -0.5; - double maxoffset = 0.5; - - for (int i =0; i < 1000; i++) { + for (int i = 0; i < retries; i++) { + double minoffset = -0.5; + double maxoffset = 0.5; for (int j = 0; j < 20; j++) { double midoffset = (minoffset + maxoffset) / 2; TS_RUN(voltage_offset_set(ts, channel, midoffset)); TS_RUN(start(ts)); - TS_RUN(read(ts, buffer, BUFFER_SIZE)); + enum ThunderScopeHWStatus status = thunderscopehw_read(ts, buffer, BUFFER_SIZE); + if (status != THUNDERSCOPEHW_STATUS_OK) { + fprintf(stderr, "thunderscopehw_read failed, error = %s\n", thunderscopehw_describe_error(status)); + j--; + TS_RUN(stop(ts)); + continue; + } // Convert signed output to unsigned output for (size_t i = 0; i < BUFFER_SIZE; i++) { buffer[i] += 0x80; @@ -133,10 +151,12 @@ int main(int argc, char** argv) { if (buffer[i] < 0x80) low++; sum += buffer[i]; } -// fprintf(stderr," min = %8.4f max = %8.4f mid = %8.4f high=%d low=%d avg=%f\n", -// minoffset, maxoffset, midoffset, -// high, low, -// sum / (double)BUFFER_SIZE); + if (verbose) { + fprintf(stderr," min = %8.4f max = %8.4f mid = %8.4f high=%d low=%d avg=%f\n", + minoffset, maxoffset, midoffset, + high, low, + sum / (double)BUFFER_SIZE); + } if (high > low) { minoffset = midoffset; } else { diff --git a/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c b/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c index 2c28cb3e..26f20f56 100644 --- a/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c +++ b/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c @@ -5,6 +5,10 @@ #include <inttypes.h> #include <string.h> +#ifndef WIN32 +#include <unistd.h> +#endif + void write32(uint64_t x, FILE* f) { uint32_t v = 0; if (x < (uint64_t)0xFFFFFFFF) v = (uint32_t)x; @@ -168,7 +172,7 @@ int main(int argc, char** argv) { } break; case 3: // voffset - ret = thunderscopehw_voltage_offset_set(ts, channel, atoi(optarg)); + ret = thunderscopehw_voltage_offset_set(ts, channel, atof(optarg)); if (ret != THUNDERSCOPEHW_STATUS_OK) { fprintf(stderr, "Failed to set voffset. error =%s\n", thunderscopehw_describe_error(ret)); exit(1); @@ -235,6 +239,11 @@ int main(int argc, char** argv) { uint16_t block_align; uint16_t bits_per_sample; }; +#ifdef WIN32 + Sleep(500); +#else + usleep(500000); +#endif struct Fmt fmt; fmt.pcm = 1; diff --git a/Software/libthunderscopehw/library/thunderscopehw_internals.c b/Software/libthunderscopehw/library/thunderscopehw_internals.c index f178ae54..e3b491e2 100644 --- a/Software/libthunderscopehw/library/thunderscopehw_internals.c +++ b/Software/libthunderscopehw/library/thunderscopehw_internals.c @@ -156,8 +156,6 @@ enum ThunderScopeHWStatus thunderscopehw_configure_channels(struct ThunderScopeH switch (num_channels_on) { case 0: - return THUNDERSCOPEHW_STATUS_NO_CHANNELS; - case 1: on_channels[1] = on_channels[2] = on_channels[3] = on_channels[0]; clkdiv = 0; @@ -200,6 +198,8 @@ enum ThunderScopeHWStatus thunderscopehw_configure_channels(struct ThunderScopeH #else usleep(5000); #endif + /* No channels, leave data mover off. */ + if (num_channels_on == 0) return THUNDERSCOPEHW_STATUS_OK; return thunderscopehw_set_datamover_reg(ts); } From 9cc74528397aaf2641bb35d2a9e502f7f87f3dd2 Mon Sep 17 00:00:00 2001 From: profezzorn <hubbe@hubbe.net> Date: Wed, 16 Feb 2022 23:44:12 -0800 Subject: [PATCH 12/13] add thunderscopehwbench and some minor fixes --- Software/libthunderscopehw/CMakeLists.txt | 1 + .../thunderscopehwbench/CMakeLists.txt | 4 + .../thunderscopehwbench/thunderscopehwbench.c | 150 ++++++++++++++++++ .../thunderscopehwdump/thunderscopehwdump.c | 2 +- .../library/thunderscopehw.c | 4 +- 5 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 Software/libthunderscopehw/examples/thunderscopehwbench/CMakeLists.txt create mode 100644 Software/libthunderscopehw/examples/thunderscopehwbench/thunderscopehwbench.c diff --git a/Software/libthunderscopehw/CMakeLists.txt b/Software/libthunderscopehw/CMakeLists.txt index 0890d133..5b83eed1 100644 --- a/Software/libthunderscopehw/CMakeLists.txt +++ b/Software/libthunderscopehw/CMakeLists.txt @@ -7,6 +7,7 @@ project(thunderscopehwlib VERSION ${PROJECT_VERSION}) add_subdirectory(library) add_subdirectory(examples/thunderscopehwdump) add_subdirectory(examples/thunderscopehwcalibrate) +add_subdirectory(examples/thunderscopehwbench) enable_testing() add_subdirectory(test) diff --git a/Software/libthunderscopehw/examples/thunderscopehwbench/CMakeLists.txt b/Software/libthunderscopehw/examples/thunderscopehwbench/CMakeLists.txt new file mode 100644 index 00000000..22305733 --- /dev/null +++ b/Software/libthunderscopehw/examples/thunderscopehwbench/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(thunderscopehwbench + thunderscopehwbench.c) +target_link_libraries(thunderscopehwbench + thunderscopehwlib) diff --git a/Software/libthunderscopehw/examples/thunderscopehwbench/thunderscopehwbench.c b/Software/libthunderscopehw/examples/thunderscopehwbench/thunderscopehwbench.c new file mode 100644 index 00000000..0001b297 --- /dev/null +++ b/Software/libthunderscopehw/examples/thunderscopehwbench/thunderscopehwbench.c @@ -0,0 +1,150 @@ +#include "thunderscopehw.h" + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> + +#ifndef WIN32 +#include <unistd.h> +#include <sys/time.h> +#endif + + +static uint64_t time_ns(void) +{ +#ifdef WIN32 + struct timespec tv; + if (timespec_get(&ts, TIME_UTC) != TIME_UTC) + { + fprintf(stderr, "timespec_get failed!"); + exit(1); + } + return 1000000000 * ts.tv_sec + ts.tv_nsec; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return 1000000000 * tv.tv_sec + tv.tv_usec * 1000; +#endif +} + +struct Option { + const char* name; + bool needs_argument; + int return_value; +}; + +struct Option options[] = { + {"device", true, 1 }, + {"verbose", false, 2 }, + {"repeat", true, 3 }, +}; + +#define TS_RUN(X) do { \ + enum ThunderScopeHWStatus ret = thunderscopehw_##X; \ + if (ret != THUNDERSCOPEHW_STATUS_OK) { \ + fprintf(stderr, "thunderscopehw_%s failed @ line %d, error = %s\n", #X, __LINE__, thunderscopehw_describe_error(ret)); \ + exit(1); \ + } \ +} while(0) + +char* optarg; +int optind = 1; +int mygetopt(int argc, char** argv) { + if (optind >= argc) return -1; + if (!argv[optind][0] == '-' || argv[optind][1] != '-') return -1; + char *arg = strchr(argv[optind], '='); + for (size_t i = 0; i < sizeof(options) / sizeof(options[0]); i++) { + size_t len = strlen(options[i].name); + if (strncmp(options[i].name, argv[optind] + 2, len)) continue; + if (options[i].needs_argument) { + if (!arg) continue; + if (argv[optind] + 2 + len != arg) continue; + optarg = arg + 1; + } else { + if (arg) continue; + if (argv[optind][2 + len]) continue; + optarg = NULL; + } + optind++; + return options[i].return_value; + } + fprintf(stderr, "Unknown option: %s\n", argv[optind]); + exit(1); +} + +int main(int argc, char** argv) { + int verbose = 0; + int repeat = 1; + uint64_t scope_id = 0; + uint64_t samples = 0; + int samplerate = 0; + while (1) { + switch (mygetopt(argc, argv)) { + case 1: + if (!sscanf(optarg, "%" PRIx64, &scope_id)) { + fprintf(stderr, "Scope ID must be hexadecimal.\n"); + exit(1); + } + continue; + case 2: + verbose++; + continue; + case 3: + if (!sscanf(optarg, "%d", &repeat)) { + fprintf(stderr, "--repeat needs a number.\n"); + exit(1); + } + continue; + default: + continue; + case -1: + break; + } + break; + } + + if (scope_id == 0) { + uint64_t scope_ids[32]; + int scopes = thunderscopehw_scan(scope_ids, 32); + if (scopes == 0) { + fprintf(stderr, "No thunderscopehw hardware found.\n"); + exit(1); + } + if (scopes > 1) { + fprintf(stderr, "Multiple scopes found, please select one with --device.\n"); + for (int i = 0; i < scopes; i++) { + fprintf(stderr, " %0" PRIx64 "\n", scope_ids[i]); + } + exit(1); + } + scope_id = scope_ids[0]; + } + + // 32Mb +#define BUFFER_SIZE (32<<20) + uint8_t* buffer; +#ifdef _WIN32 + buffer = _aligned_malloc(BUFFER_SIZE, 4096); +#else + posix_memalign((void**)&buffer, 4096, BUFFER_SIZE); +#endif + + struct ThunderScopeHW *ts = thunderscopehw_create(); + enum ThunderScopeHWStatus ret; + TS_RUN(connect(ts, scope_id)); + + + TS_RUN(enable_channel(ts, 0)); + TS_RUN(start(ts)); + for (int i = 0; i < repeat; i++) { + uint64_t start = time_ns(); + uint64_t bytes = 0; + for (int j = 0; j < (1<<30) / BUFFER_SIZE; j++) { + TS_RUN(read(ts, buffer, BUFFER_SIZE)); + bytes += BUFFER_SIZE; + } + uint64_t end = time_ns(); + printf("Rate = %f Mib/s\n", bytes / 1000.0 / 1000.0 * 1000000000.0 / (end - start)); + } +} diff --git a/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c b/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c index 26f20f56..e29331cd 100644 --- a/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c +++ b/Software/libthunderscopehw/examples/thunderscopehwdump/thunderscopehwdump.c @@ -273,7 +273,7 @@ int main(int argc, char** argv) { exit(1); } -#define BUFFER_SIZE (1<<20) +#define BUFFER_SIZE samples uint8_t* buffer; #ifdef _WIN32 buffer = _aligned_malloc(BUFFER_SIZE, 4096); diff --git a/Software/libthunderscopehw/library/thunderscopehw.c b/Software/libthunderscopehw/library/thunderscopehw.c index 4bbd50da..0356e995 100644 --- a/Software/libthunderscopehw/library/thunderscopehw.c +++ b/Software/libthunderscopehw/library/thunderscopehw.c @@ -116,13 +116,13 @@ static enum ThunderScopeHWStatus thunderscopehw_update_buffer_head(struct Thunde uint32_t error_code = transfer_counter >> 30; if (error_code & 1) return THUNDERSCOPEHW_STATUS_DATAMOVER_ERROR; + if (error_code & 2) return THUNDERSCOPEHW_STATUS_FIFO_OVERFLOW; uint32_t overflow_cycles = (transfer_counter >> 16) & 0x3FFF; - if (overflow_cycles) { + if (overflow_cycles) return THUNDERSCOPEHW_STATUS_PIPELINE_OVERFLOW; - } uint32_t pages_moved = transfer_counter & 0xFFFF; uint64_t buffer_head = (ts->buffer_head & ~0xFFFFULL) | pages_moved; From 191b10304e44edb4157fe95b221b0e9be80ee761 Mon Sep 17 00:00:00 2001 From: profezzorn <hubbe@hubbe.net> Date: Thu, 17 Feb 2022 09:56:43 -0800 Subject: [PATCH 13/13] swap fifo/datamover error bits --- Software/libthunderscopehw/library/thunderscopehw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Software/libthunderscopehw/library/thunderscopehw.c b/Software/libthunderscopehw/library/thunderscopehw.c index 0356e995..1b8f2495 100644 --- a/Software/libthunderscopehw/library/thunderscopehw.c +++ b/Software/libthunderscopehw/library/thunderscopehw.c @@ -114,10 +114,10 @@ static enum ThunderScopeHWStatus thunderscopehw_update_buffer_head(struct Thunde // 1 page = 4k uint32_t transfer_counter = thunderscopehw_read32(ts, DATAMOVER_TRANSFER_COUNTER); uint32_t error_code = transfer_counter >> 30; - if (error_code & 1) + if (error_code & 2) return THUNDERSCOPEHW_STATUS_DATAMOVER_ERROR; - if (error_code & 2) + if (error_code & 1) return THUNDERSCOPEHW_STATUS_FIFO_OVERFLOW; uint32_t overflow_cycles = (transfer_counter >> 16) & 0x3FFF;