add averaging
This commit is contained in:
169
main.cpp
169
main.cpp
@ -101,6 +101,7 @@ struct Config {
|
|||||||
std::string live_html_path = "live_plot.html";
|
std::string live_html_path = "live_plot.html";
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[noreturn]] void fail(const std::string& message) {
|
[[noreturn]] void fail(const std::string& message) {
|
||||||
@ -381,7 +382,7 @@ void print_help(const char* exe_name) {
|
|||||||
<< " [internal_ref_hz:2000000]\n"
|
<< " [internal_ref_hz:2000000]\n"
|
||||||
<< " [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]\n"
|
<< " [live_html:live_plot.html] [live_json:live_plot.json] [tty:/tmp/ttyADC_data] [di1_group_avg]\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"
|
||||||
@ -413,6 +414,7 @@ void print_help(const char* exe_name) {
|
|||||||
<< " step_words:32768 -> input stream transfer step 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"
|
<< " live_html/live_json -> live graph files updated as packets arrive\n"
|
||||||
<< " tty:/tmp/ttyADC_data -> write a continuous legacy 4-word CH1/CH2 stream to a Linux/POSIX tty or PTY link path\n"
|
<< " tty:/tmp/ttyADC_data -> write a continuous legacy 4-word CH1/CH2 stream to a Linux/POSIX tty or PTY link path\n"
|
||||||
|
<< " di1_group_avg -> with tty + di1:trace, emit one averaged CH1/CH2 step per constant DI1 run\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"
|
||||||
<< "Differential physical channel mapping:\n"
|
<< "Differential physical channel mapping:\n"
|
||||||
@ -432,6 +434,8 @@ void print_help(const char* exe_name) {
|
|||||||
<< "can either zero ADC samples on change, be exported as a separate synchronous trace, or be ignored.\n"
|
<< "can either zero ADC samples on change, be exported as a separate synchronous trace, or be ignored.\n"
|
||||||
<< "Open live_plot.html in a browser to see the live graph update over time.\n"
|
<< "Open live_plot.html in a browser to see the live graph update over time.\n"
|
||||||
<< "The live HTML supports X/Y zoom buttons, mouse-wheel zoom, and reset.\n"
|
<< "The live HTML supports X/Y zoom buttons, mouse-wheel zoom, and reset.\n"
|
||||||
|
<< "For tty output, use di1_group_avg together with di1:trace to emit one averaged 4-word step\n"
|
||||||
|
<< "per constant DI1 run while keeping the current ring-buffered binary frame format.\n"
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< "Recommended working example:\n"
|
<< "Recommended working example:\n"
|
||||||
<< " " << exe_name
|
<< " " << exe_name
|
||||||
@ -441,7 +445,13 @@ void print_help(const char* exe_name) {
|
|||||||
<< "Internal-clock example:\n"
|
<< "Internal-clock example:\n"
|
||||||
<< " " << exe_name
|
<< " " << exe_name
|
||||||
<< " clock:internal internal_ref_hz:2000000 start:di_syn2_rise stop:di_syn2_fall"
|
<< " clock:internal internal_ref_hz:2000000 start:di_syn2_rise stop:di_syn2_fall"
|
||||||
<< " sample_clock_hz:max duration_ms:100 packet_limit:0 csv:chirp.csv svg:chirp.svg\n";
|
<< " sample_clock_hz:max duration_ms:100 packet_limit:0 csv:chirp.csv svg:chirp.svg\n"
|
||||||
|
<< "\n"
|
||||||
|
<< "TTY DI1-group average example:\n"
|
||||||
|
<< " " << exe_name
|
||||||
|
<< " clock:internal internal_ref_hz:2000000 start:di_syn2_rise stop:di_syn2_fall"
|
||||||
|
<< " sample_clock_hz:max range:0.2 di1:trace di1_group_avg duration_ms:100 packet_limit:0"
|
||||||
|
<< " tty:/tmp/ttyADC_data\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
Config parse_args(int argc, char** argv) {
|
Config parse_args(int argc, char** argv) {
|
||||||
@ -513,6 +523,10 @@ Config parse_args(int argc, char** argv) {
|
|||||||
cfg.di1_mode = parse_di1_mode(arg.substr(4));
|
cfg.di1_mode = parse_di1_mode(arg.substr(4));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if ((arg == "di1_group_avg") || (arg == "di1_avg")) {
|
||||||
|
cfg.di1_group_average = 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;
|
||||||
@ -631,6 +645,12 @@ Config parse_args(int argc, char** argv) {
|
|||||||
if (cfg.input_buffer_words < cfg.recv_block_words) {
|
if (cfg.input_buffer_words < cfg.recv_block_words) {
|
||||||
cfg.input_buffer_words = cfg.recv_block_words;
|
cfg.input_buffer_words = cfg.recv_block_words;
|
||||||
}
|
}
|
||||||
|
if (cfg.di1_group_average && (cfg.di1_mode != Di1Mode::Trace)) {
|
||||||
|
fail("di1_group_avg requires di1:trace");
|
||||||
|
}
|
||||||
|
if (cfg.tty_path && cfg.di1_group_average && (cfg.channel_count != 2U)) {
|
||||||
|
fail("tty di1_group_avg requires channels:2");
|
||||||
|
}
|
||||||
if (cfg.tty_path && (cfg.channel_count != 2U)) {
|
if (cfg.tty_path && (cfg.channel_count != 2U)) {
|
||||||
fail("tty output requires channels:2");
|
fail("tty output requires channels:2");
|
||||||
}
|
}
|
||||||
@ -996,6 +1016,40 @@ struct TtyContinuousState {
|
|||||||
uint16_t next_index = 1;
|
uint16_t next_index = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TtyGroupAverageState {
|
||||||
|
double sum_ch1 = 0.0;
|
||||||
|
double sum_ch2 = 0.0;
|
||||||
|
uint32_t count_ch1 = 0;
|
||||||
|
uint32_t count_ch2 = 0;
|
||||||
|
uint32_t next_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_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) {
|
int16_t pack_raw_code_to_int16(double avg_raw_code) {
|
||||||
const double scaled =
|
const double scaled =
|
||||||
avg_raw_code * 32767.0 / static_cast<double>(X502_ADC_SCALE_CODE_MAX);
|
avg_raw_code * 32767.0 / static_cast<double>(X502_ADC_SCALE_CODE_MAX);
|
||||||
@ -1253,6 +1307,7 @@ int run(const Config& cfg) {
|
|||||||
const uint32_t read_capacity_words = std::max(cfg.recv_block_words, cfg.input_step_words);
|
const uint32_t read_capacity_words = std::max(cfg.recv_block_words, cfg.input_step_words);
|
||||||
std::size_t tty_ring_capacity_bytes = 0;
|
std::size_t tty_ring_capacity_bytes = 0;
|
||||||
std::unique_ptr<TtyProtocolWriter> tty_writer;
|
std::unique_ptr<TtyProtocolWriter> tty_writer;
|
||||||
|
const bool tty_di1_group_average = cfg.tty_path.has_value() && cfg.di1_group_average;
|
||||||
if (cfg.tty_path) {
|
if (cfg.tty_path) {
|
||||||
const uint64_t typical_tty_batch_frames = (static_cast<uint64_t>(read_capacity_words) + 1U) / 2U;
|
const uint64_t typical_tty_batch_frames = (static_cast<uint64_t>(read_capacity_words) + 1U) / 2U;
|
||||||
const uint64_t typical_tty_batch_bytes = typical_tty_batch_frames * sizeof(uint16_t) * 4U;
|
const uint64_t typical_tty_batch_bytes = typical_tty_batch_frames * sizeof(uint16_t) * 4U;
|
||||||
@ -1263,8 +1318,10 @@ int run(const Config& cfg) {
|
|||||||
}
|
}
|
||||||
tty_ring_capacity_bytes = static_cast<std::size_t>(tty_ring_bytes_u64);
|
tty_ring_capacity_bytes = static_cast<std::size_t>(tty_ring_bytes_u64);
|
||||||
tty_writer = std::make_unique<TtyProtocolWriter>(*cfg.tty_path, tty_ring_capacity_bytes);
|
tty_writer = std::make_unique<TtyProtocolWriter>(*cfg.tty_path, tty_ring_capacity_bytes);
|
||||||
|
if (!tty_di1_group_average) {
|
||||||
tty_writer->emit_packet_start();
|
tty_writer->emit_packet_start();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
CaptureFileWriter writer(cfg.csv_path, cfg.svg_path, cfg.live_html_path, cfg.live_json_path);
|
CaptureFileWriter writer(cfg.csv_path, cfg.svg_path, cfg.live_html_path, cfg.live_json_path);
|
||||||
writer.initialize_live_plot();
|
writer.initialize_live_plot();
|
||||||
writer.initialize_csv(cfg.channel_count, cfg.di1_mode == Di1Mode::Trace);
|
writer.initialize_csv(cfg.channel_count, cfg.di1_mode == Di1Mode::Trace);
|
||||||
@ -1276,6 +1333,11 @@ int run(const Config& cfg) {
|
|||||||
<< " recv block words: " << cfg.recv_block_words << "\n"
|
<< " recv block words: " << cfg.recv_block_words << "\n"
|
||||||
<< " input step words: " << cfg.input_step_words << "\n"
|
<< " input step words: " << cfg.input_step_words << "\n"
|
||||||
<< " input buffer words: " << cfg.input_buffer_words << "\n"
|
<< " input buffer words: " << cfg.input_buffer_words << "\n"
|
||||||
|
<< " tty di1_group_avg: "
|
||||||
|
<< (tty_di1_group_average ? std::string("enabled")
|
||||||
|
: (cfg.di1_group_average ? std::string("requested, tty disabled")
|
||||||
|
: std::string("disabled")))
|
||||||
|
<< "\n"
|
||||||
<< " SVG history packets kept in RAM: "
|
<< " SVG history packets kept in RAM: "
|
||||||
<< ((cfg.svg_history_packets == 0U) ? std::string("all (unbounded)") : std::to_string(cfg.svg_history_packets))
|
<< ((cfg.svg_history_packets == 0U) ? std::string("all (unbounded)") : std::to_string(cfg.svg_history_packets))
|
||||||
<< "\n";
|
<< "\n";
|
||||||
@ -1293,12 +1355,14 @@ int run(const Config& cfg) {
|
|||||||
std::vector<double> adc_raw_buffer(read_capacity_words);
|
std::vector<double> adc_raw_buffer(read_capacity_words);
|
||||||
std::vector<uint32_t> din_buffer(read_capacity_words);
|
std::vector<uint32_t> din_buffer(read_capacity_words);
|
||||||
std::deque<double> pending_adc;
|
std::deque<double> pending_adc;
|
||||||
|
std::deque<double> pending_adc_raw;
|
||||||
std::deque<uint32_t> pending_din;
|
std::deque<uint32_t> pending_din;
|
||||||
std::deque<CapturePacket> packets;
|
std::deque<CapturePacket> packets;
|
||||||
PacketAccumulator current_packet;
|
PacketAccumulator current_packet;
|
||||||
TtyContinuousState tty_state;
|
TtyContinuousState tty_state;
|
||||||
|
TtyGroupAverageState tty_group_state;
|
||||||
std::vector<uint16_t> tty_frame_words;
|
std::vector<uint16_t> tty_frame_words;
|
||||||
tty_frame_words.reserve(static_cast<std::size_t>(read_capacity_words) * 2U);
|
tty_frame_words.reserve(static_cast<std::size_t>(read_capacity_words) * 2U + 16U);
|
||||||
current_packet.reset(target_frames, cfg.channel_count);
|
current_packet.reset(target_frames, cfg.channel_count);
|
||||||
std::size_t csv_global_frame_index = 0;
|
std::size_t csv_global_frame_index = 0;
|
||||||
|
|
||||||
@ -1385,15 +1449,67 @@ int run(const Config& cfg) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto append_tty_frame = [&](uint16_t word0, uint16_t word1, uint16_t word2, uint16_t word3) {
|
||||||
|
tty_frame_words.push_back(word0);
|
||||||
|
tty_frame_words.push_back(word1);
|
||||||
|
tty_frame_words.push_back(word2);
|
||||||
|
tty_frame_words.push_back(word3);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto append_tty_packet_start = [&]() {
|
||||||
|
append_tty_frame(0x000A, 0xFFFF, 0xFFFF, 0xFFFF);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto append_tty_group_step = [&]() {
|
||||||
|
if (!tty_di1_group_average || !tty_group_state.has_complete_step()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tty_group_state.next_index >= 0xFFFFU) {
|
||||||
|
fail("TTY protocol step index overflow within packet");
|
||||||
|
}
|
||||||
|
|
||||||
|
const double ch1_avg = tty_group_state.sum_ch1 / static_cast<double>(tty_group_state.count_ch1);
|
||||||
|
const double ch2_avg = tty_group_state.sum_ch2 / static_cast<double>(tty_group_state.count_ch2);
|
||||||
|
append_tty_frame(0x000A,
|
||||||
|
static_cast<uint16_t>(tty_group_state.next_index),
|
||||||
|
static_cast<uint16_t>(pack_raw_code_to_int16(ch1_avg)),
|
||||||
|
static_cast<uint16_t>(pack_raw_code_to_int16(ch2_avg)));
|
||||||
|
++tty_group_state.next_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto flush_tty_frames = [&]() {
|
||||||
|
if (!tty_writer || tty_frame_words.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_writer->enqueue_encoded_frames(tty_frame_words.data(), tty_frame_words.size() / 4U);
|
||||||
|
tty_frame_words.clear();
|
||||||
|
|
||||||
|
const auto tty_stats = tty_writer->stats();
|
||||||
|
if (!tty_overflow_warning_printed && (tty_stats.ring_overflows != 0U)) {
|
||||||
|
std::cerr << "Warning: TTY ring buffer overflowed; dropping oldest frames to keep the stream continuous\n";
|
||||||
|
tty_overflow_warning_printed = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
auto start_packet = [&]() {
|
auto start_packet = [&]() {
|
||||||
if (packet_active) {
|
if (packet_active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
current_packet.reset(target_frames, cfg.channel_count);
|
current_packet.reset(target_frames, cfg.channel_count);
|
||||||
|
if (tty_di1_group_average) {
|
||||||
|
tty_group_state.reset_packet();
|
||||||
|
append_tty_packet_start();
|
||||||
|
}
|
||||||
packet_active = true;
|
packet_active = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto finish_packet = [&](PacketCloseReason reason) {
|
auto finish_packet = [&](PacketCloseReason reason) {
|
||||||
|
if (tty_di1_group_average) {
|
||||||
|
append_tty_group_step();
|
||||||
|
tty_group_state.clear_step();
|
||||||
|
}
|
||||||
|
|
||||||
const std::size_t frames = current_packet.frame_count(cfg.channel_count);
|
const std::size_t frames = current_packet.frame_count(cfg.channel_count);
|
||||||
if (frames != 0U) {
|
if (frames != 0U) {
|
||||||
current_packet.channels[0].resize(frames);
|
current_packet.channels[0].resize(frames);
|
||||||
@ -1475,6 +1591,9 @@ int run(const Config& cfg) {
|
|||||||
|
|
||||||
packet_active = false;
|
packet_active = false;
|
||||||
current_packet.reset(target_frames, cfg.channel_count);
|
current_packet.reset(target_frames, cfg.channel_count);
|
||||||
|
if (tty_di1_group_average) {
|
||||||
|
tty_group_state.clear_step();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
while (!stop_loop_requested) {
|
while (!stop_loop_requested) {
|
||||||
@ -1488,6 +1607,7 @@ int run(const Config& cfg) {
|
|||||||
if (console_stop_requested()) {
|
if (console_stop_requested()) {
|
||||||
if (packet_active) {
|
if (packet_active) {
|
||||||
finish_packet(PacketCloseReason::UserStop);
|
finish_packet(PacketCloseReason::UserStop);
|
||||||
|
flush_tty_frames();
|
||||||
}
|
}
|
||||||
stop_loop_requested = true;
|
stop_loop_requested = true;
|
||||||
break;
|
break;
|
||||||
@ -1573,6 +1693,7 @@ int run(const Config& cfg) {
|
|||||||
fail("Raw ADC parsing returned a different sample count than voltage processing");
|
fail("Raw ADC parsing returned a different sample count than voltage processing");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tty_di1_group_average) {
|
||||||
tty_frame_words.clear();
|
tty_frame_words.clear();
|
||||||
tty_frame_words.reserve(((static_cast<std::size_t>(raw_adc_count) + 1U) / 2U) * 4U);
|
tty_frame_words.reserve(((static_cast<std::size_t>(raw_adc_count) + 1U) / 2U) * 4U);
|
||||||
for (uint32_t i = 0; i < raw_adc_count; ++i) {
|
for (uint32_t i = 0; i < raw_adc_count; ++i) {
|
||||||
@ -1583,10 +1704,10 @@ int run(const Config& cfg) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
tty_frame_words.push_back(0x000A);
|
append_tty_frame(0x000A,
|
||||||
tty_frame_words.push_back(tty_state.next_index);
|
tty_state.next_index,
|
||||||
tty_frame_words.push_back(static_cast<uint16_t>(tty_state.pending_ch1));
|
static_cast<uint16_t>(tty_state.pending_ch1),
|
||||||
tty_frame_words.push_back(static_cast<uint16_t>(sample));
|
static_cast<uint16_t>(sample));
|
||||||
tty_state.pending_ch1_valid = false;
|
tty_state.pending_ch1_valid = false;
|
||||||
|
|
||||||
if (tty_state.next_index >= 0xFFFEU) {
|
if (tty_state.next_index >= 0xFFFEU) {
|
||||||
@ -1595,15 +1716,7 @@ int run(const Config& cfg) {
|
|||||||
++tty_state.next_index;
|
++tty_state.next_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
flush_tty_frames();
|
||||||
if (!tty_frame_words.empty()) {
|
|
||||||
tty_writer->enqueue_encoded_frames(tty_frame_words.data(), tty_frame_words.size() / 4U);
|
|
||||||
|
|
||||||
const auto tty_stats = tty_writer->stats();
|
|
||||||
if (!tty_overflow_warning_printed && (tty_stats.ring_overflows != 0U)) {
|
|
||||||
std::cerr << "Warning: TTY ring buffer overflowed; dropping oldest frames to keep the stream continuous\n";
|
|
||||||
tty_overflow_warning_printed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1619,20 +1732,31 @@ int run(const Config& cfg) {
|
|||||||
for (uint32_t i = 0; i < adc_count; ++i) {
|
for (uint32_t i = 0; i < adc_count; ++i) {
|
||||||
pending_adc.push_back(adc_buffer[i]);
|
pending_adc.push_back(adc_buffer[i]);
|
||||||
}
|
}
|
||||||
|
if (tty_di1_group_average) {
|
||||||
|
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) {
|
for (uint32_t i = 0; i < din_count; ++i) {
|
||||||
pending_din.push_back(din_buffer[i]);
|
pending_din.push_back(din_buffer[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pending_adc.size() > 1000000U) ||
|
if ((pending_adc.size() > 1000000U) ||
|
||||||
(pending_din.size() > 1000000U)) {
|
(pending_din.size() > 1000000U) ||
|
||||||
|
(tty_di1_group_average && (pending_adc_raw.size() > 1000000U))) {
|
||||||
fail("Internal backlog grew too large while aligning ADC and DIN samples");
|
fail("Internal backlog grew too large while aligning ADC and DIN samples");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!pending_adc.empty() &&
|
while (!pending_adc.empty() &&
|
||||||
!pending_din.empty() &&
|
!pending_din.empty() &&
|
||||||
|
(!tty_di1_group_average || !pending_adc_raw.empty()) &&
|
||||||
!stop_loop_requested) {
|
!stop_loop_requested) {
|
||||||
const double adc_value = pending_adc.front();
|
const double adc_value = pending_adc.front();
|
||||||
pending_adc.pop_front();
|
pending_adc.pop_front();
|
||||||
|
const double adc_raw_value = tty_di1_group_average ? pending_adc_raw.front() : 0.0;
|
||||||
|
if (tty_di1_group_average) {
|
||||||
|
pending_adc_raw.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
const uint32_t din_value = pending_din.front();
|
const uint32_t din_value = pending_din.front();
|
||||||
pending_din.pop_front();
|
pending_din.pop_front();
|
||||||
@ -1697,6 +1821,11 @@ int run(const Config& cfg) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tty_di1_group_average && di1_changed) {
|
||||||
|
append_tty_group_step();
|
||||||
|
tty_group_state.clear_step();
|
||||||
|
}
|
||||||
|
|
||||||
const uint32_t lch = next_lch;
|
const uint32_t lch = next_lch;
|
||||||
next_lch = (next_lch + 1U) % cfg.channel_count;
|
next_lch = (next_lch + 1U) % cfg.channel_count;
|
||||||
|
|
||||||
@ -1715,6 +1844,9 @@ int run(const Config& cfg) {
|
|||||||
|
|
||||||
if (current_packet.channels[lch].size() < target_frames) {
|
if (current_packet.channels[lch].size() < target_frames) {
|
||||||
current_packet.channels[lch].push_back(stored_value);
|
current_packet.channels[lch].push_back(stored_value);
|
||||||
|
if (tty_di1_group_average) {
|
||||||
|
tty_group_state.add_sample(lch, adc_raw_value);
|
||||||
|
}
|
||||||
++current_packet.stored_samples;
|
++current_packet.stored_samples;
|
||||||
++total_stored_adc_samples;
|
++total_stored_adc_samples;
|
||||||
++stats_stored_adc_samples;
|
++stats_stored_adc_samples;
|
||||||
@ -1738,10 +1870,13 @@ int run(const Config& cfg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flush_tty_frames();
|
||||||
|
|
||||||
if (console_stop_requested()) {
|
if (console_stop_requested()) {
|
||||||
if (packet_active) {
|
if (packet_active) {
|
||||||
finish_packet(PacketCloseReason::UserStop);
|
finish_packet(PacketCloseReason::UserStop);
|
||||||
}
|
}
|
||||||
|
flush_tty_frames();
|
||||||
stop_loop_requested = true;
|
stop_loop_requested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user