From ab18c539900e6c8776ca78b3ef0ac0fa5a8298f4 Mon Sep 17 00:00:00 2001 From: awe Date: Thu, 9 Apr 2026 13:36:44 +0300 Subject: [PATCH 1/2] test new format --- .codex | 0 main.cpp | 125 ++++++++++++++++++++++++++++++++++++++- tty_protocol_writer.cpp | 128 ++++++++++++++++++++++++++++++++++++++++ tty_protocol_writer.h | 29 +++++++++ 4 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 .codex create mode 100644 tty_protocol_writer.cpp create mode 100644 tty_protocol_writer.h diff --git a/.codex b/.codex new file mode 100644 index 0000000..e69de29 diff --git a/main.cpp b/main.cpp index 0cf51b5..2d3ddb6 100644 --- a/main.cpp +++ b/main.cpp @@ -15,6 +15,7 @@ #endif #include "capture_file_writer.h" +#include "tty_protocol_writer.h" #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -91,6 +93,7 @@ struct Config { std::string svg_path = "capture.svg"; std::string live_html_path = "live_plot.html"; std::string live_json_path = "live_plot.json"; + std::optional tty_path; }; [[noreturn]] void fail(const std::string& message) { @@ -371,7 +374,7 @@ void print_help(const char* exe_name) { << " [internal_ref_hz:2000000]\n" << " [di1:zero|trace|ignore]\n" << " [duration_ms:100] [packet_limit:0] [csv:capture.csv] [svg:capture.svg]\n" - << " [live_html:live_plot.html] [live_json:live_plot.json]\n" + << " [live_html:live_plot.html] [live_json:live_plot.json] [tty:/dev/ttyADC_data]\n" << " [recv_block:32768] [stats_period_ms:1000] [live_update_period_ms:1000] [svg_history_packets:50] [start_wait_ms:10000]\n" << " [buffer_words:8388608] [step_words:32768]\n" << " [pullup_syn1] [pullup_syn2] [pulldown_conv_in] [pulldown_start_in]\n" @@ -402,6 +405,7 @@ void print_help(const char* exe_name) { << " buffer_words:8388608 -> input stream buffer size in 32-bit words\n" << " step_words:32768 -> input stream transfer step in 32-bit words\n" << " live_html/live_json -> live graph files updated as packets arrive\n" + << " tty:/dev/ttyADC_data -> write binary step frames to a Linux/POSIX tty path\n" << " If sample_clock_hz is omitted together with clock:internal, the maximum ADC speed is used\n" << "\n" << "Differential physical channel mapping:\n" @@ -577,6 +581,10 @@ Config parse_args(int argc, char** argv) { cfg.live_json_path = arg.substr(10); continue; } + if (starts_with(arg, "tty:")) { + cfg.tty_path = arg.substr(4); + continue; + } fail("Unknown argument: " + arg); } @@ -616,6 +624,9 @@ Config parse_args(int argc, char** argv) { if (cfg.input_buffer_words < cfg.recv_block_words) { cfg.input_buffer_words = cfg.recv_block_words; } + if (cfg.tty_path && (cfg.channel_count != 2U)) { + fail("tty output requires channels:2"); + } if (sync_uses_di_syn1(cfg.sync_mode) && sync_uses_di_syn1(cfg.sync_start_mode)) { fail("clock and start cannot both use DI_SYN1; use start_in or immediate start"); } @@ -857,6 +868,48 @@ struct PacketAccumulator { } }; +struct TtyStepAccumulator { + double sum_ch1 = 0.0; + double sum_ch2 = 0.0; + uint32_t count_ch1 = 0; + uint32_t count_ch2 = 0; + uint32_t next_step_index = 1; + + void clear_step() { + sum_ch1 = 0.0; + sum_ch2 = 0.0; + count_ch1 = 0; + count_ch2 = 0; + } + + void reset_packet() { + clear_step(); + next_step_index = 1; + } + + void add_sample(uint32_t lch, double raw_code) { + if (lch == 0U) { + sum_ch1 += raw_code; + ++count_ch1; + } else if (lch == 1U) { + sum_ch2 += raw_code; + ++count_ch2; + } + } + + bool has_complete_step() const { + return (count_ch1 != 0U) && (count_ch2 != 0U); + } +}; + +int16_t pack_raw_code_to_int16(double avg_raw_code) { + const double scaled = + avg_raw_code * 32767.0 / static_cast(X502_ADC_SCALE_CODE_MAX); + const long long rounded = std::llround(scaled); + const long long clamped = std::clamp(rounded, -32768LL, 32767LL); + return static_cast(clamped); +} + struct ConsoleCtrlGuard { bool installed = false; @@ -1039,11 +1092,16 @@ int run(const Config& cfg) { << " ADC range: +/-" << range_to_volts(cfg.range) << " V\n" << " max frames per packet per channel: " << target_frames << "\n"; + std::unique_ptr tty_writer; + if (cfg.tty_path) { + tty_writer = std::make_unique(*cfg.tty_path); + } CaptureFileWriter writer(cfg.csv_path, cfg.svg_path, cfg.live_html_path, cfg.live_json_path); writer.initialize_live_plot(); writer.initialize_csv(cfg.channel_count, cfg.di1_mode == Di1Mode::Trace); std::cout << " live plot html: " << writer.live_html_path() << "\n" << " live plot data: " << writer.live_json_path() << "\n" + << " tty step output: " << (cfg.tty_path ? *cfg.tty_path : std::string("disabled")) << "\n" << " recv block words: " << cfg.recv_block_words << "\n" << " input step words: " << cfg.input_step_words << "\n" << " input buffer words: " << cfg.input_buffer_words << "\n" @@ -1062,11 +1120,14 @@ int run(const Config& cfg) { const uint32_t read_capacity_words = std::max(cfg.recv_block_words, cfg.input_step_words); std::vector raw(read_capacity_words); std::vector adc_buffer(read_capacity_words); + std::vector adc_raw_buffer(read_capacity_words); std::vector din_buffer(read_capacity_words); std::deque pending_adc; + std::deque pending_adc_raw; std::deque pending_din; std::deque packets; PacketAccumulator current_packet; + TtyStepAccumulator tty_step; current_packet.reset(target_frames, cfg.channel_count); std::size_t csv_global_frame_index = 0; @@ -1145,9 +1206,29 @@ int run(const Config& cfg) { return; } current_packet.reset(target_frames, cfg.channel_count); + if (tty_writer) { + tty_step.reset_packet(); + tty_writer->emit_packet_start(); + } packet_active = true; }; + auto emit_tty_step = [&]() { + if (!tty_writer || !tty_step.has_complete_step()) { + return; + } + if (tty_step.next_step_index >= 0xFFFFU) { + fail("TTY protocol step index overflow within packet"); + } + + const double ch1_avg = tty_step.sum_ch1 / static_cast(tty_step.count_ch1); + const double ch2_avg = tty_step.sum_ch2 / static_cast(tty_step.count_ch2); + tty_writer->emit_step(static_cast(tty_step.next_step_index), + pack_raw_code_to_int16(ch1_avg), + pack_raw_code_to_int16(ch2_avg)); + ++tty_step.next_step_index; + }; + auto finish_packet = [&](PacketCloseReason reason) { const std::size_t frames = current_packet.frame_count(cfg.channel_count); if (frames != 0U) { @@ -1230,6 +1311,7 @@ int run(const Config& cfg) { packet_active = false; current_packet.reset(target_frames, cfg.channel_count); + tty_step.clear_step(); }; while (!stop_loop_requested) { @@ -1309,7 +1391,24 @@ int run(const Config& cfg) { } expect_ok(api, process_err, "Process ADC+DIN data"); - if ((adc_count == 0U) && (din_count == 0U)) { + uint32_t raw_adc_count = 0; + if (tty_writer) { + raw_adc_count = static_cast(adc_raw_buffer.size()); + const int32_t raw_process_err = api.ProcessData(device.hnd, + raw.data(), + static_cast(recvd), + 0, + adc_raw_buffer.data(), + &raw_adc_count, + nullptr, + nullptr); + expect_ok(api, raw_process_err, "Process raw ADC data"); + if (raw_adc_count != adc_count) { + fail("Raw ADC processing returned a different sample count than voltage processing"); + } + } + + if ((adc_count == 0U) && (din_count == 0U) && (!tty_writer || (raw_adc_count == 0U))) { continue; } @@ -1321,19 +1420,31 @@ int run(const Config& cfg) { for (uint32_t i = 0; i < adc_count; ++i) { pending_adc.push_back(adc_buffer[i]); } + if (tty_writer) { + for (uint32_t i = 0; i < raw_adc_count; ++i) { + pending_adc_raw.push_back(adc_raw_buffer[i]); + } + } for (uint32_t i = 0; i < din_count; ++i) { pending_din.push_back(din_buffer[i]); } - if ((pending_adc.size() > 1000000U) || (pending_din.size() > 1000000U)) { + if ((pending_adc.size() > 1000000U) || + (pending_din.size() > 1000000U) || + (tty_writer && (pending_adc_raw.size() > 1000000U))) { fail("Internal backlog grew too large while aligning ADC and DIN samples"); } while (!pending_adc.empty() && !pending_din.empty() && + (!tty_writer || !pending_adc_raw.empty()) && !stop_loop_requested) { const double adc_value = pending_adc.front(); pending_adc.pop_front(); + const double adc_raw_value = tty_writer ? pending_adc_raw.front() : 0.0; + if (tty_writer) { + pending_adc_raw.pop_front(); + } const uint32_t din_value = pending_din.front(); pending_din.pop_front(); @@ -1391,6 +1502,11 @@ int run(const Config& cfg) { continue; } + if (tty_writer && di1_changed) { + emit_tty_step(); + tty_step.clear_step(); + } + const uint32_t lch = next_lch; next_lch = (next_lch + 1U) % cfg.channel_count; @@ -1409,6 +1525,9 @@ int run(const Config& cfg) { if (current_packet.channels[lch].size() < target_frames) { current_packet.channels[lch].push_back(stored_value); + if (tty_writer) { + tty_step.add_sample(lch, adc_raw_value); + } ++current_packet.stored_samples; ++total_stored_adc_samples; ++stats_stored_adc_samples; diff --git a/tty_protocol_writer.cpp b/tty_protocol_writer.cpp new file mode 100644 index 0000000..f7857c1 --- /dev/null +++ b/tty_protocol_writer.cpp @@ -0,0 +1,128 @@ +#include "tty_protocol_writer.h" + +#include +#include + +#ifdef _WIN32 + +TtyProtocolWriter::TtyProtocolWriter(std::string path) : path_(std::move(path)) { + throw std::runtime_error("tty output is supported only on Linux/POSIX"); +} + +TtyProtocolWriter::~TtyProtocolWriter() = default; + +TtyProtocolWriter::TtyProtocolWriter(TtyProtocolWriter&& other) noexcept = default; + +TtyProtocolWriter& TtyProtocolWriter::operator=(TtyProtocolWriter&& other) noexcept = default; + +void TtyProtocolWriter::emit_packet_start() const {} + +void TtyProtocolWriter::emit_step(uint16_t index, int16_t ch1_avg, int16_t ch2_avg) const { + (void) index; + (void) ch1_avg; + (void) ch2_avg; +} + +const std::string& TtyProtocolWriter::path() const { + return path_; +} + +void TtyProtocolWriter::write_frame(uint16_t word0, uint16_t word1, uint16_t word2, uint16_t word3) const { + (void) word0; + (void) word1; + (void) word2; + (void) word3; +} + +void TtyProtocolWriter::close_fd() noexcept {} + +#else + +#include +#include +#include +#include +#include +#include + +namespace { + +std::string io_error(const std::string& action, const std::string& path) { + std::ostringstream out; + out << action << " '" << path << "': " << std::strerror(errno); + return out.str(); +} + +} // namespace + +TtyProtocolWriter::TtyProtocolWriter(std::string path) : path_(std::move(path)) { + fd_ = ::open(path_.c_str(), O_WRONLY | O_NOCTTY); + if (fd_ < 0) { + throw std::runtime_error(io_error("Cannot open tty output", path_)); + } +} + +TtyProtocolWriter::~TtyProtocolWriter() { + close_fd(); +} + +TtyProtocolWriter::TtyProtocolWriter(TtyProtocolWriter&& other) noexcept + : path_(std::move(other.path_)), + fd_(other.fd_) { + other.fd_ = -1; +} + +TtyProtocolWriter& TtyProtocolWriter::operator=(TtyProtocolWriter&& other) noexcept { + if (this != &other) { + close_fd(); + path_ = std::move(other.path_); + fd_ = other.fd_; + other.fd_ = -1; + } + return *this; +} + +void TtyProtocolWriter::emit_packet_start() const { + write_frame(0x000A, 0xFFFF, 0xFFFF, 0xFFFF); +} + +void TtyProtocolWriter::emit_step(uint16_t index, int16_t ch1_avg, int16_t ch2_avg) const { + write_frame(0x000A, + index, + static_cast(ch1_avg), + static_cast(ch2_avg)); +} + +const std::string& TtyProtocolWriter::path() const { + return path_; +} + +void TtyProtocolWriter::write_frame(uint16_t word0, uint16_t word1, uint16_t word2, uint16_t word3) const { + const uint16_t frame[4] = {word0, word1, word2, word3}; + const std::uint8_t* bytes = reinterpret_cast(frame); + std::size_t remaining = sizeof(frame); + + while (remaining != 0U) { + const ssize_t written = ::write(fd_, bytes, remaining); + if (written < 0) { + if (errno == EINTR) { + continue; + } + throw std::runtime_error(io_error("Cannot write tty frame to", path_)); + } + if (written == 0) { + throw std::runtime_error("tty write returned 0 bytes for '" + path_ + "'"); + } + bytes += static_cast(written); + remaining -= static_cast(written); + } +} + +void TtyProtocolWriter::close_fd() noexcept { + if (fd_ >= 0) { + ::close(fd_); + fd_ = -1; + } +} + +#endif diff --git a/tty_protocol_writer.h b/tty_protocol_writer.h new file mode 100644 index 0000000..295e0c5 --- /dev/null +++ b/tty_protocol_writer.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +class TtyProtocolWriter { +public: + explicit TtyProtocolWriter(std::string path); + ~TtyProtocolWriter(); + + TtyProtocolWriter(const TtyProtocolWriter&) = delete; + TtyProtocolWriter& operator=(const TtyProtocolWriter&) = delete; + TtyProtocolWriter(TtyProtocolWriter&& other) noexcept; + TtyProtocolWriter& operator=(TtyProtocolWriter&& other) noexcept; + + void emit_packet_start() const; + void emit_step(uint16_t index, int16_t ch1_avg, int16_t ch2_avg) const; + + const std::string& path() const; + +private: + void write_frame(uint16_t word0, uint16_t word1, uint16_t word2, uint16_t word3) const; + void close_fd() noexcept; + + std::string path_; +#ifndef _WIN32 + int fd_ = -1; +#endif +}; From fc66e62b5b74067003c296c992df59561506f1cc Mon Sep 17 00:00:00 2001 From: awe Date: Thu, 9 Apr 2026 13:52:10 +0300 Subject: [PATCH 2/2] fix --- main.cpp | 202 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 170 insertions(+), 32 deletions(-) diff --git a/main.cpp b/main.cpp index 2d3ddb6..6aeb63a 100644 --- a/main.cpp +++ b/main.cpp @@ -19,6 +19,8 @@ #include #include +#include +#include #include #include #include @@ -34,6 +36,11 @@ #include #include +#ifndef _WIN32 + #include + #include +#endif + namespace { enum class StopMode { @@ -662,18 +669,87 @@ Config parse_args(int argc, char** argv) { return cfg; } +#ifdef _WIN32 +using ModuleHandle = HMODULE; +#else +using ModuleHandle = void*; +#endif + +std::string dynamic_loader_error() { +#ifdef _WIN32 + return "unknown error"; +#else + const char* error = dlerror(); + return ((error != nullptr) && (*error != '\0')) ? std::string(error) : std::string("unknown error"); +#endif +} + +ModuleHandle open_library(const char* path) { +#ifdef _WIN32 + return LoadLibraryA(path); +#else + dlerror(); + return dlopen(path, RTLD_LAZY | RTLD_LOCAL); +#endif +} + +void close_library(ModuleHandle module) { +#ifdef _WIN32 + if (module != nullptr) { + FreeLibrary(module); + } +#else + if (module != nullptr) { + dlclose(module); + } +#endif +} + +ModuleHandle load_library_or_fail(const std::vector& candidates, + const std::string& description) { + std::string last_error = "no candidates provided"; + for (const auto& candidate : candidates) { + ModuleHandle module = open_library(candidate.c_str()); + if (module != nullptr) { + return module; + } + last_error = dynamic_loader_error(); + } + + std::ostringstream out; + out << "Cannot load " << description << ". Tried:"; + for (const auto& candidate : candidates) { + out << " " << candidate; + } + out << ". Last error: " << last_error; + fail(out.str()); +} + template -Fn load_symbol(HMODULE module, const char* name) { +Fn load_symbol(ModuleHandle module, const char* name) { +#ifdef _WIN32 const auto addr = GetProcAddress(module, name); if (addr == nullptr) { fail(std::string("GetProcAddress failed for symbol: ") + name); } return reinterpret_cast(addr); +#else + dlerror(); + void* addr = dlsym(module, name); + const char* error = dlerror(); + if ((addr == nullptr) || (error != nullptr)) { + std::ostringstream out; + out << "dlsym failed for symbol " << name << ": " + << ((error != nullptr) ? error : "unknown error"); + fail(out.str()); + } + return reinterpret_cast(addr); +#endif } struct Api { - HMODULE x502_module = nullptr; - HMODULE e502_module = nullptr; + ModuleHandle x502_module = nullptr; + ModuleHandle e502_module = nullptr; decltype(&X502_Create) Create = nullptr; decltype(&X502_Free) Free = nullptr; @@ -709,14 +785,20 @@ struct Api { decltype(&E502_OpenByIpAddr) OpenByIpAddr = nullptr; Api() { - x502_module = LoadLibraryA("x502api.dll"); - if (x502_module == nullptr) { - fail("Cannot load x502api.dll"); - } - e502_module = LoadLibraryA("e502api.dll"); - if (e502_module == nullptr) { - fail("Cannot load e502api.dll"); - } + x502_module = load_library_or_fail( +#ifdef _WIN32 + {"x502api.dll"}, +#else + {"libx502api.so", "x502api.so", "./libx502api.so", "./x502api.so"}, +#endif + "x502 API library"); + e502_module = load_library_or_fail( +#ifdef _WIN32 + {"e502api.dll"}, +#else + {"libe502api.so", "e502api.so", "./libe502api.so", "./e502api.so"}, +#endif + "e502 API library"); Create = load_symbol(x502_module, "X502_Create"); Free = load_symbol(x502_module, "X502_Free"); @@ -753,12 +835,8 @@ struct Api { } ~Api() { - if (e502_module != nullptr) { - FreeLibrary(e502_module); - } - if (x502_module != nullptr) { - FreeLibrary(x502_module); - } + close_library(e502_module); + close_library(x502_module); } }; @@ -782,6 +860,19 @@ constexpr uint32_t kE502DiSyn2Mask = (static_cast(1U) << 13U) | (static_cast(1U) << 17U); constexpr uint32_t kE502Digital1Mask = (static_cast(1U) << 0U); +using TickMs = uint64_t; + +TickMs tick_count_ms() { +#ifdef _WIN32 + return static_cast(GetTickCount64()); +#else + using namespace std::chrono; + return static_cast( + duration_cast(steady_clock::now().time_since_epoch()).count()); +#endif +} + +#ifdef _WIN32 volatile LONG g_console_stop_requested = 0; BOOL WINAPI console_ctrl_handler(DWORD ctrl_type) { @@ -795,6 +886,17 @@ BOOL WINAPI console_ctrl_handler(DWORD ctrl_type) { bool console_stop_requested() { return InterlockedCompareExchange(&g_console_stop_requested, 0, 0) != 0; } +#else +volatile std::sig_atomic_t g_console_stop_requested = 0; + +void console_ctrl_handler(int) { + g_console_stop_requested = 1; +} + +bool console_stop_requested() { + return g_console_stop_requested != 0; +} +#endif enum class PacketCloseReason { ExternalStopEdge, @@ -913,16 +1015,52 @@ int16_t pack_raw_code_to_int16(double avg_raw_code) { struct ConsoleCtrlGuard { bool installed = false; +#ifndef _WIN32 + bool sigint_installed = false; + bool sigterm_installed = false; + bool sigabrt_installed = false; + struct sigaction old_sigint {}; + struct sigaction old_sigterm {}; + struct sigaction old_sigabrt {}; +#endif + ConsoleCtrlGuard() { +#ifdef _WIN32 InterlockedExchange(&g_console_stop_requested, 0); installed = SetConsoleCtrlHandler(console_ctrl_handler, TRUE) != 0; +#else + g_console_stop_requested = 0; + + struct sigaction action {}; + action.sa_handler = console_ctrl_handler; + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + + sigint_installed = sigaction(SIGINT, &action, &old_sigint) == 0; + sigterm_installed = sigaction(SIGTERM, &action, &old_sigterm) == 0; + sigabrt_installed = sigaction(SIGABRT, &action, &old_sigabrt) == 0; + installed = sigint_installed && sigterm_installed && sigabrt_installed; +#endif } ~ConsoleCtrlGuard() { +#ifdef _WIN32 if (installed) { SetConsoleCtrlHandler(console_ctrl_handler, FALSE); } InterlockedExchange(&g_console_stop_requested, 0); +#else + if (sigint_installed) { + sigaction(SIGINT, &old_sigint, nullptr); + } + if (sigterm_installed) { + sigaction(SIGTERM, &old_sigterm, nullptr); + } + if (sigabrt_installed) { + sigaction(SIGABRT, &old_sigabrt, nullptr); + } + g_console_stop_requested = 0; +#endif } }; @@ -1140,11 +1278,11 @@ int run(const Config& cfg) { uint32_t next_lch = 0; bool di1_initialized = false; bool di1_prev_level = false; - const ULONGLONG start_wait_deadline = GetTickCount64() + cfg.start_wait_ms; - const ULONGLONG capture_loop_start = GetTickCount64(); - ULONGLONG stats_window_start = capture_loop_start; - ULONGLONG last_stats_print = capture_loop_start; - ULONGLONG last_live_update = 0; + const TickMs start_wait_deadline = tick_count_ms() + cfg.start_wait_ms; + const TickMs capture_loop_start = tick_count_ms(); + TickMs stats_window_start = capture_loop_start; + TickMs last_stats_print = capture_loop_start; + TickMs last_live_update = 0; uint64_t total_raw_words = 0; uint64_t total_adc_samples = 0; @@ -1162,7 +1300,7 @@ int run(const Config& cfg) { uint64_t stats_completed_packets = 0; auto print_stats = [&](bool final_report) { - const ULONGLONG now = GetTickCount64(); + const TickMs now = tick_count_ms(); const double elapsed_s = std::max(1e-9, static_cast(now - stats_window_start) / 1000.0); const double mb_per_s = (static_cast(stats_raw_words) * sizeof(uint32_t)) / elapsed_s / 1000.0 / 1000.0; const double adc_samples_per_s = static_cast(stats_adc_samples) / elapsed_s; @@ -1281,12 +1419,12 @@ int run(const Config& cfg) { } const double elapsed_capture_s = - std::max(1e-9, static_cast(GetTickCount64() - capture_loop_start) / 1000.0); + std::max(1e-9, static_cast(tick_count_ms() - capture_loop_start) / 1000.0); const double packets_per_second = (elapsed_capture_s >= 0.1) ? (static_cast(total_completed_packets) / elapsed_capture_s) : 0.0; - const ULONGLONG now = GetTickCount64(); + const TickMs now = tick_count_ms(); const bool should_update_live = (cfg.live_update_period_ms == 0U) || (last_live_update == 0U) || @@ -1345,7 +1483,7 @@ int run(const Config& cfg) { stats_raw_words += static_cast(recvd); } if (recvd == 0) { - if (!capture_started && (GetTickCount64() >= start_wait_deadline)) { + if (!capture_started && (tick_count_ms() >= start_wait_deadline)) { std::ostringstream message; message << "Timeout before first ADC data. start=" << sync_mode_to_string(cfg.sync_start_mode, true) @@ -1558,7 +1696,7 @@ int run(const Config& cfg) { stop_loop_requested = true; } - if ((cfg.stats_period_ms != 0U) && ((GetTickCount64() - last_stats_print) >= cfg.stats_period_ms)) { + if ((cfg.stats_period_ms != 0U) && ((tick_count_ms() - last_stats_print) >= cfg.stats_period_ms)) { print_stats(false); } } @@ -1592,20 +1730,20 @@ int run(const Config& cfg) { std::cout << "Average stats: " << "MB/s=" << std::fixed << std::setprecision(3) << ((static_cast(total_raw_words) * sizeof(uint32_t)) / - std::max(1e-9, static_cast(GetTickCount64() - capture_loop_start) / 1000.0) / + std::max(1e-9, static_cast(tick_count_ms() - capture_loop_start) / 1000.0) / 1000.0 / 1000.0) << ", ADC samples/s=" << (static_cast(total_adc_samples) / - std::max(1e-9, static_cast(GetTickCount64() - capture_loop_start) / 1000.0)) + std::max(1e-9, static_cast(tick_count_ms() - capture_loop_start) / 1000.0)) << ", DIN samples/s=" << (static_cast(total_din_samples) / - std::max(1e-9, static_cast(GetTickCount64() - capture_loop_start) / 1000.0)) + std::max(1e-9, static_cast(tick_count_ms() - capture_loop_start) / 1000.0)) << ", frames/s per channel=" << (static_cast(total_completed_frames) / - std::max(1e-9, static_cast(GetTickCount64() - capture_loop_start) / 1000.0)) + std::max(1e-9, static_cast(tick_count_ms() - capture_loop_start) / 1000.0)) << ", packets/s=" << (static_cast(total_completed_packets) / - std::max(1e-9, static_cast(GetTickCount64() - capture_loop_start) / 1000.0)) + std::max(1e-9, static_cast(tick_count_ms() - capture_loop_start) / 1000.0)) << ", packets captured=" << total_completed_packets; if (cfg.di1_mode == Di1Mode::ZeroOnChange) { std::cout << ", zeroed on DI1 change="