#pragma once #include #include #include #include #include "secsgem/gem/carrier_state.hpp" // shared CarrierTransition template // E87 §6 Load Port state models — three independent FSMs per port: // // LPTS LoadPortTransferState - is a carrier being moved on/off? // LRS LoadPortReservationStatus - host reservation // LAS LoadPortAssociationStatus - is a carrier associated? // // Wire-byte values match E87-0716 §10.3.5-7. namespace secsgem::gem { enum class LoadPortTransferState : uint8_t { OutOfService = 0, InService = 1, // ready, no carrier in motion Loading = 2, // carrier arriving Unloading = 3, // carrier leaving NoState = 255, }; const char* load_port_transfer_state_name(LoadPortTransferState s); enum class LoadPortTransferEvent { EnterService, // OutOfService -> InService LeaveService, // any -> OutOfService StartLoading, // InService -> Loading CompleteLoading, // Loading -> InService StartUnloading, // InService -> Unloading CompleteUnloading, // Unloading -> InService }; const char* load_port_transfer_event_name(LoadPortTransferEvent e); enum class LoadPortReservationStatus : uint8_t { NotReserved = 0, Reserved = 1, NoState = 255, }; const char* load_port_reservation_status_name(LoadPortReservationStatus s); enum class LoadPortReservationEvent { Reserve, // NotReserved -> Reserved Release, // Reserved -> NotReserved }; const char* load_port_reservation_event_name(LoadPortReservationEvent e); enum class LoadPortAssociationStatus : uint8_t { NotAssociated = 0, Associated = 1, NoState = 255, }; const char* load_port_association_status_name(LoadPortAssociationStatus s); enum class LoadPortAssociationEvent { Associate, // NotAssociated -> Associated Disassociate, // Associated -> NotAssociated }; const char* load_port_association_event_name(LoadPortAssociationEvent e); using LoadPortTransferTable = CarrierTransitionTable; using LoadPortReservationTable = CarrierTransitionTable; using LoadPortAssociationTable = CarrierTransitionTable; LoadPortTransferTable default_load_port_transfer_table(); LoadPortReservationTable default_load_port_reservation_table(); LoadPortAssociationTable default_load_port_association_table(); class LoadPortStateMachine { public: using TransferChangeHandler = std::function; using ReservationChangeHandler = std::function; using AssociationChangeHandler = std::function; LoadPortStateMachine(); LoadPortTransferState transfer_state() const { return tx_state_; } LoadPortReservationStatus reservation_state() const { return rs_state_; } LoadPortAssociationStatus association_state() const { return as_state_; } void set_transfer_handler(TransferChangeHandler h) { on_tx_ = std::move(h); } void set_reservation_handler(ReservationChangeHandler h) { on_rs_ = std::move(h); } void set_association_handler(AssociationChangeHandler h) { on_as_ = std::move(h); } bool on_transfer_event(LoadPortTransferEvent e); bool on_reservation_event(LoadPortReservationEvent e); bool on_association_event(LoadPortAssociationEvent e); private: LoadPortTransferTable tx_table_; LoadPortReservationTable rs_table_; LoadPortAssociationTable as_table_; LoadPortTransferState tx_state_ = LoadPortTransferState::InService; LoadPortReservationStatus rs_state_ = LoadPortReservationStatus::NotReserved; LoadPortAssociationStatus as_state_ = LoadPortAssociationStatus::NotAssociated; TransferChangeHandler on_tx_; ReservationChangeHandler on_rs_; AssociationChangeHandler on_as_; }; } // namespace secsgem::gem