Compare commits
2 Commits
00dc0e21b7
...
71bf90f003
| Author | SHA1 | Date | |
|---|---|---|---|
| 71bf90f003 | |||
| f462e65cc2 |
145
main.cpp
145
main.cpp
@ -113,6 +113,7 @@ struct Config {
|
|||||||
std::string live_json_path = "live_plot.json";
|
std::string live_json_path = "live_plot.json";
|
||||||
std::optional<std::string> tty_path;
|
std::optional<std::string> tty_path;
|
||||||
bool di1_group_average = false;
|
bool di1_group_average = false;
|
||||||
|
bool do1_toggle_per_frame = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[noreturn]] void fail(const std::string& message) {
|
[[noreturn]] void fail(const std::string& message) {
|
||||||
@ -470,6 +471,7 @@ void print_help(const char* exe_name) {
|
|||||||
<< " [di1:zero|trace|ignore]\n"
|
<< " [di1:zero|trace|ignore]\n"
|
||||||
<< " [duration_ms:100] [packet_limit:0] [csv:capture.csv] [svg:capture.svg]\n"
|
<< " [duration_ms:100] [packet_limit:0] [csv:capture.csv] [svg:capture.svg]\n"
|
||||||
<< " [live_html:live_plot.html] [live_json:live_plot.json] [tty:/tmp/ttyADC_data] [di1_group_avg]\n"
|
<< " [live_html:live_plot.html] [live_json:live_plot.json] [tty:/tmp/ttyADC_data] [di1_group_avg]\n"
|
||||||
|
<< " [do1_toggle_per_frame]\n"
|
||||||
<< " [recv_block:32768] [stats_period_ms:1000] [live_update_period_ms:1000] [svg_history_packets:50] [start_wait_ms:10000]\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"
|
<< " [buffer_words:8388608] [step_words:32768]\n"
|
||||||
<< " [pullup_syn1] [pullup_syn2] [pulldown_conv_in] [pulldown_start_in]\n"
|
<< " [pullup_syn1] [pullup_syn2] [pulldown_conv_in] [pulldown_start_in]\n"
|
||||||
@ -504,6 +506,8 @@ 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 -> packet-gated DO1 output: LOW,HIGH,LOW,HIGH per 2-channel frame inside packet\n"
|
||||||
|
<< " outside packet windows DO1 is forced LOW\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"
|
||||||
@ -631,6 +635,10 @@ Config parse_args(int argc, char** argv) {
|
|||||||
cfg.di1_group_average = true;
|
cfg.di1_group_average = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (arg == "do1_toggle_per_frame") {
|
||||||
|
cfg.do1_toggle_per_frame = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (starts_with(arg, "sample_clock_hz:")) {
|
if (starts_with(arg, "sample_clock_hz:")) {
|
||||||
const std::string value = trim_copy(arg.substr(16));
|
const std::string value = trim_copy(arg.substr(16));
|
||||||
cfg.sample_clock_specified = true;
|
cfg.sample_clock_specified = true;
|
||||||
@ -765,6 +773,9 @@ 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");
|
||||||
}
|
}
|
||||||
@ -914,6 +925,7 @@ struct Api {
|
|||||||
decltype(&X502_SetAdcFreq) SetAdcFreq = nullptr;
|
decltype(&X502_SetAdcFreq) SetAdcFreq = nullptr;
|
||||||
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_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;
|
||||||
@ -924,6 +936,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_Send) Send = nullptr;
|
||||||
|
decltype(&X502_PrepareData) PrepareData = nullptr;
|
||||||
decltype(&X502_ProcessData) ProcessData = nullptr;
|
decltype(&X502_ProcessData) ProcessData = nullptr;
|
||||||
|
|
||||||
decltype(&E502_OpenUsb) OpenUsb = nullptr;
|
decltype(&E502_OpenUsb) OpenUsb = nullptr;
|
||||||
@ -967,6 +982,7 @@ struct Api {
|
|||||||
SetAdcFreq = load_symbol<decltype(SetAdcFreq)>(x502_module, "X502_SetAdcFreq");
|
SetAdcFreq = load_symbol<decltype(SetAdcFreq)>(x502_module, "X502_SetAdcFreq");
|
||||||
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");
|
||||||
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");
|
||||||
@ -977,6 +993,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");
|
||||||
|
Send = load_symbol<decltype(Send)>(x502_module, "X502_Send");
|
||||||
|
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");
|
||||||
|
|
||||||
OpenUsb = load_symbol<decltype(OpenUsb)>(e502_module, "E502_OpenUsb");
|
OpenUsb = load_symbol<decltype(OpenUsb)>(e502_module, "E502_OpenUsb");
|
||||||
@ -1009,6 +1028,7 @@ constexpr uint32_t kE502DiSyn2Mask =
|
|||||||
(static_cast<uint32_t>(1U) << 13U) | (static_cast<uint32_t>(1U) << 17U);
|
(static_cast<uint32_t>(1U) << 13U) | (static_cast<uint32_t>(1U) << 17U);
|
||||||
constexpr uint32_t kE502Digital1Mask = (static_cast<uint32_t>(1U) << 0U);
|
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 kStreamInputAdcFlag = 0x80000000U;
|
constexpr uint32_t kStreamInputAdcFlag = 0x80000000U;
|
||||||
constexpr uint32_t kStreamInputCalibratedAdcFlag = 0x40000000U;
|
constexpr uint32_t kStreamInputCalibratedAdcFlag = 0x40000000U;
|
||||||
|
|
||||||
@ -1361,9 +1381,20 @@ int run(const Config& cfg) {
|
|||||||
<< " words/s, while the documented Ethernet input-only limit is about 2500000 words/s.";
|
<< " words/s, while the documented Ethernet input-only limit is about 2500000 words/s.";
|
||||||
fail(message.str());
|
fail(message.str());
|
||||||
}
|
}
|
||||||
|
double actual_dout_freq_hz = actual_frame_freq_hz;
|
||||||
|
if (cfg.do1_toggle_per_frame) {
|
||||||
|
if (actual_frame_freq_hz <= 0.0) {
|
||||||
|
fail("do1_toggle_per_frame requires a positive ADC frame rate");
|
||||||
|
}
|
||||||
|
expect_ok(api, api.SetOutFreq(device.hnd, &actual_dout_freq_hz), "Set DOUT frequency");
|
||||||
|
}
|
||||||
|
|
||||||
expect_ok(api, api.SetStreamBufSize(device.hnd, X502_STREAM_CH_IN, cfg.input_buffer_words), "Set input buffer size");
|
expect_ok(api, api.SetStreamBufSize(device.hnd, X502_STREAM_CH_IN, cfg.input_buffer_words), "Set input buffer size");
|
||||||
expect_ok(api, api.SetStreamStep(device.hnd, X502_STREAM_CH_IN, cfg.input_step_words), "Set input stream step");
|
expect_ok(api, api.SetStreamStep(device.hnd, X502_STREAM_CH_IN, cfg.input_step_words), "Set input stream step");
|
||||||
|
if (cfg.do1_toggle_per_frame) {
|
||||||
|
expect_ok(api, api.SetStreamBufSize(device.hnd, X502_STREAM_CH_OUT, cfg.input_buffer_words), "Set output buffer size");
|
||||||
|
expect_ok(api, api.SetStreamStep(device.hnd, X502_STREAM_CH_OUT, cfg.input_step_words), "Set output stream step");
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t pullups = 0;
|
uint32_t pullups = 0;
|
||||||
if (cfg.pullup_syn1) {
|
if (cfg.pullup_syn1) {
|
||||||
@ -1381,7 +1412,11 @@ int run(const Config& cfg) {
|
|||||||
expect_ok(api, api.SetDigInPullup(device.hnd, pullups), "Set digital input pullups/pulldowns");
|
expect_ok(api, api.SetDigInPullup(device.hnd, pullups), "Set digital input pullups/pulldowns");
|
||||||
|
|
||||||
expect_ok(api, api.Configure(device.hnd, 0), "Configure device");
|
expect_ok(api, api.Configure(device.hnd, 0), "Configure device");
|
||||||
expect_ok(api, api.StreamsEnable(device.hnd, X502_STREAM_ADC | X502_STREAM_DIN), "Enable ADC+DIN stream");
|
uint32_t enabled_streams = X502_STREAM_ADC | X502_STREAM_DIN;
|
||||||
|
if (cfg.do1_toggle_per_frame) {
|
||||||
|
enabled_streams |= X502_STREAM_DOUT;
|
||||||
|
}
|
||||||
|
expect_ok(api, api.StreamsEnable(device.hnd, enabled_streams), "Enable data streams");
|
||||||
|
|
||||||
const std::size_t target_frames = std::max<std::size_t>(
|
const std::size_t target_frames = std::max<std::size_t>(
|
||||||
1, static_cast<std::size_t>(std::llround((cfg.duration_ms / 1000.0) * actual_frame_freq_hz)));
|
1, static_cast<std::size_t>(std::llround((cfg.duration_ms / 1000.0) * actual_frame_freq_hz)));
|
||||||
@ -1413,6 +1448,10 @@ int run(const Config& cfg) {
|
|||||||
<< " channel 2: "
|
<< " channel 2: "
|
||||||
<< ((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: "
|
||||||
|
<< (cfg.do1_toggle_per_frame ? std::string("enabled (packet-gated, LOW-first)") : std::string("disabled")) << "\n"
|
||||||
|
<< " DOUT rate: "
|
||||||
|
<< (cfg.do1_toggle_per_frame ? std::to_string(actual_dout_freq_hz) + " Hz" : std::string("disabled")) << "\n"
|
||||||
<< " ADC range: +/-" << range_to_volts(cfg.range) << " V\n"
|
<< " ADC range: +/-" << range_to_volts(cfg.range) << " V\n"
|
||||||
<< " max frames per packet per channel: " << target_frames << "\n";
|
<< " max frames per packet per channel: " << target_frames << "\n";
|
||||||
|
|
||||||
@ -1476,6 +1515,22 @@ 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";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cfg.do1_toggle_per_frame) {
|
||||||
|
expect_ok(api, api.PreloadStart(device.hnd), "Start DOUT preload");
|
||||||
|
const uint32_t preload_low_word = 0U;
|
||||||
|
uint32_t preload_encoded_word = 0U;
|
||||||
|
expect_ok(api,
|
||||||
|
api.PrepareData(device.hnd, nullptr, nullptr, &preload_low_word, 1U, 0, &preload_encoded_word),
|
||||||
|
"Prepare initial DOUT LOW");
|
||||||
|
const int32_t preload_sent = api.Send(device.hnd, &preload_encoded_word, 1U, cfg.recv_timeout_ms);
|
||||||
|
if (preload_sent < 0) {
|
||||||
|
fail("Send initial DOUT LOW: " + x502_error(api, preload_sent));
|
||||||
|
}
|
||||||
|
if (preload_sent != 1) {
|
||||||
|
fail("Send initial DOUT LOW did not transmit exactly one word");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
expect_ok(api, api.StreamsStart(device.hnd), "Start streams");
|
expect_ok(api, api.StreamsStart(device.hnd), "Start streams");
|
||||||
device.streams_started = true;
|
device.streams_started = true;
|
||||||
|
|
||||||
@ -1486,6 +1541,7 @@ 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;
|
||||||
@ -1516,6 +1572,14 @@ 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_next_state_high = false;
|
||||||
|
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;
|
||||||
@ -1632,6 +1696,66 @@ 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sent_words < chunk_words) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require_full_flush && !pending_dout.empty()) {
|
||||||
|
fail("DOUT queue could not be fully flushed before shutdown");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
auto start_packet = [&]() {
|
auto start_packet = [&]() {
|
||||||
if (packet_active) {
|
if (packet_active) {
|
||||||
return;
|
return;
|
||||||
@ -1648,6 +1772,9 @@ int run(const Config& cfg) {
|
|||||||
tty_group_state.reset_packet();
|
tty_group_state.reset_packet();
|
||||||
append_tty_packet_start();
|
append_tty_packet_start();
|
||||||
}
|
}
|
||||||
|
if (cfg.do1_toggle_per_frame) {
|
||||||
|
do1_next_state_high = false;
|
||||||
|
}
|
||||||
packet_active = true;
|
packet_active = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2023,12 +2150,24 @@ int run(const Config& cfg) {
|
|||||||
|
|
||||||
if (packet_active && stop_edge) {
|
if (packet_active && stop_edge) {
|
||||||
finish_packet(PacketCloseReason::ExternalStopEdge);
|
finish_packet(PacketCloseReason::ExternalStopEdge);
|
||||||
|
if (cfg.do1_toggle_per_frame && (lch == (cfg.channel_count - 1U))) {
|
||||||
|
append_dout_word(false);
|
||||||
|
}
|
||||||
if ((cfg.packet_limit != 0U) && (total_completed_packets >= cfg.packet_limit)) {
|
if ((cfg.packet_limit != 0U) && (total_completed_packets >= cfg.packet_limit)) {
|
||||||
stop_loop_requested = true;
|
stop_loop_requested = true;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cfg.do1_toggle_per_frame && (lch == (cfg.channel_count - 1U))) {
|
||||||
|
if (packet_active) {
|
||||||
|
append_dout_word(do1_next_state_high);
|
||||||
|
do1_next_state_high = !do1_next_state_high;
|
||||||
|
} else {
|
||||||
|
append_dout_word(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!packet_active) {
|
if (!packet_active) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2099,6 +2238,7 @@ int run(const Config& cfg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flush_dout_queue(0U, false);
|
||||||
flush_tty_frames();
|
flush_tty_frames();
|
||||||
|
|
||||||
if (console_stop_requested()) {
|
if (console_stop_requested()) {
|
||||||
@ -2114,6 +2254,9 @@ int run(const Config& cfg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
append_dout_word(false);
|
||||||
|
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;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,7 @@ exec "$BIN" \
|
|||||||
di1_group_avg \
|
di1_group_avg \
|
||||||
duration_ms:100 \
|
duration_ms:100 \
|
||||||
packet_limit:0 \
|
packet_limit:0 \
|
||||||
|
do1_toggle_per_frame \
|
||||||
profile:amplitude \
|
profile:amplitude \
|
||||||
"tty:${TTY_PATH}" \
|
"tty:${TTY_PATH}" \
|
||||||
"$@"
|
"$@"
|
||||||
|
|||||||
Reference in New Issue
Block a user