new rezhim
This commit is contained in:
231
main.cpp
231
main.cpp
@ -116,6 +116,7 @@ struct Config {
|
|||||||
bool do1_toggle_per_frame = false;
|
bool do1_toggle_per_frame = false;
|
||||||
bool do1_noise_subtract = false;
|
bool do1_noise_subtract = false;
|
||||||
bool do1_raw_tty_marked = false;
|
bool do1_raw_tty_marked = false;
|
||||||
|
bool do1_pair_subtract_avg = false;
|
||||||
std::optional<uint32_t> noise_avg_steps;
|
std::optional<uint32_t> noise_avg_steps;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -474,7 +475,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] [do1_noise_subtract] [do1_raw_tty_marked] [noise_avg_steps:N]\n"
|
<< " [do1_toggle_per_frame] [do1_noise_subtract] [do1_raw_tty_marked] [do1_pair_subtract_avg] [noise_avg_steps:N]\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"
|
||||||
@ -520,9 +521,13 @@ void print_help(const char* exe_name) {
|
|||||||
<< " from both phase channels, tagged by DI1 level from synchronous DIN:\n"
|
<< " from both phase channels, tagged by DI1 level from synchronous DIN:\n"
|
||||||
<< " word0=0x00A3 for DO1/DI1 LOW, word0=0x00A4 for DO1/DI1 HIGH\n"
|
<< " word0=0x00A3 for DO1/DI1 LOW, word0=0x00A4 for DO1/DI1 HIGH\n"
|
||||||
<< " no baseline subtraction is applied in this mode\n"
|
<< " no baseline subtraction is applied in this mode\n"
|
||||||
|
<< " do1_pair_subtract_avg -> with tty + do1_toggle_per_frame + phase profile, pair adjacent CH1/CH2 ticks,\n"
|
||||||
|
<< " drop boundary pairs with mismatched DI1/DI2, compute low-high by DI2 per pair,\n"
|
||||||
|
<< " average within each constant DI1 run, and emit legacy 4-word tty frames (word0=0x000A)\n"
|
||||||
<< " noise_avg_steps:N -> kept for compatibility in do1_noise_subtract mode (current baseline is previous HIGH step)\n"
|
<< " noise_avg_steps:N -> kept for compatibility in do1_noise_subtract mode (current baseline is previous HIGH step)\n"
|
||||||
<< " (still required when do1_noise_subtract is enabled)\n"
|
<< " (still required when do1_noise_subtract is enabled)\n"
|
||||||
<< " tty fast stream-only modes -> di1_group_avg, do1_noise_subtract, do1_raw_tty_marked; skip CSV/SVG/live outputs\n"
|
<< " tty fast stream-only modes -> di1_group_avg, do1_noise_subtract, do1_raw_tty_marked, do1_pair_subtract_avg;\n"
|
||||||
|
<< " skip CSV/SVG/live outputs\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"
|
||||||
<< "Profiles:\n"
|
<< "Profiles:\n"
|
||||||
@ -553,6 +558,8 @@ void print_help(const char* exe_name) {
|
|||||||
<< "DI1 from synchronous DIN is used as the actual DO1 state marker, and each LOW step subtracts previous HIGH step.\n"
|
<< "DI1 from synchronous DIN is used as the actual DO1 state marker, and each LOW step subtracts previous HIGH step.\n"
|
||||||
<< "For raw loopback diagnostics, use do1_toggle_per_frame + do1_raw_tty_marked in phase profile;\n"
|
<< "For raw loopback diagnostics, use do1_toggle_per_frame + do1_raw_tty_marked in phase profile;\n"
|
||||||
<< "steps are tagged in word0 as 0x00A3 (LOW) / 0x00A4 (HIGH) with raw per-step channel averages.\n"
|
<< "steps are tagged in word0 as 0x00A3 (LOW) / 0x00A4 (HIGH) with raw per-step channel averages.\n"
|
||||||
|
<< "For DI1-stable low/high DI2 subtraction with legacy tty output, use do1_toggle_per_frame + do1_pair_subtract_avg\n"
|
||||||
|
<< "in phase profile; boundary CH1/CH2 pairs with mismatched DI1/DI2 are dropped before averaging.\n"
|
||||||
<< "Amplitude mode keeps the raw AD8317 voltage as captured on X1; no inversion is applied.\n"
|
<< "Amplitude mode keeps the raw AD8317 voltage as captured on X1; no inversion is applied.\n"
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< "Phase profile example:\n"
|
<< "Phase profile example:\n"
|
||||||
@ -673,6 +680,10 @@ Config parse_args(int argc, char** argv) {
|
|||||||
cfg.do1_raw_tty_marked = true;
|
cfg.do1_raw_tty_marked = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (arg == "do1_pair_subtract_avg") {
|
||||||
|
cfg.do1_pair_subtract_avg = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (arg == "do1_toggle_per_frame") {
|
if (arg == "do1_toggle_per_frame") {
|
||||||
cfg.do1_toggle_per_frame = true;
|
cfg.do1_toggle_per_frame = true;
|
||||||
continue;
|
continue;
|
||||||
@ -792,7 +803,7 @@ Config parse_args(int argc, char** argv) {
|
|||||||
cfg.live_update_period_ms = std::max<uint32_t>(cfg.live_update_period_ms, 1000U);
|
cfg.live_update_period_ms = std::max<uint32_t>(cfg.live_update_period_ms, 1000U);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cfg.tty_path && (cfg.di1_group_average || cfg.do1_noise_subtract || cfg.do1_raw_tty_marked)) {
|
if (cfg.tty_path && (cfg.di1_group_average || cfg.do1_noise_subtract || cfg.do1_raw_tty_marked || cfg.do1_pair_subtract_avg)) {
|
||||||
if (!cfg.recv_block_specified) {
|
if (!cfg.recv_block_specified) {
|
||||||
cfg.recv_block_words = std::max<uint32_t>(cfg.recv_block_words, 65536U);
|
cfg.recv_block_words = std::max<uint32_t>(cfg.recv_block_words, 65536U);
|
||||||
}
|
}
|
||||||
@ -818,6 +829,9 @@ Config parse_args(int argc, char** argv) {
|
|||||||
if (cfg.di1_group_average && cfg.do1_raw_tty_marked) {
|
if (cfg.di1_group_average && cfg.do1_raw_tty_marked) {
|
||||||
fail("do1_raw_tty_marked is incompatible with di1_group_avg");
|
fail("do1_raw_tty_marked is incompatible with di1_group_avg");
|
||||||
}
|
}
|
||||||
|
if (cfg.di1_group_average && cfg.do1_pair_subtract_avg) {
|
||||||
|
fail("do1_pair_subtract_avg is incompatible with di1_group_avg");
|
||||||
|
}
|
||||||
if (cfg.do1_noise_subtract) {
|
if (cfg.do1_noise_subtract) {
|
||||||
if (!cfg.tty_path.has_value()) {
|
if (!cfg.tty_path.has_value()) {
|
||||||
fail("do1_noise_subtract requires tty:<path>");
|
fail("do1_noise_subtract requires tty:<path>");
|
||||||
@ -831,6 +845,9 @@ Config parse_args(int argc, char** argv) {
|
|||||||
if (cfg.do1_raw_tty_marked) {
|
if (cfg.do1_raw_tty_marked) {
|
||||||
fail("do1_noise_subtract is incompatible with do1_raw_tty_marked");
|
fail("do1_noise_subtract is incompatible with do1_raw_tty_marked");
|
||||||
}
|
}
|
||||||
|
if (cfg.do1_pair_subtract_avg) {
|
||||||
|
fail("do1_noise_subtract is incompatible with do1_pair_subtract_avg");
|
||||||
|
}
|
||||||
if (!cfg.noise_avg_steps.has_value()) {
|
if (!cfg.noise_avg_steps.has_value()) {
|
||||||
fail("do1_noise_subtract requires noise_avg_steps:N");
|
fail("do1_noise_subtract requires noise_avg_steps:N");
|
||||||
}
|
}
|
||||||
@ -847,6 +864,9 @@ Config parse_args(int argc, char** argv) {
|
|||||||
if (!cfg.do1_toggle_per_frame) {
|
if (!cfg.do1_toggle_per_frame) {
|
||||||
fail("do1_raw_tty_marked requires do1_toggle_per_frame");
|
fail("do1_raw_tty_marked requires do1_toggle_per_frame");
|
||||||
}
|
}
|
||||||
|
if (cfg.do1_pair_subtract_avg) {
|
||||||
|
fail("do1_raw_tty_marked is incompatible with do1_pair_subtract_avg");
|
||||||
|
}
|
||||||
if (cfg.mode != X502_LCH_MODE_DIFF) {
|
if (cfg.mode != X502_LCH_MODE_DIFF) {
|
||||||
fail("do1_raw_tty_marked requires phase configuration: mode:diff channels:2 ch1:2 ch2:3");
|
fail("do1_raw_tty_marked requires phase configuration: mode:diff channels:2 ch1:2 ch2:3");
|
||||||
}
|
}
|
||||||
@ -854,6 +874,26 @@ Config parse_args(int argc, char** argv) {
|
|||||||
fail("do1_raw_tty_marked requires phase configuration: mode:diff channels:2 ch1:2 ch2:3");
|
fail("do1_raw_tty_marked requires phase configuration: mode:diff channels:2 ch1:2 ch2:3");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cfg.do1_pair_subtract_avg) {
|
||||||
|
if (!cfg.tty_path.has_value()) {
|
||||||
|
fail("do1_pair_subtract_avg requires tty:<path>");
|
||||||
|
}
|
||||||
|
if (!cfg.do1_toggle_per_frame) {
|
||||||
|
fail("do1_pair_subtract_avg requires do1_toggle_per_frame");
|
||||||
|
}
|
||||||
|
if (cfg.do1_noise_subtract) {
|
||||||
|
fail("do1_pair_subtract_avg is incompatible with do1_noise_subtract");
|
||||||
|
}
|
||||||
|
if (cfg.do1_raw_tty_marked) {
|
||||||
|
fail("do1_pair_subtract_avg is incompatible with do1_raw_tty_marked");
|
||||||
|
}
|
||||||
|
if (cfg.profile != CaptureProfile::Phase) {
|
||||||
|
fail("do1_pair_subtract_avg requires profile:phase");
|
||||||
|
}
|
||||||
|
if ((cfg.mode != X502_LCH_MODE_DIFF) || (cfg.channel_count != 2U) || (cfg.ch1 != 2U) || (cfg.ch2 != 3U)) {
|
||||||
|
fail("do1_pair_subtract_avg requires phase configuration: mode:diff channels:2 ch1:2 ch2:3");
|
||||||
|
}
|
||||||
|
}
|
||||||
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");
|
||||||
}
|
}
|
||||||
@ -1407,6 +1447,105 @@ struct Do1NoiseSubtractState {
|
|||||||
void finish_step() { clear_step(); }
|
void finish_step() { clear_step(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Do1PairSubtractAverageState {
|
||||||
|
struct PairSample {
|
||||||
|
double ch1 = 0.0;
|
||||||
|
double ch2 = 0.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::deque<PairSample> low_pairs;
|
||||||
|
std::deque<PairSample> high_pairs;
|
||||||
|
bool run_initialized = false;
|
||||||
|
bool run_di1_high = false;
|
||||||
|
double diff_sum_ch1 = 0.0;
|
||||||
|
double diff_sum_ch2 = 0.0;
|
||||||
|
uint32_t diff_count = 0;
|
||||||
|
|
||||||
|
bool pending_ch1_valid = false;
|
||||||
|
double pending_ch1_raw = 0.0;
|
||||||
|
bool pending_ch1_di1_high = false;
|
||||||
|
bool pending_ch1_di2_high = false;
|
||||||
|
|
||||||
|
uint16_t next_index = 1;
|
||||||
|
|
||||||
|
void clear_run_pairs() {
|
||||||
|
low_pairs.clear();
|
||||||
|
high_pairs.clear();
|
||||||
|
diff_sum_ch1 = 0.0;
|
||||||
|
diff_sum_ch2 = 0.0;
|
||||||
|
diff_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_pending_ch1() {
|
||||||
|
pending_ch1_valid = false;
|
||||||
|
pending_ch1_raw = 0.0;
|
||||||
|
pending_ch1_di1_high = false;
|
||||||
|
pending_ch1_di2_high = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_packet() {
|
||||||
|
clear_run_pairs();
|
||||||
|
run_initialized = false;
|
||||||
|
run_di1_high = false;
|
||||||
|
clear_pending_ch1();
|
||||||
|
next_index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void start_run(bool di1_high) {
|
||||||
|
clear_run_pairs();
|
||||||
|
run_initialized = true;
|
||||||
|
run_di1_high = di1_high;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_run() {
|
||||||
|
clear_run_pairs();
|
||||||
|
run_initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_pending_ch1(double raw_code, bool di1_high, bool di2_high) {
|
||||||
|
pending_ch1_valid = true;
|
||||||
|
pending_ch1_raw = raw_code;
|
||||||
|
pending_ch1_di1_high = di1_high;
|
||||||
|
pending_ch1_di2_high = di2_high;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_pair_sample(bool di2_high, double ch1_value, double ch2_value) {
|
||||||
|
const PairSample sample{ch1_value, ch2_value};
|
||||||
|
if (di2_high) {
|
||||||
|
high_pairs.push_back(sample);
|
||||||
|
} else {
|
||||||
|
low_pairs.push_back(sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!low_pairs.empty() && !high_pairs.empty()) {
|
||||||
|
const PairSample low = low_pairs.front();
|
||||||
|
const PairSample high = high_pairs.front();
|
||||||
|
low_pairs.pop_front();
|
||||||
|
high_pairs.pop_front();
|
||||||
|
|
||||||
|
diff_sum_ch1 += (low.ch1 - high.ch1);
|
||||||
|
diff_sum_ch2 += (low.ch2 - high.ch2);
|
||||||
|
++diff_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_output() const { return diff_count != 0U; }
|
||||||
|
|
||||||
|
double avg_diff_ch1() const {
|
||||||
|
if (diff_count == 0U) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
return diff_sum_ch1 / static_cast<double>(diff_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
double avg_diff_ch2() const {
|
||||||
|
if (diff_count == 0U) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
return diff_sum_ch2 / static_cast<double>(diff_count);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
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);
|
||||||
@ -1688,15 +1827,17 @@ int run(const Config& cfg) {
|
|||||||
const bool tty_di1_group_average = cfg.tty_path.has_value() && cfg.di1_group_average;
|
const bool tty_di1_group_average = cfg.tty_path.has_value() && cfg.di1_group_average;
|
||||||
const bool tty_do1_noise_subtract = cfg.tty_path.has_value() && cfg.do1_noise_subtract;
|
const bool tty_do1_noise_subtract = cfg.tty_path.has_value() && cfg.do1_noise_subtract;
|
||||||
const bool tty_do1_raw_tty_marked = cfg.tty_path.has_value() && cfg.do1_raw_tty_marked;
|
const bool tty_do1_raw_tty_marked = cfg.tty_path.has_value() && cfg.do1_raw_tty_marked;
|
||||||
|
const bool tty_do1_pair_subtract_avg = cfg.tty_path.has_value() && cfg.do1_pair_subtract_avg;
|
||||||
const bool fast_tty_avg_stream_mode =
|
const bool fast_tty_avg_stream_mode =
|
||||||
tty_di1_group_average || tty_do1_noise_subtract || tty_do1_raw_tty_marked;
|
tty_di1_group_average || tty_do1_noise_subtract || tty_do1_raw_tty_marked || tty_do1_pair_subtract_avg;
|
||||||
const uint16_t tty_packet_start_marker =
|
const uint16_t tty_packet_start_marker =
|
||||||
(cfg.profile == CaptureProfile::Amplitude) ? 0x001AU : 0x000AU;
|
(cfg.profile == CaptureProfile::Amplitude) ? 0x001AU : 0x000AU;
|
||||||
const std::string fast_tty_mode_name = tty_do1_noise_subtract
|
const std::string fast_tty_mode_name = tty_do1_noise_subtract
|
||||||
? std::string("do1_noise_subtract")
|
? std::string("do1_noise_subtract")
|
||||||
: (tty_do1_raw_tty_marked ? std::string("do1_raw_tty_marked")
|
: (tty_do1_raw_tty_marked ? std::string("do1_raw_tty_marked")
|
||||||
: (tty_di1_group_average ? std::string("di1_group_avg")
|
: (tty_do1_pair_subtract_avg ? std::string("do1_pair_subtract_avg")
|
||||||
: std::string("none")));
|
: (tty_di1_group_average ? std::string("di1_group_avg")
|
||||||
|
: std::string("none"))));
|
||||||
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;
|
||||||
@ -1707,7 +1848,8 @@ 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_do1_noise_subtract && !tty_do1_raw_tty_marked) {
|
if (!tty_di1_group_average && !tty_do1_noise_subtract && !tty_do1_raw_tty_marked &&
|
||||||
|
!tty_do1_pair_subtract_avg) {
|
||||||
tty_writer->emit_packet_start(tty_packet_start_marker);
|
tty_writer->emit_packet_start(tty_packet_start_marker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1727,10 +1869,13 @@ int run(const Config& cfg) {
|
|||||||
<< " tty di1_group_avg: " << (tty_di1_group_average ? "enabled" : "disabled") << "\n"
|
<< " tty di1_group_avg: " << (tty_di1_group_average ? "enabled" : "disabled") << "\n"
|
||||||
<< " tty do1_noise_subtract: " << (tty_do1_noise_subtract ? "enabled" : "disabled") << "\n"
|
<< " tty do1_noise_subtract: " << (tty_do1_noise_subtract ? "enabled" : "disabled") << "\n"
|
||||||
<< " tty do1_raw_tty_marked: " << (tty_do1_raw_tty_marked ? "enabled" : "disabled") << "\n"
|
<< " tty do1_raw_tty_marked: " << (tty_do1_raw_tty_marked ? "enabled" : "disabled") << "\n"
|
||||||
|
<< " tty do1_pair_subtract_avg: " << (tty_do1_pair_subtract_avg ? "enabled" : "disabled") << "\n"
|
||||||
<< " do1_noise_subtract marker: "
|
<< " do1_noise_subtract marker: "
|
||||||
<< (tty_do1_noise_subtract ? "DI1 from DIN (DO1->DI1 loopback expected)" : "n/a") << "\n"
|
<< (tty_do1_noise_subtract ? "DI1 from DIN (DO1->DI1 loopback expected)" : "n/a") << "\n"
|
||||||
<< " do1_raw_tty_marked markers: "
|
<< " do1_raw_tty_marked markers: "
|
||||||
<< (tty_do1_raw_tty_marked ? "0x00A3=LOW, 0x00A4=HIGH (DI1 from DIN)" : "n/a") << "\n"
|
<< (tty_do1_raw_tty_marked ? "0x00A3=LOW, 0x00A4=HIGH (DI1 from DIN)" : "n/a") << "\n"
|
||||||
|
<< " do1_pair_subtract_avg marker: "
|
||||||
|
<< (tty_do1_pair_subtract_avg ? "word0=0x000A, low-high by DI2, averaged per DI1 run" : "n/a") << "\n"
|
||||||
<< " noise_avg_steps: "
|
<< " noise_avg_steps: "
|
||||||
<< (tty_do1_noise_subtract ? std::to_string(*cfg.noise_avg_steps) : std::string("n/a")) << "\n"
|
<< (tty_do1_noise_subtract ? std::to_string(*cfg.noise_avg_steps) : std::string("n/a")) << "\n"
|
||||||
<< " stream-only note: ignoring csv/svg/live_html/live_json/live_update_period_ms/svg_history_packets\n";
|
<< " stream-only note: ignoring csv/svg/live_html/live_json/live_update_period_ms/svg_history_packets\n";
|
||||||
@ -1758,6 +1903,11 @@ int run(const Config& cfg) {
|
|||||||
: (cfg.do1_raw_tty_marked ? std::string("requested, tty disabled")
|
: (cfg.do1_raw_tty_marked ? std::string("requested, tty disabled")
|
||||||
: std::string("disabled")))
|
: std::string("disabled")))
|
||||||
<< "\n"
|
<< "\n"
|
||||||
|
<< " tty do1_pair_subtract_avg: "
|
||||||
|
<< (tty_do1_pair_subtract_avg ? std::string("enabled")
|
||||||
|
: (cfg.do1_pair_subtract_avg ? 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";
|
||||||
@ -1826,6 +1976,7 @@ int run(const Config& cfg) {
|
|||||||
TtyGroupAverageState tty_group_state;
|
TtyGroupAverageState tty_group_state;
|
||||||
Do1RawTaggedState tty_do1_raw_state;
|
Do1RawTaggedState tty_do1_raw_state;
|
||||||
Do1NoiseSubtractState tty_do1_noise_state;
|
Do1NoiseSubtractState tty_do1_noise_state;
|
||||||
|
Do1PairSubtractAverageState tty_do1_pair_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 + 16U);
|
tty_frame_words.reserve(static_cast<std::size_t>(read_capacity_words) * 2U + 16U);
|
||||||
if (tty_do1_noise_subtract) {
|
if (tty_do1_noise_subtract) {
|
||||||
@ -2041,6 +2192,32 @@ int run(const Config& cfg) {
|
|||||||
tty_do1_noise_state.finish_step();
|
tty_do1_noise_state.finish_step();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto append_tty_do1_pair_subtracted_avg_run = [&]() {
|
||||||
|
if (!tty_do1_pair_subtract_avg) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!tty_do1_pair_state.run_initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tty_do1_pair_state.has_output()) {
|
||||||
|
tty_do1_pair_state.clear_run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tty_do1_pair_state.next_index >= 0xFFFFU) {
|
||||||
|
fail("TTY protocol step index overflow within packet");
|
||||||
|
}
|
||||||
|
|
||||||
|
append_tty_frame(0x000AU,
|
||||||
|
tty_do1_pair_state.next_index,
|
||||||
|
static_cast<uint16_t>(pack_raw_code_to_int16(tty_do1_pair_state.avg_diff_ch1())),
|
||||||
|
static_cast<uint16_t>(pack_raw_code_to_int16(tty_do1_pair_state.avg_diff_ch2())));
|
||||||
|
++tty_do1_pair_state.next_index;
|
||||||
|
++packet_avg_steps;
|
||||||
|
tty_do1_pair_state.clear_run();
|
||||||
|
};
|
||||||
|
|
||||||
auto flush_tty_frames = [&]() {
|
auto flush_tty_frames = [&]() {
|
||||||
if (!tty_writer || tty_frame_words.empty()) {
|
if (!tty_writer || tty_frame_words.empty()) {
|
||||||
return;
|
return;
|
||||||
@ -2077,6 +2254,9 @@ int run(const Config& cfg) {
|
|||||||
} else if (tty_do1_noise_subtract) {
|
} else if (tty_do1_noise_subtract) {
|
||||||
tty_do1_noise_state.reset_packet();
|
tty_do1_noise_state.reset_packet();
|
||||||
append_tty_packet_start();
|
append_tty_packet_start();
|
||||||
|
} else if (tty_do1_pair_subtract_avg) {
|
||||||
|
tty_do1_pair_state.reset_packet();
|
||||||
|
append_tty_packet_start();
|
||||||
}
|
}
|
||||||
packet_active = true;
|
packet_active = true;
|
||||||
};
|
};
|
||||||
@ -2100,6 +2280,9 @@ int run(const Config& cfg) {
|
|||||||
// Finalize the last DI1 run in packet, drop only incomplete channel tuples.
|
// Finalize the last DI1 run in packet, drop only incomplete channel tuples.
|
||||||
append_tty_do1_subtracted_step();
|
append_tty_do1_subtracted_step();
|
||||||
tty_do1_noise_state.clear_step();
|
tty_do1_noise_state.clear_step();
|
||||||
|
} else if (tty_do1_pair_subtract_avg) {
|
||||||
|
append_tty_do1_pair_subtracted_avg_run();
|
||||||
|
tty_do1_pair_state.reset_packet();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::size_t frames = fast_tty_avg_stream_mode
|
const std::size_t frames = fast_tty_avg_stream_mode
|
||||||
@ -2222,6 +2405,8 @@ int run(const Config& cfg) {
|
|||||||
tty_do1_raw_state.clear_step();
|
tty_do1_raw_state.clear_step();
|
||||||
} else if (tty_do1_noise_subtract) {
|
} else if (tty_do1_noise_subtract) {
|
||||||
tty_do1_noise_state.clear_step();
|
tty_do1_noise_state.clear_step();
|
||||||
|
} else if (tty_do1_pair_subtract_avg) {
|
||||||
|
tty_do1_pair_state.reset_packet();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2473,7 +2658,8 @@ int run(const Config& cfg) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((din_value & kE502Digital2Mask) != 0U) {
|
const bool di2_level = (din_value & kE502Digital2Mask) != 0U;
|
||||||
|
if (di2_level) {
|
||||||
++packet_di2_high_clocks;
|
++packet_di2_high_clocks;
|
||||||
} else {
|
} else {
|
||||||
++packet_di2_low_clocks;
|
++packet_di2_low_clocks;
|
||||||
@ -2508,7 +2694,34 @@ int run(const Config& cfg) {
|
|||||||
|
|
||||||
if (fast_tty_avg_stream_mode) {
|
if (fast_tty_avg_stream_mode) {
|
||||||
if (fast_packet_frames < target_frames) {
|
if (fast_packet_frames < target_frames) {
|
||||||
if (tty_do1_noise_subtract) {
|
if (tty_do1_pair_subtract_avg) {
|
||||||
|
if (lch == 0U) {
|
||||||
|
tty_do1_pair_state.add_pending_ch1(adc_raw_value, di1_level, di2_level);
|
||||||
|
} else if (lch == 1U) {
|
||||||
|
if (tty_do1_pair_state.pending_ch1_valid) {
|
||||||
|
const bool pair_di1_matches =
|
||||||
|
(tty_do1_pair_state.pending_ch1_di1_high == di1_level);
|
||||||
|
const bool pair_di2_matches =
|
||||||
|
(tty_do1_pair_state.pending_ch1_di2_high == di2_level);
|
||||||
|
|
||||||
|
if (pair_di1_matches && pair_di2_matches) {
|
||||||
|
if (!tty_do1_pair_state.run_initialized) {
|
||||||
|
tty_do1_pair_state.start_run(di1_level);
|
||||||
|
} else if (tty_do1_pair_state.run_di1_high != di1_level) {
|
||||||
|
append_tty_do1_pair_subtracted_avg_run();
|
||||||
|
tty_do1_pair_state.start_run(di1_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_do1_pair_state.add_pair_sample(di2_level,
|
||||||
|
tty_do1_pair_state.pending_ch1_raw,
|
||||||
|
adc_raw_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tty_do1_pair_state.clear_pending_ch1();
|
||||||
|
} else {
|
||||||
|
tty_do1_pair_state.clear_pending_ch1();
|
||||||
|
}
|
||||||
|
} else if (tty_do1_noise_subtract) {
|
||||||
tty_do1_noise_state.add_sample(lch, adc_raw_value);
|
tty_do1_noise_state.add_sample(lch, adc_raw_value);
|
||||||
} else if (tty_do1_raw_tty_marked) {
|
} else if (tty_do1_raw_tty_marked) {
|
||||||
tty_do1_raw_state.add_sample(lch, adc_raw_value);
|
tty_do1_raw_state.add_sample(lch, adc_raw_value);
|
||||||
|
|||||||
33
run_do1_pair_subtract_avg.sh
Executable file
33
run_do1_pair_subtract_avg.sh
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
BIN="${BIN:-./main.exe}"
|
||||||
|
TTY_PATH="${TTY_PATH:-/tmp/ttyADC_data}"
|
||||||
|
LIB_DIR="${LIB_DIR:-$HOME/.local/lib}"
|
||||||
|
|
||||||
|
if [[ ! -x "$BIN" ]]; then
|
||||||
|
echo "Binary '$BIN' not found or not executable. Run ./build_main.sh first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -d "$LIB_DIR" ]]; then
|
||||||
|
export LD_LIBRARY_PATH="${LIB_DIR}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$BIN" \
|
||||||
|
profile:phase \
|
||||||
|
clock:internal \
|
||||||
|
internal_ref_hz:2000000 \
|
||||||
|
start:di_syn2_rise \
|
||||||
|
stop:di_syn2_fall \
|
||||||
|
sample_clock_hz:max \
|
||||||
|
range:5 \
|
||||||
|
duration_ms:100 \
|
||||||
|
packet_limit:0 \
|
||||||
|
do1_toggle_per_frame \
|
||||||
|
do1_pair_subtract_avg \
|
||||||
|
"tty:${TTY_PATH}" \
|
||||||
|
"$@"
|
||||||
Reference in New Issue
Block a user