REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
run_manager.cpp
Go to the documentation of this file.
1#include "run/run_manager.h"
2#include "mode/counters.h"
3
4#include <Arduino.h>
5#include <cmath>
6#include <cstdlib>
7
8#include <daq/daq.h>
9#include <utils/logging.h>
10
11// This is an interim hacky solution to introduce another kind of RunDataHandler
12#include "QNEthernet.h"
13#include "net/ethernet.h"
14
15#include <mode/mode.h>
16#include <mode/teensy/mode.h>
17#include <protocol/protocol_oob.h>
18#include <run/run.h>
19
20namespace run {
21
23
24FASTRUN run::Result run_flexio_raw(carrier::Carrier &carrier_, Run &run) {
25 auto state_change_handler = run.state_change_handler.get();
26 auto run_data_handler = run.data_handler.get();
27
28 run.daq_config.num_channels = carrier_.get_active_adc_channel_range();
29
30 if (!run_data_handler) {
31 return Result::err("Can not start run without RunDataHandler.");
32 }
33
35 auto on_overload = run.config.halt_on_overload
36 ? mode::OnOverload::HALT
37 : mode::OnOverload::IGNORE;
38
39 if (!mode::FlexIOControl::init(run.config.ic_time, run.config.op_time,
40 on_overload,
41 mode::OnExtHalt::IGNORE, run.sync_config)) {
42 return Result::err("Error while initializing state machine");
43 }
44
45 // Start a data stream if data acquisition is active
46 auto data_stream = daq::stream::get(run, run_data_handler, false);
47 if (run.daq_config) {
48 auto success = data_stream.start();
49 if (!success) {
50 return Result::err_fmt("Error starting data stream: %s", success.msg.c_str());
51 }
52 }
53
54 // Start run immediately or wait for SYNC signal
55 state_change_handler->handle(run.to(RunState::TAKE_OFF, millis()), run);
56 if (!run.sync_config.enabled) {
58 }else {
59 if (run.sync_config.is_master) {
60 // wait for others beeing ready
61 delay(100);
62 // Generate the SYNC signal ourselves
63 // This will be received by us and will be broadcast to other carriers
64 if (!carrier_.ctrl_block->send_sync(run.sync_config.id)) {
65 return Result::err("Error sending SYNC as master.");
66 }
67 }
68
69 elapsedMillis since_takeoff;
71 if (since_takeoff > 5000) {
72 return Result::err("Timeout while waiting for SYNC signal.");
73 }
74 }
75 }
76
77 Result result = Result::ok({});
79 result = data_stream.process();
80 if (result.is_err()) break;
81 }
83
84 // When a data sample must be gathered very close to the end of OP duration,
85 // it takes a few microseconds for it to end up in the DMA buffer.
86 // This is hard to check for, since the DMA active flag is only set once the DMA
87 // is triggered by the last CLK pulse.
88 // Easiest solution is to wait for it.
89 delayMicroseconds(20);
90 // Stream out remaining partially filled buffer
91 if (result.is_ok())
92 result = data_stream.process(true);
93
94 // Explicitly stop data_stream, even though going out of scope should do it
95 if (!data_stream.stop())
96 result = Result::err("Error while stopping data stream.");
97
98 // Capture all signals on carrier when requested
99 if (run.daq_config.sample_op_end) {
100 std::array<std::array<float, 8>, 6> data_op_end;
101 if (carrier_.measure_all_signals(data_op_end)) {
102 run_data_handler->handle_op_end(run, data_op_end);
103 }else {
104 result = Result::err("Error while measuring OP_END data.");
105 }
106 }
107
108 auto actual_op_time = mode::FlexIOControl::get_actual_op_time();
109
110 auto &perf = mode::PerformanceCounter::get();
111 perf.add(mode::Mode::IC, run.config.ic_time / 1000);
112 perf.add(mode::Mode::OP, actual_op_time / 1000);
113 perf.increase_run();
114
115 if (result.is_err())
116 return result;
117
118 // DONE
119 auto change = run.to(RunState::DONE, actual_op_time);
120 state_change_handler->handle(change, run);
121
122 return result;
123}
124
125FASTRUN void run_flexio(carrier::Carrier &carrier_, Run &run) {
126 auto state_change_handler = run.state_change_handler.get();
127
128 if (!state_change_handler) {
129 LOG_ERROR("Can not start run without RunStateChangeHandler");
130 return;
131 }
132
133 auto result = run_flexio_raw(carrier_, run);
134 if (auto msg = result.if_err()) {
135 auto change = run.to(RunState::ERROR, millis());
136 LOG_ERROR(msg->c_str());
137 state_change_handler->handle(change, run, msg->c_str());
138 }
139}
140
141void Run::run(carrier::Carrier &carrier_) {
142 run_flexio(carrier_, *this);
143}
144
145} // namespace run
static void to_end()
Definition mode.cpp:396
static bool is_idle()
Definition mode.cpp:463
static unsigned long long get_actual_op_time()
Definition mode.cpp:458
static bool is_done()
Definition mode.cpp:473
static void reset()
Definition mode.cpp:402
static void force_start()
Definition mode.cpp:370
static bool init(unsigned long long ic_time_ns, unsigned long long op_time_ns, mode::OnOverload on_overload=mode::OnOverload::HALT, mode::OnExtHalt on_ext_halt=mode::OnExtHalt::IGNORE, SyncConfig sync_config={})
Definition mode.cpp:95
static constexpr int success
Definition flasher.cpp:275
::Result< std::monostate, std::string > Result
FASTRUN run::Result run_flexio_raw(carrier::Carrier &carrier_, Run &run)
FASTRUN void run_flexio(carrier::Carrier &carrier_, Run &run)