35 bool ready =
false, started =
false, completed =
false, have_previous =
false;
36 std::uint32_t consumer = 0, previous_cycle = 0;
37 std::uint64_t previous_ticks = 0, previous_generation = 0;
40 std::uint32_t memory(std::size_t offset) {
return device.read_memory32(shared + offset); }
43 std::uint64_t wide(std::size_t offset) {
44 const auto low = memory(offset);
45 return low | (
static_cast<std::uint64_t
>(memory(offset + 4)) << 32);
50 const auto &c = configuration.coefficients;
51 const std::array<std::uint32_t, 15> expected{configuration.cycles,
52 configuration.period_ticks,
53 configuration.lqr ? 1U : 0U,
54 configuration.overload_iterations,
55 static_cast<std::uint32_t
>(c.kp),
56 static_cast<std::uint32_t
>(c.ki_period),
57 static_cast<std::uint32_t
>(c.derivative_decay),
58 static_cast<std::uint32_t
>(c.derivative_gain),
59 static_cast<std::uint32_t
>(c.position_gain),
60 static_cast<std::uint32_t
>(c.velocity_gain),
61 static_cast<std::uint32_t
>(c.reference_gain),
62 static_cast<std::uint32_t
>(c.output_min),
63 static_cast<std::uint32_t
>(c.output_max),
64 static_cast<std::uint32_t
>(c.integral_min),
65 static_cast<std::uint32_t
>(c.integral_max)};
66 for (std::size_t index = 0; index < expected.size(); ++index)
69 "AMP running firmware contract differs from logger configuration");
75 void consume(std::uint32_t producer) {
78 for (
unsigned batch = 0; batch < 8 && consumer != producer; ++batch) {
81 const auto ticks = wide(slot);
82 const auto generation = wide(slot + 8);
83 const auto work = wide(slot + 16);
84 const auto cycle = memory(slot + 24);
85 const auto reference =
signed_word(memory(slot + 28));
86 const auto position =
signed_word(memory(slot + 32));
87 const auto velocity =
signed_word(memory(slot + 36));
88 const auto command =
signed_word(memory(slot + 40));
89 const auto integral =
signed_word(memory(slot + 44));
90 const auto derivative =
signed_word(memory(slot + 48));
91 const auto clipped = memory(slot + 52);
92 const auto held = memory(slot + 56);
93 const auto submitted = memory(slot + 60);
94 if (cycle >= configuration.cycles || !generation || clipped > 1 || held > 1 ||
96 (have_previous && (cycle <= previous_cycle || ticks <= previous_ticks ||
97 generation <= previous_generation)))
99 "AMP telemetry contradicts the observed sample sequence");
101 derivative, clipped != 0, held != 0};
102 output.sample(reference, position, velocity, observed, submitted != 0, ticks,
104 previous_cycle = cycle;
105 previous_ticks = ticks;
106 previous_generation = generation;
107 have_previous =
true;
117 std::uint64_t mailbox_address,
const RunHooks *acquisition =
nullptr)
118 : device(backend), configuration(run), output(files), hooks(acquisition),
119 shared(mailbox_address) {
137 "AMP firmware refused or telemetry overflowed: cause=" +