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
22using FlexioResult = Result<unsigned long long>;
23
24FASTRUN FlexioResult run_flexio_raw(carrier::Carrier &carrier_, Run &run) {
25 auto run_data_handler = run.data_handler.get();
26
27 run.daq_config.num_channels = carrier_.get_active_adc_channel_range();
28
29 if (!run_data_handler) {
30 return UnitResult::err("Can not start run without RunDataHandler.");
31 }
32
34 auto on_overload = run.config.halt_on_overload
35 ? mode::OnOverload::HALT
36 : mode::OnOverload::IGNORE;
37
38 if (!mode::FlexIOControl::init(run.config.ic_time, run.config.op_time,
39 on_overload,
40 mode::OnExtHalt::IGNORE, run.sync_config)) {
41 return UnitResult::err("Error while initializing state machine");
42 }
43
44 // Start a data stream if data acquisition is active
45 auto data_stream = daq::stream::get(run, run_data_handler, false);
46 if (run.daq_config) {
47 auto success = data_stream.start();
48 if (!success) {
49 return UnitResult::err_fmt("Error starting data stream: %s", success.err_value().c_str());
50 }
51 }
52
53 // Start run immediately or wait for SYNC signal
54 run_data_handler->handle(run.to(RunState::TAKE_OFF, millis()), run);
55 if (!run.sync_config.enabled) {
57 }else {
58 if (run.sync_config.is_master) {
59 // wait for others beeing ready
60 delay(500);
61 // Generate the SYNC signal ourselves
62 // This will be received by us and will be broadcast to other carriers
63 if (!carrier_.ctrl_block->send_sync(run.sync_config.id)) {
64 return UnitResult::err("Error sending SYNC as master.");
65 }
66 }
67
68 elapsedMillis since_takeoff;
70 if (since_takeoff > 5000) {
71 return UnitResult::err("Timeout while waiting for SYNC signal.");
72 }
73 }
74 }
75
76 UnitResult result = UnitResult::ok();
78 result = data_stream.process();
79 if (result.is_err()) break;
80 }
82
83 // When a data sample must be gathered very close to the end of OP duration,
84 // it takes a few microseconds for it to end up in the DMA buffer.
85 // This is hard to check for, since the DMA active flag is only set once the DMA
86 // is triggered by the last CLK pulse.
87 // Easiest solution is to wait for it.
88 delayMicroseconds(20);
89 // Stream out remaining partially filled buffer
90 if (result.is_ok())
91 result <<= data_stream.process(true);
92
93 // Explicitly stop data_stream, even though going out of scope should do it
94 if (!data_stream.stop())
95 result <<= UnitResult::err("Error while stopping data stream.");
96
97 // Capture all signals on carrier when requested
98 if (run.daq_config.sample_op_end) {
99 std::array<std::array<float, 8>, 6> data_op_end;
100 if (carrier_.measure_all_signals(data_op_end)) {
101 run_data_handler->handle_op_end(run, data_op_end);
102 }else {
103 result <<= UnitResult::err("Error while measuring OP_END data.");
104 }
105 }
106
107 auto actual_op_time = mode::FlexIOControl::get_actual_op_time();
108
109 auto &perf = mode::PerformanceCounter::get();
110 perf.add(mode::Mode::IC, run.config.ic_time / 1000);
111 perf.add(mode::Mode::OP, actual_op_time / 1000);
112 perf.increase_run();
113
114 if (result.is_err())
115 return result;
116 return FlexioResult::ok(actual_op_time);
117}
118
119FASTRUN void run_flexio(carrier::Carrier &carrier_, Run &run) {
120 auto data_handler = run.data_handler.get();
121
122 if (!data_handler) {
123 LOG_ERROR("Can not start run without RunDataHandler");
124 return;
125 }
126
127 auto result = run_flexio_raw(carrier_, run);
128
129 if (auto msg = result.as_err()) {
130 auto change = run.to(RunState::ERROR, millis());
131 LOG_ERROR(msg->c_str());
132 data_handler->handle(change, run, msg->c_str());
133 }else {
134 auto change = run.to(RunState::DONE, result.ok_value());
135 data_handler->handle(change, run);
136 }
137}
138
139void Run::run(carrier::Carrier &carrier_) {
140 run_flexio(carrier_, *this);
141}
142
143} // 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< unsigned long long > FlexioResult
FASTRUN FlexioResult run_flexio_raw(carrier::Carrier &carrier_, Run &run)
FASTRUN void run_flexio(carrier::Carrier &carrier_, Run &run)