fix
This commit is contained in:
236
main.cpp
236
main.cpp
@ -506,9 +506,9 @@ void print_help(const char* exe_name) {
|
|||||||
<< " live_html/live_json -> live graph files updated as packets arrive outside tty+di1_group_avg fast mode\n"
|
<< " live_html/live_json -> live graph files updated as packets arrive outside tty+di1_group_avg fast mode\n"
|
||||||
<< " tty:/tmp/ttyADC_data -> write a continuous legacy 4-word CH1/CH2 stream; with channels:1, CH2 is 0\n"
|
<< " tty:/tmp/ttyADC_data -> write a continuous legacy 4-word CH1/CH2 stream; with channels:1, CH2 is 0\n"
|
||||||
<< " di1_group_avg -> with tty + di1:trace, emit one averaged 4-word step per constant DI1 run\n"
|
<< " di1_group_avg -> with tty + di1:trace, emit one averaged 4-word step per constant DI1 run\n"
|
||||||
<< " do1_toggle_per_frame -> DI_SYN2 level-gated DO1 modulation:\n"
|
<< " do1_toggle_per_frame -> hardware cyclic DO1 pattern in module memory:\n"
|
||||||
<< " DO1 is forced LOW when DI_SYN2 is LOW,\n"
|
<< " DO1 outputs 000111... continuously (toggle every 3 ADC ticks)\n"
|
||||||
<< " while DI_SYN2 is HIGH, DO1 toggles every 3 ADC ticks\n"
|
<< " without per-tick DOUT updates from PC\n"
|
||||||
<< " tty+di1_group_avg -> fast stream-only mode: skip CSV/SVG/live outputs and send only averaged tty data\n"
|
<< " tty+di1_group_avg -> fast stream-only mode: skip CSV/SVG/live outputs and send only averaged tty data\n"
|
||||||
<< " If sample_clock_hz is omitted together with clock:internal, the maximum ADC speed is used\n"
|
<< " If sample_clock_hz is omitted together with clock:internal, the maximum ADC speed is used\n"
|
||||||
<< "\n"
|
<< "\n"
|
||||||
@ -762,17 +762,6 @@ Config parse_args(int argc, char** argv) {
|
|||||||
cfg.input_buffer_words = std::max<uint32_t>(cfg.input_buffer_words, 16U * 1024U * 1024U);
|
cfg.input_buffer_words = std::max<uint32_t>(cfg.input_buffer_words, 16U * 1024U * 1024U);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cfg.do1_toggle_per_frame) {
|
|
||||||
if (!cfg.recv_block_specified) {
|
|
||||||
cfg.recv_block_words = 32U;
|
|
||||||
}
|
|
||||||
if (!cfg.input_step_specified) {
|
|
||||||
cfg.input_step_words = 32U;
|
|
||||||
}
|
|
||||||
if (!cfg.input_buffer_specified) {
|
|
||||||
cfg.input_buffer_words = std::max<uint32_t>(cfg.input_buffer_words, 256U * 1024U);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cfg.recv_block_words == 0) {
|
if (cfg.recv_block_words == 0) {
|
||||||
fail("recv_block must be > 0");
|
fail("recv_block must be > 0");
|
||||||
}
|
}
|
||||||
@ -785,9 +774,6 @@ Config parse_args(int argc, char** argv) {
|
|||||||
if (cfg.di1_group_average && (cfg.di1_mode != Di1Mode::Trace)) {
|
if (cfg.di1_group_average && (cfg.di1_mode != Di1Mode::Trace)) {
|
||||||
fail("di1_group_avg requires di1:trace");
|
fail("di1_group_avg requires di1:trace");
|
||||||
}
|
}
|
||||||
if (cfg.do1_toggle_per_frame && (cfg.channel_count != 2U)) {
|
|
||||||
fail("do1_toggle_per_frame requires channels:2");
|
|
||||||
}
|
|
||||||
if (sync_uses_di_syn1(cfg.sync_mode) && sync_uses_di_syn1(cfg.sync_start_mode)) {
|
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");
|
fail("clock and start cannot both use DI_SYN1; use start_in or immediate start");
|
||||||
}
|
}
|
||||||
@ -938,6 +924,7 @@ struct Api {
|
|||||||
decltype(&X502_GetAdcFreq) GetAdcFreq = nullptr;
|
decltype(&X502_GetAdcFreq) GetAdcFreq = nullptr;
|
||||||
decltype(&X502_SetDinFreq) SetDinFreq = nullptr;
|
decltype(&X502_SetDinFreq) SetDinFreq = nullptr;
|
||||||
decltype(&X502_SetOutFreq) SetOutFreq = nullptr;
|
decltype(&X502_SetOutFreq) SetOutFreq = nullptr;
|
||||||
|
decltype(&X502_AsyncOutDig) AsyncOutDig = nullptr;
|
||||||
decltype(&X502_SetRefFreq) SetRefFreq = nullptr;
|
decltype(&X502_SetRefFreq) SetRefFreq = nullptr;
|
||||||
decltype(&X502_SetStreamBufSize) SetStreamBufSize = nullptr;
|
decltype(&X502_SetStreamBufSize) SetStreamBufSize = nullptr;
|
||||||
decltype(&X502_SetStreamStep) SetStreamStep = nullptr;
|
decltype(&X502_SetStreamStep) SetStreamStep = nullptr;
|
||||||
@ -948,7 +935,9 @@ struct Api {
|
|||||||
decltype(&X502_StreamsStart) StreamsStart = nullptr;
|
decltype(&X502_StreamsStart) StreamsStart = nullptr;
|
||||||
decltype(&X502_GetRecvReadyCount) GetRecvReadyCount = nullptr;
|
decltype(&X502_GetRecvReadyCount) GetRecvReadyCount = nullptr;
|
||||||
decltype(&X502_Recv) Recv = nullptr;
|
decltype(&X502_Recv) Recv = nullptr;
|
||||||
decltype(&X502_PreloadStart) PreloadStart = nullptr;
|
decltype(&X502_OutCycleLoadStart) OutCycleLoadStart = nullptr;
|
||||||
|
decltype(&X502_OutCycleSetup) OutCycleSetup = nullptr;
|
||||||
|
decltype(&X502_OutCycleStop) OutCycleStop = nullptr;
|
||||||
decltype(&X502_Send) Send = nullptr;
|
decltype(&X502_Send) Send = nullptr;
|
||||||
decltype(&X502_PrepareData) PrepareData = nullptr;
|
decltype(&X502_PrepareData) PrepareData = nullptr;
|
||||||
decltype(&X502_ProcessData) ProcessData = nullptr;
|
decltype(&X502_ProcessData) ProcessData = nullptr;
|
||||||
@ -995,6 +984,7 @@ struct Api {
|
|||||||
GetAdcFreq = load_symbol<decltype(GetAdcFreq)>(x502_module, "X502_GetAdcFreq");
|
GetAdcFreq = load_symbol<decltype(GetAdcFreq)>(x502_module, "X502_GetAdcFreq");
|
||||||
SetDinFreq = load_symbol<decltype(SetDinFreq)>(x502_module, "X502_SetDinFreq");
|
SetDinFreq = load_symbol<decltype(SetDinFreq)>(x502_module, "X502_SetDinFreq");
|
||||||
SetOutFreq = load_symbol<decltype(SetOutFreq)>(x502_module, "X502_SetOutFreq");
|
SetOutFreq = load_symbol<decltype(SetOutFreq)>(x502_module, "X502_SetOutFreq");
|
||||||
|
AsyncOutDig = load_symbol<decltype(AsyncOutDig)>(x502_module, "X502_AsyncOutDig");
|
||||||
SetRefFreq = load_symbol<decltype(SetRefFreq)>(x502_module, "X502_SetRefFreq");
|
SetRefFreq = load_symbol<decltype(SetRefFreq)>(x502_module, "X502_SetRefFreq");
|
||||||
SetStreamBufSize = load_symbol<decltype(SetStreamBufSize)>(x502_module, "X502_SetStreamBufSize");
|
SetStreamBufSize = load_symbol<decltype(SetStreamBufSize)>(x502_module, "X502_SetStreamBufSize");
|
||||||
SetStreamStep = load_symbol<decltype(SetStreamStep)>(x502_module, "X502_SetStreamStep");
|
SetStreamStep = load_symbol<decltype(SetStreamStep)>(x502_module, "X502_SetStreamStep");
|
||||||
@ -1005,7 +995,9 @@ struct Api {
|
|||||||
StreamsStart = load_symbol<decltype(StreamsStart)>(x502_module, "X502_StreamsStart");
|
StreamsStart = load_symbol<decltype(StreamsStart)>(x502_module, "X502_StreamsStart");
|
||||||
GetRecvReadyCount = load_symbol<decltype(GetRecvReadyCount)>(x502_module, "X502_GetRecvReadyCount");
|
GetRecvReadyCount = load_symbol<decltype(GetRecvReadyCount)>(x502_module, "X502_GetRecvReadyCount");
|
||||||
Recv = load_symbol<decltype(Recv)>(x502_module, "X502_Recv");
|
Recv = load_symbol<decltype(Recv)>(x502_module, "X502_Recv");
|
||||||
PreloadStart = load_symbol<decltype(PreloadStart)>(x502_module, "X502_PreloadStart");
|
OutCycleLoadStart = try_load_symbol<decltype(OutCycleLoadStart)>(x502_module, "X502_OutCycleLoadStart");
|
||||||
|
OutCycleSetup = try_load_symbol<decltype(OutCycleSetup)>(x502_module, "X502_OutCycleSetup");
|
||||||
|
OutCycleStop = try_load_symbol<decltype(OutCycleStop)>(x502_module, "X502_OutCycleStop");
|
||||||
Send = load_symbol<decltype(Send)>(x502_module, "X502_Send");
|
Send = load_symbol<decltype(Send)>(x502_module, "X502_Send");
|
||||||
PrepareData = load_symbol<decltype(PrepareData)>(x502_module, "X502_PrepareData");
|
PrepareData = load_symbol<decltype(PrepareData)>(x502_module, "X502_PrepareData");
|
||||||
ProcessData = load_symbol<decltype(ProcessData)>(x502_module, "X502_ProcessData");
|
ProcessData = load_symbol<decltype(ProcessData)>(x502_module, "X502_ProcessData");
|
||||||
@ -1042,6 +1034,7 @@ constexpr uint32_t kE502Digital1Mask = (static_cast<uint32_t>(1U) << 0U);
|
|||||||
constexpr uint32_t kE502Digital2Mask = (static_cast<uint32_t>(1U) << 1U);
|
constexpr uint32_t kE502Digital2Mask = (static_cast<uint32_t>(1U) << 1U);
|
||||||
constexpr uint32_t kE502Do1Mask = (static_cast<uint32_t>(1U) << 0U);
|
constexpr uint32_t kE502Do1Mask = (static_cast<uint32_t>(1U) << 0U);
|
||||||
constexpr uint32_t kDo1TogglePeriodTicks = 3U;
|
constexpr uint32_t kDo1TogglePeriodTicks = 3U;
|
||||||
|
constexpr uint32_t kDo1CyclePatternWords = kDo1TogglePeriodTicks * 2U;
|
||||||
constexpr uint32_t kStreamInputAdcFlag = 0x80000000U;
|
constexpr uint32_t kStreamInputAdcFlag = 0x80000000U;
|
||||||
constexpr uint32_t kStreamInputCalibratedAdcFlag = 0x40000000U;
|
constexpr uint32_t kStreamInputCalibratedAdcFlag = 0x40000000U;
|
||||||
|
|
||||||
@ -1463,7 +1456,7 @@ int run(const Config& cfg) {
|
|||||||
<< ((cfg.channel_count >= 2U) ? phy_channel_name(cfg.mode, cfg.ch2) : std::string("disabled")) << "\n"
|
<< ((cfg.channel_count >= 2U) ? phy_channel_name(cfg.mode, cfg.ch2) : std::string("disabled")) << "\n"
|
||||||
<< " DI1 handling: " << di1_mode_to_string(cfg.di1_mode) << "\n"
|
<< " DI1 handling: " << di1_mode_to_string(cfg.di1_mode) << "\n"
|
||||||
<< " DO1 toggle per frame: "
|
<< " DO1 toggle per frame: "
|
||||||
<< (cfg.do1_toggle_per_frame ? std::string("enabled (DI_SYN2 level-gated, toggle each 3 ADC ticks, LOW outside HIGH)")
|
<< (cfg.do1_toggle_per_frame ? std::string("enabled (hardware cyclic 000111..., toggle every 3 ADC ticks)")
|
||||||
: std::string("disabled")) << "\n"
|
: std::string("disabled")) << "\n"
|
||||||
<< " DOUT rate: "
|
<< " DOUT rate: "
|
||||||
<< (cfg.do1_toggle_per_frame ? std::to_string(actual_dout_freq_hz) + " Hz" : std::string("disabled")) << "\n"
|
<< (cfg.do1_toggle_per_frame ? std::to_string(actual_dout_freq_hz) + " Hz" : std::string("disabled")) << "\n"
|
||||||
@ -1530,20 +1523,46 @@ int run(const Config& cfg) {
|
|||||||
std::cerr << "Warning: Ctrl+C handler could not be installed; continuous mode may stop abruptly.\n";
|
std::cerr << "Warning: Ctrl+C handler could not be installed; continuous mode may stop abruptly.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<uint32_t, kDo1CyclePatternWords> do1_cycle_pattern {};
|
||||||
|
std::array<uint32_t, kDo1CyclePatternWords> do1_cycle_encoded {};
|
||||||
if (cfg.do1_toggle_per_frame) {
|
if (cfg.do1_toggle_per_frame) {
|
||||||
expect_ok(api, api.PreloadStart(device.hnd), "Start DOUT preload");
|
if ((api.OutCycleLoadStart == nullptr) || (api.OutCycleSetup == nullptr) || (api.OutCycleStop == nullptr)) {
|
||||||
const uint32_t preload_low_word = 0U;
|
fail("do1_toggle_per_frame requires X502_OutCycle* API support (cyclic output mode)");
|
||||||
uint32_t preload_encoded_word = 0U;
|
}
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < do1_cycle_pattern.size(); ++i) {
|
||||||
|
do1_cycle_pattern[i] = (i < kDo1TogglePeriodTicks) ? 0U : kE502Do1Mask;
|
||||||
|
}
|
||||||
|
|
||||||
expect_ok(api,
|
expect_ok(api,
|
||||||
api.PrepareData(device.hnd, nullptr, nullptr, &preload_low_word, 1U, 0, &preload_encoded_word),
|
api.OutCycleLoadStart(device.hnd, static_cast<uint32_t>(do1_cycle_pattern.size())),
|
||||||
"Prepare initial DOUT LOW");
|
"Allocate cyclic DOUT buffer");
|
||||||
const int32_t preload_sent = api.Send(device.hnd, &preload_encoded_word, 1U, cfg.recv_timeout_ms);
|
expect_ok(api,
|
||||||
if (preload_sent < 0) {
|
api.PrepareData(device.hnd,
|
||||||
fail("Send initial DOUT LOW: " + x502_error(api, preload_sent));
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
do1_cycle_pattern.data(),
|
||||||
|
static_cast<uint32_t>(do1_cycle_pattern.size()),
|
||||||
|
0,
|
||||||
|
do1_cycle_encoded.data()),
|
||||||
|
"Prepare cyclic DOUT pattern");
|
||||||
|
|
||||||
|
std::size_t sent_cycle_words = 0;
|
||||||
|
while (sent_cycle_words < do1_cycle_encoded.size()) {
|
||||||
|
const int32_t sent = api.Send(device.hnd,
|
||||||
|
do1_cycle_encoded.data() + sent_cycle_words,
|
||||||
|
static_cast<uint32_t>(do1_cycle_encoded.size() - sent_cycle_words),
|
||||||
|
cfg.recv_timeout_ms);
|
||||||
|
if (sent < 0) {
|
||||||
|
fail("Send cyclic DOUT pattern: " + x502_error(api, sent));
|
||||||
}
|
}
|
||||||
if (preload_sent != 1) {
|
if (sent == 0) {
|
||||||
fail("Send initial DOUT LOW did not transmit exactly one word");
|
fail("Send cyclic DOUT pattern timed out before all words were queued");
|
||||||
}
|
}
|
||||||
|
sent_cycle_words += static_cast<std::size_t>(sent);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_ok(api, api.OutCycleSetup(device.hnd, X502_OUT_CYCLE_FLAGS_WAIT_DONE), "Activate cyclic DOUT pattern");
|
||||||
}
|
}
|
||||||
|
|
||||||
expect_ok(api, api.StreamsStart(device.hnd), "Start streams");
|
expect_ok(api, api.StreamsStart(device.hnd), "Start streams");
|
||||||
@ -1556,7 +1575,6 @@ int run(const Config& cfg) {
|
|||||||
std::deque<double> pending_adc;
|
std::deque<double> pending_adc;
|
||||||
std::deque<double> pending_adc_raw;
|
std::deque<double> pending_adc_raw;
|
||||||
std::deque<uint32_t> pending_din;
|
std::deque<uint32_t> pending_din;
|
||||||
std::deque<uint32_t> pending_dout;
|
|
||||||
std::deque<CapturePacket> packets;
|
std::deque<CapturePacket> packets;
|
||||||
PacketAccumulator current_packet;
|
PacketAccumulator current_packet;
|
||||||
TtyContinuousState tty_state;
|
TtyContinuousState tty_state;
|
||||||
@ -1587,20 +1605,6 @@ int run(const Config& cfg) {
|
|||||||
TickMs stats_window_start = capture_loop_start;
|
TickMs stats_window_start = capture_loop_start;
|
||||||
TickMs last_stats_print = capture_loop_start;
|
TickMs last_stats_print = capture_loop_start;
|
||||||
TickMs last_live_update = 0;
|
TickMs last_live_update = 0;
|
||||||
bool do1_output_high = false;
|
|
||||||
bool do1_gate_active = false;
|
|
||||||
uint32_t do1_ticks_since_toggle = 0;
|
|
||||||
uint64_t do1_packet_toggle_count = 0;
|
|
||||||
uint64_t do1_packet_queued_words = 0;
|
|
||||||
uint64_t do1_packet_sent_words_baseline = 0;
|
|
||||||
uint64_t do1_total_sent_words = 0;
|
|
||||||
const std::size_t max_pending_dout_words = 1000000U;
|
|
||||||
std::vector<uint32_t> dout_prepare_input;
|
|
||||||
std::vector<uint32_t> dout_send_words;
|
|
||||||
if (cfg.do1_toggle_per_frame) {
|
|
||||||
dout_prepare_input.resize(read_capacity_words);
|
|
||||||
dout_send_words.resize(read_capacity_words);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t total_raw_words = 0;
|
uint64_t total_raw_words = 0;
|
||||||
uint64_t total_adc_samples = 0;
|
uint64_t total_adc_samples = 0;
|
||||||
@ -1717,132 +1721,6 @@ int run(const Config& cfg) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto append_dout_word = [&](bool do1_high) {
|
|
||||||
if (!cfg.do1_toggle_per_frame) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pending_dout.push_back(do1_high ? kE502Do1Mask : 0U);
|
|
||||||
if (pending_dout.size() > max_pending_dout_words) {
|
|
||||||
fail("Internal DOUT backlog grew too large");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto flush_dout_queue = [&](uint32_t send_timeout_ms, bool require_full_flush) {
|
|
||||||
if (!cfg.do1_toggle_per_frame || pending_dout.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!pending_dout.empty()) {
|
|
||||||
const std::size_t chunk_words = std::min<std::size_t>(pending_dout.size(), dout_prepare_input.size());
|
|
||||||
for (std::size_t i = 0; i < chunk_words; ++i) {
|
|
||||||
dout_prepare_input[i] = pending_dout[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
expect_ok(api,
|
|
||||||
api.PrepareData(device.hnd,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
dout_prepare_input.data(),
|
|
||||||
static_cast<uint32_t>(chunk_words),
|
|
||||||
0,
|
|
||||||
dout_send_words.data()),
|
|
||||||
"Prepare DOUT data");
|
|
||||||
|
|
||||||
std::size_t sent_words = 0;
|
|
||||||
while (sent_words < chunk_words) {
|
|
||||||
const int32_t sent = api.Send(device.hnd,
|
|
||||||
dout_send_words.data() + sent_words,
|
|
||||||
static_cast<uint32_t>(chunk_words - sent_words),
|
|
||||||
send_timeout_ms);
|
|
||||||
if (sent < 0) {
|
|
||||||
fail("Send DOUT data: " + x502_error(api, sent));
|
|
||||||
}
|
|
||||||
if (sent == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sent_words += static_cast<std::size_t>(sent);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < sent_words; ++i) {
|
|
||||||
pending_dout.pop_front();
|
|
||||||
}
|
|
||||||
do1_total_sent_words += static_cast<uint64_t>(sent_words);
|
|
||||||
|
|
||||||
if (sent_words < chunk_words) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (require_full_flush && !pending_dout.empty()) {
|
|
||||||
fail("DOUT queue could not be fully flushed before shutdown");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto do1_queue_level = [&](bool do1_high, bool count_for_packet) {
|
|
||||||
if (!cfg.do1_toggle_per_frame) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
append_dout_word(do1_high);
|
|
||||||
if (count_for_packet) {
|
|
||||||
++do1_packet_queued_words;
|
|
||||||
}
|
|
||||||
if (do1_output_high != do1_high) {
|
|
||||||
if (count_for_packet) {
|
|
||||||
++do1_packet_toggle_count;
|
|
||||||
}
|
|
||||||
do1_output_high = do1_high;
|
|
||||||
} else {
|
|
||||||
do1_output_high = do1_high;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto do1_on_packet_start = [&]() {
|
|
||||||
if (!cfg.do1_toggle_per_frame) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
do1_packet_toggle_count = 0;
|
|
||||||
do1_packet_queued_words = 0;
|
|
||||||
do1_packet_sent_words_baseline = do1_total_sent_words;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto do1_on_tick = [&](bool di_syn2_high) {
|
|
||||||
if (!cfg.do1_toggle_per_frame) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bool next_state_high = false;
|
|
||||||
if (di_syn2_high) {
|
|
||||||
if (!do1_gate_active) {
|
|
||||||
do1_gate_active = true;
|
|
||||||
do1_ticks_since_toggle = 0U;
|
|
||||||
next_state_high = true;
|
|
||||||
} else if ((do1_ticks_since_toggle + 1U) >= kDo1TogglePeriodTicks) {
|
|
||||||
do1_ticks_since_toggle = 0U;
|
|
||||||
next_state_high = !do1_output_high;
|
|
||||||
} else {
|
|
||||||
++do1_ticks_since_toggle;
|
|
||||||
next_state_high = do1_output_high;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
do1_gate_active = false;
|
|
||||||
do1_ticks_since_toggle = 0U;
|
|
||||||
next_state_high = false;
|
|
||||||
}
|
|
||||||
do1_queue_level(next_state_high, packet_active);
|
|
||||||
};
|
|
||||||
|
|
||||||
auto do1_on_packet_end = [&](bool print_packet_stats) {
|
|
||||||
if (!cfg.do1_toggle_per_frame) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (print_packet_stats) {
|
|
||||||
const uint64_t packet_sent_words = do1_total_sent_words - do1_packet_sent_words_baseline;
|
|
||||||
std::cout << " DO1 stats: transitions=" << do1_packet_toggle_count
|
|
||||||
<< ", queued_words=" << do1_packet_queued_words
|
|
||||||
<< ", sent_words=" << packet_sent_words
|
|
||||||
<< ", state=" << (do1_output_high ? "HIGH" : "LOW") << "\n";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto start_packet = [&]() {
|
auto start_packet = [&]() {
|
||||||
if (packet_active) {
|
if (packet_active) {
|
||||||
return;
|
return;
|
||||||
@ -1859,7 +1737,6 @@ int run(const Config& cfg) {
|
|||||||
tty_group_state.reset_packet();
|
tty_group_state.reset_packet();
|
||||||
append_tty_packet_start();
|
append_tty_packet_start();
|
||||||
}
|
}
|
||||||
do1_on_packet_start();
|
|
||||||
packet_active = true;
|
packet_active = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1982,7 +1859,6 @@ int run(const Config& cfg) {
|
|||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
do1_on_packet_end(frames != 0U);
|
|
||||||
packet_active = false;
|
packet_active = false;
|
||||||
packet_avg_steps = 0;
|
packet_avg_steps = 0;
|
||||||
fast_packet_frames = 0;
|
fast_packet_frames = 0;
|
||||||
@ -2016,9 +1892,6 @@ int run(const Config& cfg) {
|
|||||||
|
|
||||||
uint32_t recv_request_words = cfg.recv_block_words;
|
uint32_t recv_request_words = cfg.recv_block_words;
|
||||||
uint32_t recv_timeout_ms = cfg.recv_timeout_ms;
|
uint32_t recv_timeout_ms = cfg.recv_timeout_ms;
|
||||||
if (cfg.do1_toggle_per_frame) {
|
|
||||||
recv_timeout_ms = 0U;
|
|
||||||
}
|
|
||||||
uint32_t ready_words = 0;
|
uint32_t ready_words = 0;
|
||||||
const int32_t ready_err = api.GetRecvReadyCount(device.hnd, &ready_words);
|
const int32_t ready_err = api.GetRecvReadyCount(device.hnd, &ready_words);
|
||||||
if ((ready_err == X502_ERR_OK) && (ready_words != 0U)) {
|
if ((ready_err == X502_ERR_OK) && (ready_words != 0U)) {
|
||||||
@ -2221,10 +2094,6 @@ int run(const Config& cfg) {
|
|||||||
}
|
}
|
||||||
trigger_prev_level = di_syn2_level;
|
trigger_prev_level = di_syn2_level;
|
||||||
}
|
}
|
||||||
if (cfg.do1_toggle_per_frame) {
|
|
||||||
do1_on_tick(di_syn2_level);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!packet_active && (cfg.sync_start_mode == X502_SYNC_INTERNAL)) {
|
if (!packet_active && (cfg.sync_start_mode == X502_SYNC_INTERNAL)) {
|
||||||
start_packet();
|
start_packet();
|
||||||
}
|
}
|
||||||
@ -2318,7 +2187,6 @@ int run(const Config& cfg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_dout_queue(0U, false);
|
|
||||||
flush_tty_frames();
|
flush_tty_frames();
|
||||||
|
|
||||||
if (console_stop_requested()) {
|
if (console_stop_requested()) {
|
||||||
@ -2335,12 +2203,14 @@ int run(const Config& cfg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cfg.do1_toggle_per_frame) {
|
if (cfg.do1_toggle_per_frame) {
|
||||||
do1_queue_level(false, false);
|
expect_ok(api, api.OutCycleStop(device.hnd, X502_OUT_CYCLE_FLAGS_WAIT_DONE), "Stop cyclic DOUT pattern");
|
||||||
flush_dout_queue(cfg.recv_timeout_ms, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expect_ok(api, api.StreamsStop(device.hnd), "Stop streams");
|
expect_ok(api, api.StreamsStop(device.hnd), "Stop streams");
|
||||||
device.streams_started = false;
|
device.streams_started = false;
|
||||||
|
if (cfg.do1_toggle_per_frame) {
|
||||||
|
expect_ok(api, api.AsyncOutDig(device.hnd, 0U, ~kE502Do1Mask), "Force DO1 LOW after cyclic DOUT stop");
|
||||||
|
}
|
||||||
|
|
||||||
if ((cfg.stats_period_ms != 0U) && ((stats_raw_words != 0U) || (stats_adc_samples != 0U) ||
|
if ((cfg.stats_period_ms != 0U) && ((stats_raw_words != 0U) || (stats_adc_samples != 0U) ||
|
||||||
(stats_din_samples != 0U) || (stats_stored_adc_samples != 0U) || (stats_zeroed_samples != 0U) ||
|
(stats_din_samples != 0U) || (stats_stored_adc_samples != 0U) || (stats_zeroed_samples != 0U) ||
|
||||||
|
|||||||
Reference in New Issue
Block a user