di 1 incre

This commit is contained in:
awe
2026-04-24 18:01:45 +03:00
parent 70b5557be9
commit 8175d1cba0

View File

@ -511,8 +511,9 @@ void print_help(const char* exe_name) {
<< " do1_toggle_per_frame -> hardware cyclic DO1 pattern in module memory:\n" << " do1_toggle_per_frame -> hardware cyclic DO1 pattern in module memory:\n"
<< " DO1 outputs 00110011... continuously (toggle every 2 ADC ticks)\n" << " DO1 outputs 00110011... continuously (toggle every 2 ADC ticks)\n"
<< " without per-tick DOUT updates from PC\n" << " without per-tick DOUT updates from PC\n"
<< " do1_noise_subtract -> with tty + do1_toggle_per_frame, use programmed DO1 phase (0011...)\n" << " do1_noise_subtract -> with tty + do1_toggle_per_frame, use DI1 state from synchronous DIN\n"
<< " to average recent noise steps and subtract it from useful steps before tty output\n" << " (expected DO1->DI1 loopback) to average recent noise steps and subtract it\n"
<< " from useful steps before tty output\n"
<< " (only corrected DO1=LOW steps are sent to tty)\n" << " (only corrected DO1=LOW steps are sent to tty)\n"
<< " noise_avg_steps:N -> number of recent DO1=HIGH noise steps per channel used as subtraction baseline\n" << " noise_avg_steps:N -> number of recent DO1=HIGH noise steps per channel used as subtraction baseline\n"
<< " (required when do1_noise_subtract is enabled)\n" << " (required when do1_noise_subtract is enabled)\n"
@ -543,8 +544,8 @@ void print_help(const char* exe_name) {
<< "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" << "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" << "per constant DI1 run while keeping the current ring-buffered binary frame format.\n"
<< "For DO1-phase subtraction, use do1_toggle_per_frame + do1_noise_subtract + noise_avg_steps:N;\n" << "For DO1 subtraction with loopback, use do1_toggle_per_frame + do1_noise_subtract + noise_avg_steps:N;\n"
<< "the first ADC sample in each packet is treated as DO1 LOW in the 0011... sequence.\n" << "DI1 from synchronous DIN is used as the actual DO1 state marker.\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"
@ -1238,8 +1239,8 @@ struct Do1NoiseSubtractState {
std::array<double, 2> noise_ring_sum {}; std::array<double, 2> noise_ring_sum {};
std::array<double, 2> step_sum {}; std::array<double, 2> step_sum {};
std::array<uint32_t, 2> step_count {}; std::array<uint32_t, 2> step_count {};
uint32_t ticks_in_step = 0; bool step_level_initialized = false;
bool step_do1_high = false; bool step_di1_high = false;
uint16_t next_index = 1; uint16_t next_index = 1;
void configure(uint32_t history_steps) { void configure(uint32_t history_steps) {
@ -1253,18 +1254,24 @@ struct Do1NoiseSubtractState {
void clear_step() { void clear_step() {
step_sum = {}; step_sum = {};
step_count = {}; step_count = {};
ticks_in_step = 0;
} }
void reset_packet() { void reset_packet() {
clear_step(); clear_step();
step_do1_high = false; step_level_initialized = false;
step_di1_high = false;
next_index = 1; next_index = 1;
noise_ring_head = {}; noise_ring_head = {};
noise_ring_size = {}; noise_ring_size = {};
noise_ring_sum = {}; noise_ring_sum = {};
} }
void start_new_step(bool di1_high) {
clear_step();
step_di1_high = di1_high;
step_level_initialized = true;
}
void add_sample(uint32_t lch, double raw_code) { void add_sample(uint32_t lch, double raw_code) {
if (lch >= step_sum.size()) { if (lch >= step_sum.size()) {
return; return;
@ -1273,15 +1280,6 @@ struct Do1NoiseSubtractState {
++step_count[lch]; ++step_count[lch];
} }
bool advance_tick() {
++ticks_in_step;
if (ticks_in_step < kDo1TogglePeriodTicks) {
return false;
}
ticks_in_step = 0;
return true;
}
bool has_complete_step(uint32_t channel_count) const { bool has_complete_step(uint32_t channel_count) const {
return (step_count[0] != 0U) && ((channel_count <= 1U) || (step_count[1] != 0U)); return (step_count[0] != 0U) && ((channel_count <= 1U) || (step_count[1] != 0U));
} }
@ -1327,11 +1325,7 @@ struct Do1NoiseSubtractState {
return noise_ring_sum[lch] / static_cast<double>(size); return noise_ring_sum[lch] / static_cast<double>(size);
} }
void finish_step() { void finish_step() { clear_step(); }
step_do1_high = !step_do1_high;
step_sum = {};
step_count = {};
}
}; };
int16_t pack_raw_code_to_int16(double avg_raw_code) { int16_t pack_raw_code_to_int16(double avg_raw_code) {
@ -1650,6 +1644,8 @@ int run(const Config& cfg) {
<< " input buffer words: " << cfg.input_buffer_words << "\n" << " input buffer words: " << cfg.input_buffer_words << "\n"
<< " 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"
<< " do1_noise_subtract marker: "
<< (tty_do1_noise_subtract ? "DI1 from DIN (DO1->DI1 loopback expected)" : "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";
@ -1876,6 +1872,10 @@ int run(const Config& cfg) {
return; return;
} }
if (!tty_do1_noise_state.step_level_initialized) {
return;
}
if (!tty_do1_noise_state.has_complete_step(cfg.channel_count)) { if (!tty_do1_noise_state.has_complete_step(cfg.channel_count)) {
tty_do1_noise_state.finish_step(); tty_do1_noise_state.finish_step();
return; return;
@ -1884,7 +1884,7 @@ int run(const Config& cfg) {
const double ch1_avg = tty_do1_noise_state.step_average(0U); const double ch1_avg = tty_do1_noise_state.step_average(0U);
const double ch2_avg = (cfg.channel_count <= 1U) ? 0.0 : tty_do1_noise_state.step_average(1U); const double ch2_avg = (cfg.channel_count <= 1U) ? 0.0 : tty_do1_noise_state.step_average(1U);
if (tty_do1_noise_state.step_do1_high) { if (tty_do1_noise_state.step_di1_high) {
tty_do1_noise_state.push_noise_average(0U, ch1_avg); tty_do1_noise_state.push_noise_average(0U, ch1_avg);
if (cfg.channel_count > 1U) { if (cfg.channel_count > 1U) {
tty_do1_noise_state.push_noise_average(1U, ch2_avg); tty_do1_noise_state.push_noise_average(1U, ch2_avg);
@ -1960,7 +1960,8 @@ int run(const Config& cfg) {
append_tty_group_step(); append_tty_group_step();
tty_group_state.clear_step(); tty_group_state.clear_step();
} else if (tty_do1_noise_subtract) { } else if (tty_do1_noise_subtract) {
// Keep only complete programmed DO1 steps. Partial steps are dropped on packet close. // Finalize the last DI1 run in packet, drop only incomplete channel tuples.
append_tty_do1_subtracted_step();
tty_do1_noise_state.clear_step(); tty_do1_noise_state.clear_step();
} }
@ -2343,6 +2344,13 @@ int run(const Config& cfg) {
if (tty_di1_group_average && di1_changed) { if (tty_di1_group_average && di1_changed) {
append_tty_group_step(); append_tty_group_step();
tty_group_state.clear_step(); tty_group_state.clear_step();
} else if (tty_do1_noise_subtract) {
if (!tty_do1_noise_state.step_level_initialized) {
tty_do1_noise_state.start_new_step(di1_level);
} else if (di1_changed) {
append_tty_do1_subtracted_step();
tty_do1_noise_state.start_new_step(di1_level);
}
} }
if (!fast_tty_avg_stream_mode && if (!fast_tty_avg_stream_mode &&
@ -2356,9 +2364,6 @@ int run(const Config& cfg) {
if (fast_packet_frames < target_frames) { if (fast_packet_frames < target_frames) {
if (tty_do1_noise_subtract) { 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);
if (tty_do1_noise_state.advance_tick()) {
append_tty_do1_subtracted_step();
}
} else { } else {
tty_group_state.add_sample(lch, adc_raw_value); tty_group_state.add_sample(lch, adc_raw_value);
} }