13#ifndef WITNESS_RUN_CONTROL_H
14#define WITNESS_RUN_CONTROL_H
36 std::memcpy(&result, &value,
sizeof(result));
41template <
class Device> std::uint32_t
read_register(Device &device, std::uint8_t address) {
42 const auto result = device.read(address);
43 if (result.response != 0)
49template <
class Device>
50void write_register(Device &device, std::uint8_t address, std::uint32_t value) {
51 if (device.write(address, value, 15).response != 0)
64 const auto start = device.time();
66 if (device.time() - start > 1000000000)
87 for (
unsigned batch = 0; batch < 8 && (
read_register(device, 0x90) & 1); ++batch) {
88 std::array<std::uint32_t, 4> words{};
89 for (
unsigned index = 0; index < 4; ++index)
90 words[index] =
read_register(device,
static_cast<std::uint8_t
>(0x80 + index * 4));
98template <
class Device>
101 std::uint32_t &previous_cycle,
bool &have_previous) {
107 const auto ticks = low | (
static_cast<std::uint64_t
>(
read_register(device, 0x20)) << 32);
108 if (cycle >= configuration.
cycles || (have_previous && cycle <= previous_cycle))
110 previous_cycle = cycle;
111 have_previous =
true;
113 const bool computed = configuration.
lqr
115 position, velocity, &command)
117 reference, position, &command);
120 std::uint64_t work = 0;
122 volatile std::uint64_t accumulator = 0;
124 accumulator = accumulator +
static_cast<std::uint64_t
>(index) * index;
128 bool submitted =
false;
132 const auto commit = device.write(0x30, 1, 15);
133 if (commit.response != 0 && !(
read_register(device, 4) & 12))
135 submitted = commit.response == 0;
137 output.
sample(reference, position, velocity, command, submitted, ticks, generation, work);
142template <
class Device>
149 std::uint32_t previous_cycle = 0;
150 bool have_previous =
false, finished =
false;
151 const auto run_limit =
157 const auto run_start = device.time();
161 if (device.wait_interrupt(1000000)) {
163 const auto generation =
164 low | (
static_cast<std::uint64_t
>(
read_register(device, 0xa0)) << 32);
166 finished = (status & 4) != 0;
167 if (!finished && !(status & 8))
168 control_sample(device, configuration, state, output, result, generation,
169 previous_cycle, have_previous);
172 if (device.time() - run_start > run_limit)
176 const auto drain_start = device.time();
181 if (device.time() - drain_start > 1000000000)
void event(const std::array< std::uint32_t, 4 > &words)
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)
void validate_configuration(const RunConfiguration &configuration)
std::uint32_t read_register(Device &device, std::uint8_t address)
void drain_available(Device &device, RunOutput &output, RunResult &result)
std::int32_t signed_word(std::uint32_t value)
void configure_run(Device &device, const RunConfiguration &configuration)
void control_sample(Device &device, const RunConfiguration &configuration, witness_pid_state &state, RunOutput &output, RunResult &result, std::uint64_t generation, std::uint32_t &previous_cycle, bool &have_previous)
void write_register(Device &device, std::uint8_t address, std::uint32_t value)
RunResult execute_run(Device &device, const RunConfiguration &configuration, RunOutput &output, const RunHooks *hooks=nullptr)
witness_coefficients coefficients
std::uint32_t reference_mode
std::uint32_t fault_cycle
std::uint32_t period_ticks
std::uint32_t modeled_overload_ns
std::uint32_t overload_iterations
std::uint32_t fault_periods
std::function< void()> check
std::function< void()> finish
std::function< void()> start
bool witness_lqr_step(const witness_coefficients *coefficients, uint32_t cycle, int32_t reference, int32_t position, int32_t velocity, witness_command *command)
void witness_pid_reset(witness_pid_state *state)
bool witness_pid_step(const witness_coefficients *coefficients, witness_pid_state *state, uint32_t cycle, int32_t reference, int32_t position, witness_command *command)