noise sub mode
This commit is contained in:
277
main.cpp
277
main.cpp
@ -114,6 +114,8 @@ struct Config {
|
||||
std::optional<std::string> tty_path;
|
||||
bool di1_group_average = false;
|
||||
bool do1_toggle_per_frame = false;
|
||||
bool do1_noise_subtract = false;
|
||||
std::optional<uint32_t> noise_avg_steps;
|
||||
};
|
||||
|
||||
[[noreturn]] void fail(const std::string& message) {
|
||||
@ -471,7 +473,7 @@ void print_help(const char* exe_name) {
|
||||
<< " [di1:zero|trace|ignore]\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"
|
||||
<< " [do1_toggle_per_frame]\n"
|
||||
<< " [do1_toggle_per_frame] [do1_noise_subtract] [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"
|
||||
<< " [buffer_words:8388608] [step_words:32768]\n"
|
||||
<< " [pullup_syn1] [pullup_syn2] [pulldown_conv_in] [pulldown_start_in]\n"
|
||||
@ -496,20 +498,25 @@ void print_help(const char* exe_name) {
|
||||
<< " stats_period_ms:1000 -> print online transfer/capture statistics every 1000 ms (0 disables)\n"
|
||||
<< " recv_block:32768 -> request up to 32768 raw 32-bit words per X502_Recv() call\n"
|
||||
<< " live_update_period_ms:1000 -> refresh live HTML/JSON no more than once per second"
|
||||
<< " (ignored in tty+di1_group_avg fast mode)\n"
|
||||
<< " (ignored in tty fast stream-only modes)\n"
|
||||
<< " svg_history_packets:50 -> keep last 50 packets in RAM for final SVG (0 keeps all, risky)"
|
||||
<< " (ignored in tty+di1_group_avg fast mode)\n"
|
||||
<< " (ignored in tty fast stream-only modes)\n"
|
||||
<< " duration_ms:100 -> max packet length if stop edge does not arrive\n"
|
||||
<< " packet_limit:0 -> 0 means continuous until Ctrl+C, N means stop after N packets\n"
|
||||
<< " buffer_words:8388608 -> input stream buffer size 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 outside tty+di1_group_avg fast mode\n"
|
||||
<< " live_html/live_json -> live graph files updated as packets arrive outside tty fast stream-only modes\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"
|
||||
<< " do1_toggle_per_frame -> hardware cyclic DO1 pattern in module memory:\n"
|
||||
<< " DO1 outputs 00110011... continuously (toggle every 2 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"
|
||||
<< " do1_noise_subtract -> with tty + do1_toggle_per_frame, use programmed DO1 phase (0011...)\n"
|
||||
<< " to average recent noise steps and subtract it from useful steps before tty output\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"
|
||||
<< " (required when do1_noise_subtract is enabled)\n"
|
||||
<< " tty fast stream-only modes -> di1_group_avg or do1_noise_subtract; skip CSV/SVG/live outputs\n"
|
||||
<< " If sample_clock_hz is omitted together with clock:internal, the maximum ADC speed is used\n"
|
||||
<< "\n"
|
||||
<< "Profiles:\n"
|
||||
@ -532,10 +539,12 @@ void print_help(const char* exe_name) {
|
||||
<< "This build enables synchronous DIN together with ADC. DI_SYN2 stop edges are detected\n"
|
||||
<< "inside the same input stream, packets are split continuously by DI_SYN2 edges, and DI1\n"
|
||||
<< "can either zero ADC samples on change, be exported as a separate synchronous trace, or be ignored.\n"
|
||||
<< "Outside tty+di1_group_avg fast mode, open live_plot.html in a browser to see the live graph update over time.\n"
|
||||
<< "Outside tty fast stream-only modes, 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"
|
||||
<< "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"
|
||||
<< "For DO1-phase subtraction, 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"
|
||||
<< "Amplitude mode keeps the raw AD8317 voltage as captured on X1; no inversion is applied.\n"
|
||||
<< "\n"
|
||||
<< "Phase profile example:\n"
|
||||
@ -552,7 +561,13 @@ void print_help(const char* exe_name) {
|
||||
<< " " << exe_name
|
||||
<< " profile:amplitude 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";
|
||||
<< " tty:/tmp/ttyADC_data\n"
|
||||
<< "\n"
|
||||
<< "Amplitude TTY DO1 noise subtract example:\n"
|
||||
<< " " << exe_name
|
||||
<< " profile:amplitude clock:internal internal_ref_hz:2000000 start:di_syn2_rise stop:di_syn2_fall"
|
||||
<< " sample_clock_hz:max range:0.2 do1_toggle_per_frame do1_noise_subtract noise_avg_steps:16"
|
||||
<< " duration_ms:100 packet_limit:0 tty:/tmp/ttyADC_data\n";
|
||||
}
|
||||
|
||||
Config parse_args(int argc, char** argv) {
|
||||
@ -636,10 +651,18 @@ Config parse_args(int argc, char** argv) {
|
||||
cfg.di1_group_average = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "do1_noise_subtract") {
|
||||
cfg.do1_noise_subtract = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "do1_toggle_per_frame") {
|
||||
cfg.do1_toggle_per_frame = true;
|
||||
continue;
|
||||
}
|
||||
if (starts_with(arg, "noise_avg_steps:")) {
|
||||
cfg.noise_avg_steps = parse_u32(arg.substr(16), "noise_avg_steps");
|
||||
continue;
|
||||
}
|
||||
if (starts_with(arg, "sample_clock_hz:")) {
|
||||
const std::string value = trim_copy(arg.substr(16));
|
||||
cfg.sample_clock_specified = true;
|
||||
@ -751,7 +774,7 @@ Config parse_args(int argc, char** argv) {
|
||||
cfg.live_update_period_ms = std::max<uint32_t>(cfg.live_update_period_ms, 1000U);
|
||||
}
|
||||
}
|
||||
if (cfg.tty_path && cfg.di1_group_average) {
|
||||
if (cfg.tty_path && (cfg.di1_group_average || cfg.do1_noise_subtract)) {
|
||||
if (!cfg.recv_block_specified) {
|
||||
cfg.recv_block_words = std::max<uint32_t>(cfg.recv_block_words, 65536U);
|
||||
}
|
||||
@ -774,6 +797,25 @@ Config parse_args(int argc, char** argv) {
|
||||
if (cfg.di1_group_average && (cfg.di1_mode != Di1Mode::Trace)) {
|
||||
fail("di1_group_avg requires di1:trace");
|
||||
}
|
||||
if (cfg.do1_noise_subtract) {
|
||||
if (!cfg.tty_path.has_value()) {
|
||||
fail("do1_noise_subtract requires tty:<path>");
|
||||
}
|
||||
if (!cfg.do1_toggle_per_frame) {
|
||||
fail("do1_noise_subtract requires do1_toggle_per_frame");
|
||||
}
|
||||
if (cfg.di1_group_average) {
|
||||
fail("do1_noise_subtract is incompatible with di1_group_avg");
|
||||
}
|
||||
if (!cfg.noise_avg_steps.has_value()) {
|
||||
fail("do1_noise_subtract requires noise_avg_steps:N");
|
||||
}
|
||||
if (*cfg.noise_avg_steps == 0U) {
|
||||
fail("noise_avg_steps must be > 0");
|
||||
}
|
||||
} else if (cfg.noise_avg_steps.has_value()) {
|
||||
fail("noise_avg_steps:N can only be used together with do1_noise_subtract");
|
||||
}
|
||||
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");
|
||||
}
|
||||
@ -1188,6 +1230,110 @@ struct TtyGroupAverageState {
|
||||
}
|
||||
};
|
||||
|
||||
struct Do1NoiseSubtractState {
|
||||
uint32_t noise_avg_steps = 0;
|
||||
std::array<std::vector<double>, 2> noise_ring;
|
||||
std::array<std::size_t, 2> noise_ring_head {};
|
||||
std::array<std::size_t, 2> noise_ring_size {};
|
||||
std::array<double, 2> noise_ring_sum {};
|
||||
std::array<double, 2> step_sum {};
|
||||
std::array<uint32_t, 2> step_count {};
|
||||
uint32_t ticks_in_step = 0;
|
||||
bool step_do1_high = false;
|
||||
uint16_t next_index = 1;
|
||||
|
||||
void configure(uint32_t history_steps) {
|
||||
noise_avg_steps = history_steps;
|
||||
for (auto& ring : noise_ring) {
|
||||
ring.assign(noise_avg_steps, 0.0);
|
||||
}
|
||||
reset_packet();
|
||||
}
|
||||
|
||||
void clear_step() {
|
||||
step_sum = {};
|
||||
step_count = {};
|
||||
ticks_in_step = 0;
|
||||
}
|
||||
|
||||
void reset_packet() {
|
||||
clear_step();
|
||||
step_do1_high = false;
|
||||
next_index = 1;
|
||||
noise_ring_head = {};
|
||||
noise_ring_size = {};
|
||||
noise_ring_sum = {};
|
||||
}
|
||||
|
||||
void add_sample(uint32_t lch, double raw_code) {
|
||||
if (lch >= step_sum.size()) {
|
||||
return;
|
||||
}
|
||||
step_sum[lch] += raw_code;
|
||||
++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 {
|
||||
return (step_count[0] != 0U) && ((channel_count <= 1U) || (step_count[1] != 0U));
|
||||
}
|
||||
|
||||
double step_average(uint32_t lch) const {
|
||||
if ((lch >= step_sum.size()) || (step_count[lch] == 0U)) {
|
||||
return 0.0;
|
||||
}
|
||||
return step_sum[lch] / static_cast<double>(step_count[lch]);
|
||||
}
|
||||
|
||||
void push_noise_average(uint32_t lch, double avg_value) {
|
||||
if ((noise_avg_steps == 0U) || (lch >= noise_ring.size())) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& ring = noise_ring[lch];
|
||||
auto& head = noise_ring_head[lch];
|
||||
auto& size = noise_ring_size[lch];
|
||||
auto& sum = noise_ring_sum[lch];
|
||||
|
||||
if (size < noise_avg_steps) {
|
||||
ring[size] = avg_value;
|
||||
sum += avg_value;
|
||||
++size;
|
||||
return;
|
||||
}
|
||||
|
||||
sum -= ring[head];
|
||||
ring[head] = avg_value;
|
||||
sum += avg_value;
|
||||
head = (head + 1U) % noise_avg_steps;
|
||||
}
|
||||
|
||||
double noise_baseline(uint32_t lch) const {
|
||||
if (lch >= noise_ring_size.size()) {
|
||||
return 0.0;
|
||||
}
|
||||
const std::size_t size = noise_ring_size[lch];
|
||||
if (size == 0U) {
|
||||
return 0.0;
|
||||
}
|
||||
return noise_ring_sum[lch] / static_cast<double>(size);
|
||||
}
|
||||
|
||||
void finish_step() {
|
||||
step_do1_high = !step_do1_high;
|
||||
step_sum = {};
|
||||
step_count = {};
|
||||
}
|
||||
};
|
||||
|
||||
int16_t pack_raw_code_to_int16(double avg_raw_code) {
|
||||
const double scaled =
|
||||
avg_raw_code * 32767.0 / static_cast<double>(X502_ADC_SCALE_CODE_MAX);
|
||||
@ -1467,9 +1613,14 @@ int run(const Config& cfg) {
|
||||
std::size_t tty_ring_capacity_bytes = 0;
|
||||
std::unique_ptr<TtyProtocolWriter> tty_writer;
|
||||
const bool tty_di1_group_average = cfg.tty_path.has_value() && cfg.di1_group_average;
|
||||
const bool fast_tty_avg_stream_mode = tty_di1_group_average;
|
||||
const bool tty_do1_noise_subtract = cfg.tty_path.has_value() && cfg.do1_noise_subtract;
|
||||
const bool fast_tty_avg_stream_mode = tty_di1_group_average || tty_do1_noise_subtract;
|
||||
const uint16_t tty_packet_start_marker =
|
||||
(cfg.profile == CaptureProfile::Amplitude) ? 0x001AU : 0x000AU;
|
||||
const std::string fast_tty_mode_name =
|
||||
tty_do1_noise_subtract ? std::string("do1_noise_subtract")
|
||||
: (tty_di1_group_average ? std::string("di1_group_avg")
|
||||
: std::string("none"));
|
||||
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_bytes = typical_tty_batch_frames * sizeof(uint16_t) * 4U;
|
||||
@ -1480,7 +1631,7 @@ int run(const Config& cfg) {
|
||||
}
|
||||
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);
|
||||
if (!tty_di1_group_average) {
|
||||
if (!tty_di1_group_average && !tty_do1_noise_subtract) {
|
||||
tty_writer->emit_packet_start(tty_packet_start_marker);
|
||||
}
|
||||
}
|
||||
@ -1491,13 +1642,16 @@ int run(const Config& cfg) {
|
||||
writer->initialize_csv(cfg.channel_count, cfg.di1_mode == Di1Mode::Trace);
|
||||
}
|
||||
if (fast_tty_avg_stream_mode) {
|
||||
std::cout << " tty avg stream-only mode: enabled\n"
|
||||
std::cout << " tty fast stream-only mode: enabled (" << fast_tty_mode_name << ")\n"
|
||||
<< " tty stream output: " << *cfg.tty_path << "\n"
|
||||
<< " tty ring buffer bytes: " << tty_ring_capacity_bytes << "\n"
|
||||
<< " recv block words: " << cfg.recv_block_words << "\n"
|
||||
<< " input step words: " << cfg.input_step_words << "\n"
|
||||
<< " input buffer words: " << cfg.input_buffer_words << "\n"
|
||||
<< " tty di1_group_avg: enabled\n"
|
||||
<< " tty di1_group_avg: " << (tty_di1_group_average ? "enabled" : "disabled") << "\n"
|
||||
<< " tty do1_noise_subtract: " << (tty_do1_noise_subtract ? "enabled" : "disabled") << "\n"
|
||||
<< " noise_avg_steps: "
|
||||
<< (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";
|
||||
} else {
|
||||
std::cout << " live plot html: " << writer->live_html_path() << "\n"
|
||||
@ -1513,6 +1667,11 @@ int run(const Config& cfg) {
|
||||
: (cfg.di1_group_average ? std::string("requested, tty disabled")
|
||||
: std::string("disabled")))
|
||||
<< "\n"
|
||||
<< " tty do1_noise_subtract: "
|
||||
<< (tty_do1_noise_subtract ? std::string("enabled")
|
||||
: (cfg.do1_noise_subtract ? std::string("requested, tty disabled")
|
||||
: std::string("disabled")))
|
||||
<< "\n"
|
||||
<< " SVG history packets kept in RAM: "
|
||||
<< ((cfg.svg_history_packets == 0U) ? std::string("all (unbounded)") : std::to_string(cfg.svg_history_packets))
|
||||
<< "\n";
|
||||
@ -1579,8 +1738,12 @@ int run(const Config& cfg) {
|
||||
PacketAccumulator current_packet;
|
||||
TtyContinuousState tty_state;
|
||||
TtyGroupAverageState tty_group_state;
|
||||
Do1NoiseSubtractState tty_do1_noise_state;
|
||||
std::vector<uint16_t> tty_frame_words;
|
||||
tty_frame_words.reserve(static_cast<std::size_t>(read_capacity_words) * 2U + 16U);
|
||||
if (tty_do1_noise_subtract) {
|
||||
tty_do1_noise_state.configure(*cfg.noise_avg_steps);
|
||||
}
|
||||
if (!fast_tty_avg_stream_mode) {
|
||||
current_packet.reset(target_frames, cfg.channel_count);
|
||||
}
|
||||
@ -1647,11 +1810,13 @@ int run(const Config& cfg) {
|
||||
<< ", DIN samples/s=" << din_samples_per_s
|
||||
<< ", frames/s per channel=" << frames_per_ch_per_s
|
||||
<< ", packets/s=" << packets_per_s;
|
||||
if (cfg.di1_mode == Di1Mode::ZeroOnChange) {
|
||||
std::cout << ", zeroed on DI1 change=" << zeroed_fraction << "% ("
|
||||
<< stats_zeroed_samples << "/" << stats_stored_adc_samples << ")";
|
||||
} else if (cfg.di1_mode == Di1Mode::Trace) {
|
||||
std::cout << ", DI1 trace=enabled";
|
||||
if (!fast_tty_avg_stream_mode) {
|
||||
if (cfg.di1_mode == Di1Mode::ZeroOnChange) {
|
||||
std::cout << ", zeroed on DI1 change=" << zeroed_fraction << "% ("
|
||||
<< stats_zeroed_samples << "/" << stats_stored_adc_samples << ")";
|
||||
} else if (cfg.di1_mode == Di1Mode::Trace) {
|
||||
std::cout << ", DI1 trace=enabled";
|
||||
}
|
||||
}
|
||||
if (tty_writer) {
|
||||
std::cout << ", tty_frames_written=" << tty_frames_written
|
||||
@ -1706,6 +1871,45 @@ int run(const Config& cfg) {
|
||||
++packet_avg_steps;
|
||||
};
|
||||
|
||||
auto append_tty_do1_subtracted_step = [&]() {
|
||||
if (!tty_do1_noise_subtract) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tty_do1_noise_state.has_complete_step(cfg.channel_count)) {
|
||||
tty_do1_noise_state.finish_step();
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (tty_do1_noise_state.step_do1_high) {
|
||||
tty_do1_noise_state.push_noise_average(0U, ch1_avg);
|
||||
if (cfg.channel_count > 1U) {
|
||||
tty_do1_noise_state.push_noise_average(1U, ch2_avg);
|
||||
}
|
||||
tty_do1_noise_state.finish_step();
|
||||
return;
|
||||
}
|
||||
|
||||
if (tty_do1_noise_state.next_index >= 0xFFFFU) {
|
||||
fail("TTY protocol step index overflow within packet");
|
||||
}
|
||||
|
||||
const double ch1_corrected = ch1_avg - tty_do1_noise_state.noise_baseline(0U);
|
||||
const double ch2_corrected =
|
||||
(cfg.channel_count <= 1U) ? 0.0 : (ch2_avg - tty_do1_noise_state.noise_baseline(1U));
|
||||
|
||||
append_tty_frame((cfg.profile == CaptureProfile::Amplitude) ? 0x001AU : 0x000AU,
|
||||
tty_do1_noise_state.next_index,
|
||||
static_cast<uint16_t>(pack_raw_code_to_int16(ch1_corrected)),
|
||||
static_cast<uint16_t>(pack_raw_code_to_int16(ch2_corrected)));
|
||||
++tty_do1_noise_state.next_index;
|
||||
++packet_avg_steps;
|
||||
tty_do1_noise_state.finish_step();
|
||||
};
|
||||
|
||||
auto flush_tty_frames = [&]() {
|
||||
if (!tty_writer || tty_frame_words.empty()) {
|
||||
return;
|
||||
@ -1736,6 +1940,9 @@ int run(const Config& cfg) {
|
||||
if (tty_di1_group_average) {
|
||||
tty_group_state.reset_packet();
|
||||
append_tty_packet_start();
|
||||
} else if (tty_do1_noise_subtract) {
|
||||
tty_do1_noise_state.reset_packet();
|
||||
append_tty_packet_start();
|
||||
}
|
||||
packet_active = true;
|
||||
};
|
||||
@ -1752,6 +1959,9 @@ int run(const Config& cfg) {
|
||||
if (tty_di1_group_average) {
|
||||
append_tty_group_step();
|
||||
tty_group_state.clear_step();
|
||||
} else if (tty_do1_noise_subtract) {
|
||||
// Keep only complete programmed DO1 steps. Partial steps are dropped on packet close.
|
||||
tty_do1_noise_state.clear_step();
|
||||
}
|
||||
|
||||
const std::size_t frames = fast_tty_avg_stream_mode
|
||||
@ -1870,6 +2080,8 @@ int run(const Config& cfg) {
|
||||
}
|
||||
if (tty_di1_group_average) {
|
||||
tty_group_state.clear_step();
|
||||
} else if (tty_do1_noise_subtract) {
|
||||
tty_do1_noise_state.clear_step();
|
||||
}
|
||||
};
|
||||
|
||||
@ -2142,7 +2354,14 @@ int run(const Config& cfg) {
|
||||
|
||||
if (fast_tty_avg_stream_mode) {
|
||||
if (fast_packet_frames < target_frames) {
|
||||
tty_group_state.add_sample(lch, adc_raw_value);
|
||||
if (tty_do1_noise_subtract) {
|
||||
tty_do1_noise_state.add_sample(lch, adc_raw_value);
|
||||
if (tty_do1_noise_state.advance_tick()) {
|
||||
append_tty_do1_subtracted_step();
|
||||
}
|
||||
} else {
|
||||
tty_group_state.add_sample(lch, adc_raw_value);
|
||||
}
|
||||
if (lch == (cfg.channel_count - 1U)) {
|
||||
++fast_packet_frames;
|
||||
++total_completed_frames;
|
||||
@ -2234,7 +2453,7 @@ int run(const Config& cfg) {
|
||||
}
|
||||
} else {
|
||||
std::cout << "Captured " << total_completed_packets
|
||||
<< " packet(s) in tty avg stream-only mode\n";
|
||||
<< " packet(s) in tty fast stream-only mode (" << fast_tty_mode_name << ")\n";
|
||||
}
|
||||
std::cout << "Average stats: "
|
||||
<< "MB/s=" << std::fixed << std::setprecision(3)
|
||||
@ -2254,14 +2473,16 @@ int run(const Config& cfg) {
|
||||
<< (static_cast<double>(total_completed_packets) /
|
||||
std::max(1e-9, static_cast<double>(tick_count_ms() - capture_loop_start) / 1000.0))
|
||||
<< ", packets captured=" << total_completed_packets;
|
||||
if (cfg.di1_mode == Di1Mode::ZeroOnChange) {
|
||||
std::cout << ", zeroed on DI1 change="
|
||||
<< ((total_stored_adc_samples == 0U)
|
||||
? 0.0
|
||||
: (100.0 * static_cast<double>(total_zeroed_samples) / static_cast<double>(total_stored_adc_samples)))
|
||||
<< "% (" << total_zeroed_samples << "/" << total_stored_adc_samples << ")";
|
||||
} else if (cfg.di1_mode == Di1Mode::Trace) {
|
||||
std::cout << ", DI1 trace=enabled";
|
||||
if (!fast_tty_avg_stream_mode) {
|
||||
if (cfg.di1_mode == Di1Mode::ZeroOnChange) {
|
||||
std::cout << ", zeroed on DI1 change="
|
||||
<< ((total_stored_adc_samples == 0U)
|
||||
? 0.0
|
||||
: (100.0 * static_cast<double>(total_zeroed_samples) / static_cast<double>(total_stored_adc_samples)))
|
||||
<< "% (" << total_zeroed_samples << "/" << total_stored_adc_samples << ")";
|
||||
} else if (cfg.di1_mode == Di1Mode::Trace) {
|
||||
std::cout << ", DI1 trace=enabled";
|
||||
}
|
||||
}
|
||||
if (tty_writer) {
|
||||
std::cout << ", tty_frames_written=" << tty_final_stats.frames_written
|
||||
@ -2269,7 +2490,7 @@ int run(const Config& cfg) {
|
||||
<< ", tty_ring_overflows=" << tty_final_stats.ring_overflows;
|
||||
}
|
||||
if (fast_tty_avg_stream_mode) {
|
||||
std::cout << ", tty avg stream-only mode=enabled";
|
||||
std::cout << ", tty fast stream-only mode=" << fast_tty_mode_name;
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
|
||||
45
run_do1_noise_subtract.sh
Executable file
45
run_do1_noise_subtract.sh
Executable file
@ -0,0 +1,45 @@
|
||||
#!/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}"
|
||||
NOISE_AVG_STEPS="${NOISE_AVG_STEPS:-}"
|
||||
|
||||
if [[ ! -x "$BIN" ]]; then
|
||||
echo "Binary '$BIN' not found or not executable. Run ./build_main.sh first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$NOISE_AVG_STEPS" ]]; then
|
||||
echo "Set NOISE_AVG_STEPS to a positive integer, for example: NOISE_AVG_STEPS=16" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ "$NOISE_AVG_STEPS" =~ ^[0-9]+$ ]] || [[ "$NOISE_AVG_STEPS" -eq 0 ]]; then
|
||||
echo "NOISE_AVG_STEPS must be a positive integer, got '$NOISE_AVG_STEPS'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -d "$LIB_DIR" ]]; then
|
||||
export LD_LIBRARY_PATH="${LIB_DIR}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
|
||||
fi
|
||||
|
||||
exec "$BIN" \
|
||||
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_noise_subtract \
|
||||
"noise_avg_steps:${NOISE_AVG_STEPS}" \
|
||||
profile:amplitude \
|
||||
"tty:${TTY_PATH}" \
|
||||
"$@"
|
||||
Reference in New Issue
Block a user