e1608: do not fight a hardware trigger, stop the scan on a failed connect, daemon drop timer in the mock
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
3093568d11
commit
6245811699
5 files changed
+24
-4
No files matched your search
@@ -137,7 +137,8 @@ whether the handshake may answer status 2 ("code ignored"; one reference accepts
|
||||
source accepts it); the first frame id; and the maximum frame size. Two further things
|
||||
are worth a look on a board even though the mock's header does not flag them: the calibration memory layout and
|
||||
its coefficient type, and the status word's bits, in particular whether the "scan running" bit stays set while the
|
||||
board waits for a trigger (the source restarts a scan that reads as stopped when auto-restart is on). The DIFF input
|
||||
board waits for a trigger (with auto-restart on, the source restarts a scan that reads as stopped only when no
|
||||
trigger is configured, so as not to reset the wait for the edge; this is unverified on hardware). The DIFF input
|
||||
numbering (channel + 8) and the filler byte after scan start are agreed by both references. The scan overrun count
|
||||
is approximate: the board does not say how many scans it dropped, so the frame after a restart reports one lost.
|
||||
Errors (no device, a rejected connection code, a timeout, the scan socket closing) are written to stderr as
|
||||
|
||||
@@ -48,7 +48,7 @@ What feeds `Acquisition` is a `DataSource`, one of the registered *kinds*.
|
||||
`e1608_source` is the `DataSource`; `e1608_kind` and `e1608_panels` are the UI. A change to the wire
|
||||
never reaches the UI files.
|
||||
- The E-1608 source runs **everything inside `poll()`** on the producer thread: posted commands, the
|
||||
connect state machine (Down, Scanning, Halted), the scan read, the 500 ms status check, the digital
|
||||
connect state machine (Down, Scanning, Halted), the scan read, the 500 ms status check (its not-running restart is skipped when a hardware trigger is configured), the digital
|
||||
input/counter poll and the 20 ms waveform tick. There is no second thread. A connect attempt (discovery,
|
||||
handshake, calibration read, scan start) can block `poll()` for as long as the command timeout allows each
|
||||
step; that delays only the command queue. Every exception is caught inside `poll()`: an escape would end
|
||||
|
||||
@@ -186,6 +186,7 @@ void E1608Source::open(SourceSink& sink) {
|
||||
|
||||
void E1608Source::close() {
|
||||
if (state_ == State::Scanning) dev_.scan_stop();
|
||||
scan_started_ = false;
|
||||
link_.close();
|
||||
connected_.store(false, std::memory_order_relaxed);
|
||||
}
|
||||
@@ -212,6 +213,15 @@ void E1608Source::note(const std::string& msg) {
|
||||
}
|
||||
|
||||
void E1608Source::fail(const std::string& msg, bool fatal) {
|
||||
if (scan_started_) {
|
||||
// The scan may have started before a later connect step failed: tell the board to stop, so it
|
||||
// is not left scanning with nobody reading. Best effort; it must never throw out of here.
|
||||
try {
|
||||
dev_.scan_stop();
|
||||
} catch (...) {
|
||||
}
|
||||
scan_started_ = false;
|
||||
}
|
||||
link_.close();
|
||||
const bool was_up = connected_.exchange(false, std::memory_order_relaxed);
|
||||
note(msg);
|
||||
@@ -283,6 +293,7 @@ void E1608Source::connect_and_start() {
|
||||
}
|
||||
|
||||
link_.connect(host, cfg_.port, cfg_.code, cfg_.timeout_ms);
|
||||
scan_started_ = false;
|
||||
cal_ = Calibration{};
|
||||
if (cfg_.calibrate && !dev_.read_calibration(cal_))
|
||||
note("calibration memory refused; using nominal values");
|
||||
@@ -419,13 +430,16 @@ void E1608Source::check_status() {
|
||||
sink_->on_event(SourceEvent::Error, "scan overrun; restarting");
|
||||
restart_scan();
|
||||
pending_lost_ = 1;
|
||||
} else if (!(st & 2) && cfg_.auto_restart) {
|
||||
} else if (!(st & 2) && cfg_.auto_restart && cfg_.trigger == Trigger::None) {
|
||||
// With a hardware trigger the board may report "not running" while it waits for the edge;
|
||||
// restarting then would reset the wait forever, so only the overrun bit restarts the scan.
|
||||
restart_scan();
|
||||
}
|
||||
}
|
||||
|
||||
void E1608Source::restart_scan() {
|
||||
dev_.scan_stop();
|
||||
scan_started_ = false;
|
||||
pending_.clear();
|
||||
for (auto& r : ready_) r.clear();
|
||||
start_scan();
|
||||
@@ -437,6 +451,7 @@ void E1608Source::start_scan() {
|
||||
throw LinkError(LinkError::Kind::Command, "the aggregate rate exceeds 250 kS/s");
|
||||
try {
|
||||
dev_.scan_start(queue_, cfg_.aggregate(), cfg_.ext_clock, cfg_.trigger);
|
||||
scan_started_ = true;
|
||||
} catch (...) {
|
||||
// The board may have accepted the start (0x11) before a later step failed (the filler byte):
|
||||
// tell it to stop, so it is not left scanning with nobody reading.
|
||||
@@ -444,6 +459,7 @@ void E1608Source::start_scan() {
|
||||
dev_.scan_stop();
|
||||
} catch (...) {
|
||||
}
|
||||
scan_started_ = false;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ class E1608Source final : public DataSource {
|
||||
E1608Settings cfg_;
|
||||
SourceSink* sink_ = nullptr;
|
||||
State state_ = State::Down;
|
||||
bool scan_started_ = false; ///< a scan start succeeded and no stop has followed
|
||||
Link link_;
|
||||
Device dev_{link_};
|
||||
Calibration cal_;
|
||||
|
||||
+3
-1
@@ -327,7 +327,9 @@ class Board:
|
||||
self.first_conn = time.monotonic()
|
||||
close_quietly(old)
|
||||
if first and self.args.drop_after > 0:
|
||||
threading.Timer(self.args.drop_after, self.drop).start()
|
||||
timer = threading.Timer(self.args.drop_after, self.drop)
|
||||
timer.daemon = True
|
||||
timer.start()
|
||||
try:
|
||||
while True:
|
||||
b = conn.recv(1)
|
||||
|
||||
Reference in new issue
Block a user