Loop Timing Witness
Native controller and runtime interfaces; hardware qualification pending
Loading...
Searching...
No Matches
run_output.h
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Commercial license available
3// © Concepts 1996–2026 Miroslav Šotek. All rights reserved.
4// © Code 2020–2026 Miroslav Šotek. All rights reserved.
5// ORCID: 0009-0009-3560-0851
6// Contact: www.anulum.li | protoscience@anulum.li
7// Loop Timing Witness — exclusive raw event and controller trace output
8
12
13#ifndef WITNESS_RUN_OUTPUT_H
14#define WITNESS_RUN_OUTPUT_H
15#include "run_configuration.h"
16#include "refusal.h"
17#include "exclusive_output.h"
18#include <array>
19#include <cstdio>
20#include <stdexcept>
21
22namespace witness {
24class RunOutput {
25 ExclusiveOutput events, tracking;
26
27 public:
29 RunOutput(const char *event_path, const char *tracking_path)
30 : events(event_path, OutputFormat::binary, "cannot create exclusive event output"),
31 tracking(tracking_path, OutputFormat::text, "cannot create exclusive tracking output") {
32 auto *trace = tracking.stream("tracking output is closed");
33 if (std::fputs(
34 "cycle,reference_raw,output_raw,velocity_raw,command_raw,integral_raw,derivative_raw,clipped,integral_held,submitted,sample_ticks,irq_generation,overload_work\n",
35 trace) < 0 ||
36 std::fflush(trace) != 0)
37 throw witness::RuntimeRefused("cannot write tracking header");
38 }
39
40 ~RunOutput() = default;
41 RunOutput(const RunOutput &) = delete;
42 RunOutput &operator=(const RunOutput &) = delete;
43
45 void event(const std::array<std::uint32_t, 4> &words) {
46 auto *stream = events.stream("event output is closed");
47 std::array<unsigned char, 16> bytes{};
48 for (std::size_t word = 0; word < 4; ++word)
49 for (unsigned byte = 0; byte < 4; ++byte)
50 bytes[word * 4 + byte] = static_cast<unsigned char>(words[word] >> (byte * 8));
51 if (std::fwrite(bytes.data(), 1, bytes.size(), stream) != bytes.size())
52 throw witness::RuntimeRefused("cannot write event record");
53 }
54
55 void sample(std::int32_t reference, std::int32_t position, std::int32_t velocity,
56 const witness_command &command, bool submitted, std::uint64_t ticks,
57 std::uint64_t generation, std::uint64_t work) {
58 auto *stream = tracking.stream("tracking output is closed");
59 if (std::fprintf(stream, "%u,%d,%d,%d,%d,%d,%d,%u,%u,%u,%llu,%llu,%llu\n", command.cycle,
60 reference, position, velocity, command.command, command.integral,
61 command.derivative, static_cast<unsigned>(command.clipped),
62 static_cast<unsigned>(command.integral_held),
63 static_cast<unsigned>(submitted), static_cast<unsigned long long>(ticks),
64 static_cast<unsigned long long>(generation),
65 static_cast<unsigned long long>(work)) < 0)
66 throw witness::RuntimeRefused("cannot write tracking sample");
67 }
68
69 void finish() {
70 if (!events.is_open() || !tracking.is_open())
71 throw witness::RuntimeRefused("run output is closed");
72 const int event_status = events.close("event output is closed");
73 const int tracking_status = tracking.close("tracking output is closed");
74 if (event_status || tracking_status)
75 throw witness::RuntimeRefused("cannot finish run output");
76 }
77};
78} // namespace witness
79#endif
~RunOutput()=default
void event(const std::array< std::uint32_t, 4 > &words)
Definition run_output.h:45
void sample(std::int32_t reference, std::int32_t position, std::int32_t velocity, const witness_command &command, bool submitted, std::uint64_t ticks, std::uint64_t generation, std::uint64_t work)
Definition run_output.h:55
RunOutput(const char *event_path, const char *tracking_path)
Definition run_output.h:29