test tty writer
This commit is contained in:
91
main.cpp
91
main.cpp
@ -381,7 +381,7 @@ void print_help(const char* exe_name) {
|
||||
<< " [internal_ref_hz:2000000]\n"
|
||||
<< " [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:/dev/ttyADC_data]\n"
|
||||
<< " [live_html:live_plot.html] [live_json:live_plot.json] [tty:/tmp/ttyADC_data]\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"
|
||||
@ -412,7 +412,7 @@ void print_help(const char* exe_name) {
|
||||
<< " 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\n"
|
||||
<< " tty:/dev/ttyADC_data -> write binary step frames to a Linux/POSIX tty path\n"
|
||||
<< " tty:/tmp/ttyADC_data -> write binary step frames to a Linux/POSIX tty or PTY link path\n"
|
||||
<< " If sample_clock_hz is omitted together with clock:internal, the maximum ADC speed is used\n"
|
||||
<< "\n"
|
||||
<< "Differential physical channel mapping:\n"
|
||||
@ -747,6 +747,19 @@ Fn load_symbol(ModuleHandle module, const char* name) {
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
Fn try_load_symbol(ModuleHandle module, const char* name) {
|
||||
#ifdef _WIN32
|
||||
const auto addr = GetProcAddress(module, name);
|
||||
return reinterpret_cast<Fn>(addr);
|
||||
#else
|
||||
dlerror();
|
||||
void* addr = dlsym(module, name);
|
||||
(void) dlerror();
|
||||
return reinterpret_cast<Fn>(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct Api {
|
||||
ModuleHandle x502_module = nullptr;
|
||||
ModuleHandle e502_module = nullptr;
|
||||
@ -755,6 +768,7 @@ struct Api {
|
||||
decltype(&X502_Free) Free = nullptr;
|
||||
decltype(&X502_Close) Close = nullptr;
|
||||
decltype(&X502_GetErrorString) GetErrorString = nullptr;
|
||||
decltype(&X502_GetDevInfo) GetDevInfo = nullptr;
|
||||
decltype(&X502_GetDevInfo2) GetDevInfo2 = nullptr;
|
||||
decltype(&X502_SetMode) SetMode = nullptr;
|
||||
decltype(&X502_StreamsStop) StreamsStop = nullptr;
|
||||
@ -804,7 +818,11 @@ struct Api {
|
||||
Free = load_symbol<decltype(Free)>(x502_module, "X502_Free");
|
||||
Close = load_symbol<decltype(Close)>(x502_module, "X502_Close");
|
||||
GetErrorString = load_symbol<decltype(GetErrorString)>(x502_module, "X502_GetErrorString");
|
||||
GetDevInfo2 = load_symbol<decltype(GetDevInfo2)>(x502_module, "X502_GetDevInfo2");
|
||||
GetDevInfo = try_load_symbol<decltype(GetDevInfo)>(x502_module, "X502_GetDevInfo");
|
||||
GetDevInfo2 = try_load_symbol<decltype(GetDevInfo2)>(x502_module, "X502_GetDevInfo2");
|
||||
if ((GetDevInfo == nullptr) && (GetDevInfo2 == nullptr)) {
|
||||
fail("Neither X502_GetDevInfo nor X502_GetDevInfo2 is available in x502 API library");
|
||||
}
|
||||
SetMode = load_symbol<decltype(SetMode)>(x502_module, "X502_SetMode");
|
||||
StreamsStop = load_symbol<decltype(StreamsStop)>(x502_module, "X502_StreamsStop");
|
||||
StreamsDisable = load_symbol<decltype(StreamsDisable)>(x502_module, "X502_StreamsDisable");
|
||||
@ -859,6 +877,8 @@ void expect_ok(const Api& api, int32_t err, const std::string& what) {
|
||||
constexpr uint32_t kE502DiSyn2Mask =
|
||||
(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 kStreamInputAdcFlag = 0x80000000U;
|
||||
constexpr uint32_t kStreamInputCalibratedAdcFlag = 0x40000000U;
|
||||
|
||||
using TickMs = uint64_t;
|
||||
|
||||
@ -1012,6 +1032,30 @@ int16_t pack_raw_code_to_int16(double avg_raw_code) {
|
||||
return static_cast<int16_t>(clamped);
|
||||
}
|
||||
|
||||
bool try_extract_raw_adc_code(uint32_t word, double& raw_code) {
|
||||
if ((word & kStreamInputAdcFlag) == 0U) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t value = 0;
|
||||
if ((word & kStreamInputCalibratedAdcFlag) != 0U) {
|
||||
const uint32_t payload = word & 0x00FFFFFFU;
|
||||
value = static_cast<int32_t>(payload);
|
||||
if ((payload & 0x00800000U) != 0U) {
|
||||
value |= static_cast<int32_t>(0xFF000000U);
|
||||
}
|
||||
} else {
|
||||
const uint32_t payload = word & 0x0000FFFFU;
|
||||
value = static_cast<int32_t>(payload);
|
||||
if ((payload & 0x00008000U) != 0U) {
|
||||
value |= static_cast<int32_t>(0xFFFF0000U);
|
||||
}
|
||||
}
|
||||
|
||||
raw_code = static_cast<double>(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct ConsoleCtrlGuard {
|
||||
bool installed = false;
|
||||
|
||||
@ -1113,7 +1157,11 @@ int run(const Config& cfg) {
|
||||
device.opened = true;
|
||||
|
||||
t_x502_info info{};
|
||||
err = api.GetDevInfo2(device.hnd, &info, sizeof(info));
|
||||
if (api.GetDevInfo2 != nullptr) {
|
||||
err = api.GetDevInfo2(device.hnd, &info, sizeof(info));
|
||||
} else {
|
||||
err = api.GetDevInfo(device.hnd, &info);
|
||||
}
|
||||
expect_ok(api, err, "Get device info");
|
||||
print_device_info(info);
|
||||
|
||||
@ -1356,7 +1404,9 @@ int run(const Config& cfg) {
|
||||
return;
|
||||
}
|
||||
if (tty_step.next_step_index >= 0xFFFFU) {
|
||||
fail("TTY protocol step index overflow within packet");
|
||||
std::cerr << "Warning: TTY protocol step index overflow, forcing tty packet restart\n";
|
||||
tty_step.reset_packet();
|
||||
tty_writer->emit_packet_start();
|
||||
}
|
||||
|
||||
const double ch1_avg = tty_step.sum_ch1 / static_cast<double>(tty_step.count_ch1);
|
||||
@ -1531,18 +1581,18 @@ int run(const Config& cfg) {
|
||||
|
||||
uint32_t raw_adc_count = 0;
|
||||
if (tty_writer) {
|
||||
raw_adc_count = static_cast<uint32_t>(adc_raw_buffer.size());
|
||||
const int32_t raw_process_err = api.ProcessData(device.hnd,
|
||||
raw.data(),
|
||||
static_cast<uint32_t>(recvd),
|
||||
0,
|
||||
adc_raw_buffer.data(),
|
||||
&raw_adc_count,
|
||||
nullptr,
|
||||
nullptr);
|
||||
expect_ok(api, raw_process_err, "Process raw ADC data");
|
||||
for (std::size_t i = 0; i < recvd; ++i) {
|
||||
double raw_code = 0.0;
|
||||
if (!try_extract_raw_adc_code(raw[i], raw_code)) {
|
||||
continue;
|
||||
}
|
||||
if (raw_adc_count >= adc_raw_buffer.size()) {
|
||||
fail("Raw ADC parsing overflowed the temporary buffer");
|
||||
}
|
||||
adc_raw_buffer[raw_adc_count++] = raw_code;
|
||||
}
|
||||
if (raw_adc_count != adc_count) {
|
||||
fail("Raw ADC processing returned a different sample count than voltage processing");
|
||||
fail("Raw ADC parsing returned a different sample count than voltage processing");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1624,7 +1674,14 @@ int run(const Config& cfg) {
|
||||
start_packet();
|
||||
}
|
||||
|
||||
if (!packet_active && start_edge) {
|
||||
if (packet_active && start_edge) {
|
||||
finish_packet(PacketCloseReason::ExternalStopEdge);
|
||||
if ((cfg.packet_limit != 0U) && (total_completed_packets >= cfg.packet_limit)) {
|
||||
stop_loop_requested = true;
|
||||
continue;
|
||||
}
|
||||
start_packet();
|
||||
} else if (!packet_active && start_edge) {
|
||||
start_packet();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user