K2: SubstrateIDStatus (third E90 axis)
Adds the substrate-ID verification FSM that E90 §6.4.6 calls for: NotConfirmed initial; equipment hasn't read the ID yet WaitingForHost ID has been read; awaiting host accept/reject Confirmed host confirmed (or force-bound) Mismatched host rejected — recoverable via Bind Events: Read NotConfirmed -> WaitingForHost Confirm WaitingForHost -> Confirmed Mismatch WaitingForHost -> Mismatched Bind any -> Confirmed (force-bind) Reset any -> NotConfirmed Wire-byte values pinned via static_assert. The third axis is now exposed on SubstrateStateMachine alongside location_state() and processing_state(); set_id_handler() observes transitions. Existing two-axis API is unchanged. 4 new test cases cover the happy path, Mismatch+Bind recovery, Reset from any state, and same-state event handler suppression. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -68,13 +68,38 @@ enum class SubstrateProcessingEvent {
|
||||
|
||||
const char* substrate_processing_event_name(SubstrateProcessingEvent e);
|
||||
|
||||
// Substrate ID Status (E90 §6.4.6) — the third independent axis.
|
||||
// Captures whether the equipment has read & confirmed the wafer's ID.
|
||||
enum class SubstrateIDStatus : uint8_t {
|
||||
NotConfirmed = 0,
|
||||
WaitingForHost = 1, // ID read; awaiting host confirmation
|
||||
Confirmed = 2,
|
||||
Mismatched = 3,
|
||||
NoState = 255,
|
||||
};
|
||||
|
||||
const char* substrate_id_status_name(SubstrateIDStatus s);
|
||||
|
||||
enum class SubstrateIDEvent {
|
||||
Read, // NotConfirmed -> WaitingForHost (equipment scanned ID)
|
||||
Confirm, // WaitingForHost -> Confirmed (host accepted)
|
||||
Mismatch, // WaitingForHost -> Mismatched (host rejected)
|
||||
Bind, // any -> Confirmed (host force-bind)
|
||||
Reset, // any -> NotConfirmed
|
||||
};
|
||||
|
||||
const char* substrate_id_event_name(SubstrateIDEvent e);
|
||||
|
||||
using SubstrateTable =
|
||||
CarrierTransitionTable<SubstrateState, SubstrateEvent>;
|
||||
using SubstrateProcessingTable =
|
||||
CarrierTransitionTable<SubstrateProcessingState, SubstrateProcessingEvent>;
|
||||
using SubstrateIDTable =
|
||||
CarrierTransitionTable<SubstrateIDStatus, SubstrateIDEvent>;
|
||||
|
||||
SubstrateTable default_substrate_table();
|
||||
SubstrateProcessingTable default_substrate_processing_table();
|
||||
SubstrateIDTable default_substrate_id_table();
|
||||
|
||||
class SubstrateStateMachine {
|
||||
public:
|
||||
@@ -84,25 +109,34 @@ class SubstrateStateMachine {
|
||||
std::function<void(SubstrateProcessingState from,
|
||||
SubstrateProcessingState to,
|
||||
SubstrateProcessingEvent)>;
|
||||
using IDChangeHandler =
|
||||
std::function<void(SubstrateIDStatus from, SubstrateIDStatus to,
|
||||
SubstrateIDEvent)>;
|
||||
|
||||
SubstrateStateMachine();
|
||||
|
||||
SubstrateState location_state() const { return loc_; }
|
||||
SubstrateProcessingState processing_state() const { return proc_; }
|
||||
SubstrateIDStatus id_state() const { return id_; }
|
||||
|
||||
void set_location_handler(LocationChangeHandler h) { on_loc_ = std::move(h); }
|
||||
void set_processing_handler(ProcessingChangeHandler h) { on_proc_ = std::move(h); }
|
||||
void set_id_handler(IDChangeHandler h) { on_id_ = std::move(h); }
|
||||
|
||||
bool on_location_event(SubstrateEvent e);
|
||||
bool on_processing_event(SubstrateProcessingEvent e);
|
||||
bool on_id_event(SubstrateIDEvent e);
|
||||
|
||||
private:
|
||||
SubstrateTable loc_table_;
|
||||
SubstrateProcessingTable proc_table_;
|
||||
SubstrateIDTable id_table_;
|
||||
SubstrateState loc_ = SubstrateState::AtSource;
|
||||
SubstrateProcessingState proc_ = SubstrateProcessingState::NeedsProcessing;
|
||||
SubstrateIDStatus id_ = SubstrateIDStatus::NotConfirmed;
|
||||
LocationChangeHandler on_loc_;
|
||||
ProcessingChangeHandler on_proc_;
|
||||
IDChangeHandler on_id_;
|
||||
};
|
||||
|
||||
} // namespace secsgem::gem
|
||||
|
||||
Reference in New Issue
Block a user