DUTs

DUT_SATT_Filter

TYPE DUT_SATT_Filter :
STRUCT
    {attribute 'pytmc' := '
        pv: MATERIAL
        io: input
        field: DESC Filter material name
    '}
    sFilterMaterial : STRING;

    {attribute 'pytmc' := '
        pv: THICKNESS
        io: input
        field: DESC Filter material thickness
        field: EGU um
    '}
    fFilterThickness_um : LREAL;

    {attribute 'pytmc' := '
        pv: TRANSMISSION
        io: input
        field: DESC Current transmission value
    '}
    fTransmission : LREAL;

END_STRUCT
END_TYPE
Related:

E_PositionState

TYPE E_PositionState :
(
RETRACTED    := 0,
INSERTED    := 1,
MOVING    := 2,
INVALID :=3
);
END_TYPE

ST_MPA

TYPE ST_MPA :
STRUCT
//    i_xInsertLS AT %I*: BOOL;
//    i_xRetractLS AT %I*: BOOL;
//    _xInsertSW : BOOL;
//    _xRetractSW : BOOL;
//    q_xInsertDO AT %Q*: BOOL;
//    q_xRetractDO AT %Q*: BOOL;
//    eState : DUT_PneumaticActuator_Position;

    //Readbacks
    {attribute 'pytmc' := '
    pv: IN
    io: i
    '}
    i_bInLS    :    BOOL;
    {attribute 'pytmc' := '
    pv: OUT
    io: i
    '}
    i_bOutLS    :    BOOL;

    //Controls
    {attribute 'pytmc' := '
    pv: INSERT_DO
    io: i
    '}
    q_bRetract    :    BOOL;
    {attribute 'pytmc' := '
    pv: RETRACT_DO
    io: i
    '}
    q_bInsert    :    BOOL;

    //Logic and supervisory
    {attribute 'pytmc' := '
    pv: ILKOK
    io: i
    '}
    bILK_OK: BOOL;
    {attribute 'pytmc' := '
    pv: INSERT_OK
    io: i
    '}
    bInsertOK    :    BOOL;
    {attribute 'pytmc' := '
    pv: RETRACT_OK
    io: i
    '}
    bRetractOK    :    BOOL;
    {attribute 'pytmc' := '
    pv: IN_CMD
    io: io
    '}

    bInsert_SW        :    BOOL;
    {attribute 'pytmc' := '
    pv: OUT_CMD
    io: io
    '}
    bRetract_SW    :    BOOL;
    {attribute 'pytmc' := '
    pv: ERROR
    io: io
    '}
    bErrorPresent : BOOL;
    {attribute 'pytmc' := '
    pv: POS_STATE
    type: mbbi
    field: ZRST RETRACTED
    field: ONST INSERTED
    field: TWST MOVING
    field: THST INVALID
    io: i
    '}

    eState    :    E_PositionState := INVALID;


END_STRUCT
END_TYPE
Related:

GVLs

Global_Version

{attribute 'TcGenerated'}
{attribute 'no-analysis'}
{attribute 'linkalways'}
// This function has been automatically generated from the project information.
VAR_GLOBAL CONSTANT
    {attribute 'const_non_replaced'}
    stLibVersion_lcls_plc_lfe_motion : ST_LibVersion := (iMajor := 2, iMinor := 2, iBuild := 0, iRevision := 0, nFlags := 1, sVersion := '2.2.0');
END_VAR

GVL

{attribute 'qualified_only'}
VAR_GLOBAL
    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:ARB'}
    fbArbiter: FB_Arbiter(1);

    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:FFO:01'}
    {attribute 'TcLinkTo' := '.q_xFastFaultOut:=TIIB[PMPS_FFO]^Channel 1^Output'}
    fbFastFaultOutput1: FB_HardwareFFOutput := (bAutoReset := TRUE, i_sNetID := '172.21.88.66.1.1');

    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:FFO:02'}
    {attribute 'TcLinkTo' := '.q_xFastFaultOut:=TIIB[PMPS_FFO]^Channel 2^Output'}
    fbFastFaultOutput2: FB_HardwareFFOutput := (bAutoReset := TRUE, i_sNetID := '172.21.88.66.1.1');

    bInitIM1L0: BOOL;
    bInitIM1L1: BOOL;
    bInitIM2L0: BOOL;
    bInitIM3L0: BOOL;
    bInitIM4L0: BOOL;

    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:PMPS:ReqTrans'}
    rReqTrans AT %I*                : ARRAY [1..PMPS_GVL.AUX_ATTENUATORS] OF ST_PMPS_Attenuator_IO;
    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:PMPS:CurTrans'}
    rCurTrans AT %Q*                : ARRAY [1..PMPS_GVL.AUX_ATTENUATORS] OF ST_PMPS_Attenuator_IO;

END_VAR

Main

{attribute 'qualified_only'}
VAR_GLOBAL
(*
    Only includes motor definitions for the IOC
    These are hard-coded to be Main.M#,
    but are very convenient to store in a GVL,
    hence the confusing namespace here

    This should be refactored once the IOC
    supports arbitrary ads paths for motors
*)
    // AT2L0-SOLID: 19 Axes
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:01'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-01]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-01]^STM Status^Status^Digital input 1
    '}
    M1: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:01');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:02'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-02]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-02]^STM Status^Status^Digital input 1
    '}
    M2: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:02');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:03'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-03]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-03]^STM Status^Status^Digital input 1
    '}
    M3: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:03');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:04'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-04]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-04]^STM Status^Status^Digital input 1
    '}
    M4: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:04');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:05'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-05]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-05]^STM Status^Status^Digital input 1
    '}
    M5: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:05');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:06'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-06]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-06]^STM Status^Status^Digital input 1
    '}
    M6: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:06');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:07'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-07]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-07]^STM Status^Status^Digital input 1
    '}
    M7: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:07');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:08'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-08]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-08]^STM Status^Status^Digital input 1
    '}
    M8: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:08');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:09'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-09]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-09]^STM Status^Status^Digital input 1
    '}
    M9: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:09');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:10'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-10]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-10]^STM Status^Status^Digital input 1
    '}
    M10: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:10');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:11'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-11]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-11]^STM Status^Status^Digital input 1
    '}
    M11: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:11');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:12'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-12]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-12]^STM Status^Status^Digital input 1
    '}
    M12: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:12');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:13'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-13]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-13]^STM Status^Status^Digital input 1
    '}
    M13: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:13');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:14'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-14]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-14]^STM Status^Status^Digital input 1
    '}
    M14: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:14');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:15'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-15]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-15]^STM Status^Status^Digital input 1
    '}
    M15: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:15');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:16'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-16]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-16]^STM Status^Status^Digital input 1
    '}
    M16: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:16');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:17'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-17]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-17]^STM Status^Status^Digital input 1
    '}
    M17: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:17');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:18'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-18]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-18]^STM Status^Status^Digital input 1
    '}
    M18: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:18');
    {attribute 'pytmc' := 'pv: AT2L0:XTES:MMS:19'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AT2L0-EL7041-19]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[AT2L0-EL7041-19]^STM Status^Status^Digital input 1
    '}
    M19: DUT_MotionStage := (sName := 'AT2L0:XTES:MMS:19');

    // IM1L0-XTES: 3 Axes
    {attribute 'pytmc' := 'pv: IM1L0:XTES:MMS'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[IM1L0-EL7041]^STM Status^Status^Digital input 1;
                              .bBrakeRelease        := TIIB[IM1L0-EL2004]^Channel 1^Output'}
    M20: DUT_MotionStage := (sName := 'IM1L0:XTES:MMS');
    {attribute 'pytmc' := 'pv: IM1L0:XTES:CLZ'}
    {attribute 'TcLinkTo' := '.bHome := TIIB[IM1L0-EL1088]^Channel 2^Input'}
    M21: DUT_MotionStage := (sName := 'IM1L0:XTES:CLZ');
    {attribute 'pytmc' := 'pv: IM1L0:XTES:CLF'}
    {attribute 'TcLinkTo' := '.bHome := TIIB[IM1L0-EL1088]^Channel 4^Input'}
    M22: DUT_MotionStage := (sName := 'IM1L0:XTES:CLF');

    // IM1L1-PPM: 1 Axis
    {attribute 'pytmc' := 'pv: IM1L1:PPM:MMS'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[IM1L1-EL7041]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[IM1L1-EL7041]^STM Status^Status^Digital input 2;
                              .bBrakeRelease        := TIIB[IM1L1-EL2004]^Channel 1^Output'}
    M23: DUT_MotionStage := (sName := 'IM1L1:PPM:MMS');

    // IM2L0-XTES: 3 Axes
    {attribute 'pytmc' := 'pv: IM2L0:XTES:MMS'}
    {attribute 'TcLinkTo' := '.bBrakeRelease        := TIIB[IM2L0-EL2004]^Channel 1^Output'}
    M24: DUT_MotionStage := (sName := 'IM2L0:XTES:MMS');
    {attribute 'pytmc' := 'pv: IM2L0:XTES:CLZ'}
    {attribute 'TcLinkTo' := '.bHome := TIIB[IM2L0-EL1088]^Channel 2^Input'}
    M25: DUT_MotionStage := (sName := 'IM2L0:XTES:CLZ');
    {attribute 'pytmc' := 'pv: IM2L0:XTES:CLF'}
    {attribute 'TcLinkTo' := '.bHome := TIIB[IM2L0-EL1088]^Channel 4^Input'}
    M26: DUT_MotionStage := (sName := 'IM2L0:XTES:CLF');

    // IM3L0-PPM: 1 Axes
    {attribute 'pytmc' := 'pv: IM3L0:PPM:MMS'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[IM3L0-EL7041]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[IM3L0-EL7041]^STM Status^Status^Digital input 2;
                              .bBrakeRelease        := TIIB[IM3L0-EL2004]^Channel 1^Output'}
    M27: DUT_MotionStage := (sName := 'IM3L0:PPM:MMS');

    // IM4L0-XTES: 3 Axes
    {attribute 'pytmc' := 'pv: IM4L0:XTES:MMS'}

    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[IM4L0-EL7041]^STM Status^Status^Digital input 1;
                              .bBrakeRelease        := TIIB[IM4L0-EL2004]^Channel 1^Output'}
    M28: DUT_MotionStage := (sName := 'IM4L0:XTES:MMS');
    {attribute 'pytmc' := 'pv: IM4L0:XTES:CLZ'}
    {attribute 'TcLinkTo' := '.bHome := TIIB[IM4L0-EL1088]^Channel 2^Input'}
    M29: DUT_MotionStage := (sName := 'IM4L0:XTES:CLZ');
    {attribute 'pytmc' := 'pv: IM4L0:XTES:CLF'}
    {attribute 'TcLinkTo' := '.bHome := TIIB[IM4L0-EL1088]^Channel 4^Input'}
    M30: DUT_MotionStage := (sName := 'IM4L0:XTES:CLF');

    // PF1L0-WFS: 2 Axes
    {attribute 'pytmc' := 'pv: PF1L0:WFS:MMS:Y'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[PF1L0-EL7041-01]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[PF1L0-EL7041-01]^STM Status^Status^Digital input 2;
                              .bBrakeRelease        := TIIB[PF1L0-EL2004]^Channel 1^Output;
                              .nRawEncoderULINT     := TIIB[PF1L0-EL5042]^FB Inputs Channel 2^Position'}
    M31: DUT_MotionStage := (sName := 'PF1L0:WFS:MMS:01');
    {attribute 'pytmc' := 'pv: PF1L0:WFS:MMS:Z'}
    {attribute 'TcLinkTo' := '.nRawEncoderULINT     := TIIB[PF1L0-EL5042]^FB Inputs Channel 1^Position'}
    M32: DUT_MotionStage := (sName := 'PF1L0:WFS:MMS:02');

    // RTDSL0: 8 Axes
    {attribute 'pytmc' := 'pv: RTDSL0:DIODE:MMS:01'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[RTDSL0-EL7041-01]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[RTDSL0-EL7041-01]^STM Status^Status^Digital input 2'}
    M33: DUT_MotionStage := (sName := 'RTDSL0:DIODE:MMS:01');
    M34: DUT_MotionStage;
    M35: DUT_MotionStage;
    M36: DUT_MotionStage;
    M37: DUT_MotionStage;
    //to be uncommented when the mccallister stage on RTDSK0 is moved to RTDSLo
    (*
    {attribute 'pytmc' := 'pv: RTDSL0:SCRP:MMS:01'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[RTDSL0-EL7041-02]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[RTDSL0-EL7041-02]^STM Status^Status^Digital input 2'}
    M34: DUT_MotionStage := (sName := 'RTDSL0:SCRP:MMS:01');
    {attribute 'pytmc' := 'pv: RTDSL0:SCRP:MMS:02'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[RTDSL0-EL7041-03]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[RTDSL0-EL7041-03]^STM Status^Status^Digital input 2'}
    M35: DUT_MotionStage := (sName := 'RTDSL0:SCRP:MMS:02');
    {attribute 'pytmc' := 'pv: RTDSL0:SCRP:MMS:03'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[RTDSL0-EL7041-04]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[RTDSL0-EL7041-04]^STM Status^Status^Digital input 2'}
    M36: DUT_MotionStage := (sName := 'RTDSL0:SCRP:MMS:03');
    *)
    //LDM on RTDSL0
    {attribute 'pytmc' := 'pv: RTDSL0:LDM:MMS:01'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[RTDSL0-EL7041-05]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[RTDSL0-EL7041-05]^STM Status^Status^Digital input 2;
                               .nRawEncoderINT := TIIB[Term 113 (EL3054)]^AI Standard Channel 1^Value'}
    //M37: DUT_MotionStage := (sName := 'RTDSL0:LDM:MMS:01');
    M38: DUT_MotionStage;
    M39: DUT_MotionStage;
    M40: DUT_MotionStage;

    // to be uncommented when mccallister stage is moved from RTDSK0 -> RTDSL0
    (*
    {attribute 'pytmc' := 'pv: RTDSL0:SCRP:LED:01'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[RTDSK0-EL7041-04]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[RTDSK0-EL7041-04]^STM Status^Status^Digital input 2'}
    LED1: ENUM_XPIM_States;
    *)


    // SL1L0-POWER: 4 Axes
    {attribute 'pytmc' := 'pv: SL1L0:POWER:MMS:BOTTOM'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL1L0-EL7041-E1]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[SL1L0-EL7041-E1]^STM Status^Status^Digital input 1'}
    M41: DUT_MotionStage := (sName := 'SL1L0:POWER:MMS:BOTTOM');
        {attribute 'pytmc' := 'pv: SL1L0:POWER:MMS:SOUTH'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL1L0-EL7041-E3]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[SL1L0-EL7041-E3]^STM Status^Status^Digital input 2'}
    M42: DUT_MotionStage := (sName := 'SL1L0:POWER:MMS:SOUTH');
    {attribute 'pytmc' := 'pv: SL1L0:POWER:MMS:TOP'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL1L0-EL7041-E5]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[SL1L0-EL7041-E5]^STM Status^Status^Digital input 1'}
    M43: DUT_MotionStage := (sName := 'SL1L0:POWER:MMS:TOP');
    {attribute 'pytmc' := 'pv: SL1L0:POWER:MMS:NORTH'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL1L0-EL7041-E7]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[SL1L0-EL7041-E7]^STM Status^Status^Digital input 2'}
    M44: DUT_MotionStage := (sName := 'SL1L0:POWER:MMS:NORTH');

    // SL2L0-POWER: 4 Axes
    {attribute 'pytmc' := 'pv: SL2L0:POWER:MMS:BOTTOM'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL2L0-EL7041-E1]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[SL2L0-EL7041-E1]^STM Status^Status^Digital input 1'}
    M45: DUT_MotionStage := (sName := 'SL2L0:POWER:MMS:BOTTOM');
    {attribute 'pytmc' := 'pv: SL2L0:POWER:MMS:SOUTH'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL2L0-EL7041-E3]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[SL2L0-EL7041-E3]^STM Status^Status^Digital input 2'}
    M46: DUT_MotionStage := (sName := 'SL2L0:POWER:MMS:SOUTH');
    {attribute 'pytmc' := 'pv: SL2L0:POWER:MMS:TOP'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL2L0-EL7041-E5]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[SL2L0-EL7041-E5]^STM Status^Status^Digital input 1'}
    M47: DUT_MotionStage := (sName := 'SL2L0:POWER:MMS:TOP');
    {attribute 'pytmc' := 'pv: SL2L0:POWER:MMS:NORTH'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL2L0-EL7041-E7]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[SL2L0-EL7041-E7]^STM Status^Status^Digital input 2'}
    M48: DUT_MotionStage := (sName := 'SL2L0:POWER:MMS:NORTH');

    // SP1L0-KMONO: 6 Axes
    {attribute 'pytmc' := 'pv: SP1L0:KMONO:MMS:XTAL_ANGLE'}
    M49: DUT_MotionStage := (sName := 'SP1L0:KMONO:MMS:XTAL_ANGLE');
    {attribute 'pytmc' := 'pv: SP1L0:KMONO:MMS:XTAL_VERT'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SP1L0-EL7041-E2-MOTORS]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[SP1L0-EL7041-E2-MOTORS]^STM Status^Status^Digital input 1'}
    M50: DUT_MotionStage := (sName := 'SP1L0:KMONO:MMS:XTAL_VERT');
    {attribute 'pytmc' := 'pv: SP1L0:KMONO:MMS:RET_HORIZ'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SP1L0-EL7041-E3-MOTORS]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[SP1L0-EL7041-E3-MOTORS]^STM Status^Status^Digital input 1'}
    M51: DUT_MotionStage := (sName := 'SP1L0:KMONO:MMS:RET_HORIZ');
    {attribute 'pytmc' := 'pv: SP1L0:KMONO:MMS:RET_VERT'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SP1L0-EL7041-E4-MOTORS]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[SP1L0-EL7041-E4-MOTORS]^STM Status^Status^Digital input 2'}
    M52: DUT_MotionStage := (sName := 'SP1L0:KMONO:MMS:RET_VERT');
    {attribute 'pytmc' := 'pv: SP1L0:KMONO:MMS:DIODE_HORIZ'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SP1L0-EL7041-E5-MOTORS]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[SP1L0-EL7041-E5-MOTORS]^STM Status^Status^Digital input 1'}
    M53: DUT_MotionStage := (sName := 'SP1L0:KMONO:MMS:DIODE_HORIZ');
    {attribute 'pytmc' := 'pv: SP1L0:KMONO:MMS:DIODE_VERT'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SP1L0-EL7041-E6-MOTORS]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[SP1L0-EL7041-E6-MOTORS]^STM Status^Status^Digital input 2'}
    M54: DUT_MotionStage := (sName := 'SP1L0:KMONO:MMS:DIODE_VERT');

        // Three_Stage_RTDSX0: 3 Axes
     (*   to uncomment when stage is moved to RTDSL0
    {attribute 'pytmc' := 'pv: RTDSX0:MMS:01'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SP1L0-EL7041-E2-MOTORS]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[SP1L0-EL7041-E2-MOTORS]^STM Status^Status^Digital input 1'}
    M55: DUT_MotionStage := (sName := 'RTDSX0:MMS:01');

     {attribute 'pytmc' := 'pv: RTDSX0:MMS:02'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SP1L0-EL7041-E2-MOTORS]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[SP1L0-EL7041-E2-MOTORS]^STM Status^Status^Digital input 1'}
    M56: DUT_MotionStage := (sName := 'RTDSX0:MMS:02');

    {attribute 'pytmc' := 'pv: RTDSX0:MMS:03'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SP1L0-EL7041-E2-MOTORS]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[SP1L0-EL7041-E2-MOTORS]^STM Status^Status^Digital input 1'}
    M57: DUT_MotionStage := (sName := 'RTDSX0:MMS:03');
    *)
END_VAR
Related:

RTDSL0

//{attribute 'qualified_only'}
VAR_GLOBAL
    {attribute 'pytmc' :=' pv: RTDSL0:MPA:01 '}
    RTDSL0_MPA_01: FB_MPA := (sName := 'RTDSL0:MPA:01');

    {attribute 'pytmc' :=' pv: RTDSL0:MPA:02 '}
    RTDSL0_MPA_02: FB_MPA := (sName := 'RTDSL0:MPA:02');

    {attribute 'pytmc' :=' pv: RTDSL0:MPA:03 '}
    RTDSL0_MPA_03: FB_MPA := (sName := 'RTDSL0:MPA:03');

    {attribute 'pytmc' :=' pv: RTDSL0:MPA:04 '}
    RTDSL0_MPA_04: FB_MPA := (sName := 'RTDSL0:MPA:04');


END_VAR
Related:

POUs

FB_AttenuatorElementDensity

FUNCTION_BLOCK FB_AttenuatorElementDensity
VAR_INPUT
    sName : STRING;
END_VAR
VAR_OUTPUT
    fDensity : LREAL;
    bFound : BOOL;
END_VAR
VAR
    fbElementDensity : FB_ElementDensity;
    fDensity_gm3 : LREAL;
END_VAR
IF sName = 'C' THEN
    (* Special-case diamond here *)
    fDensity := 3.51E6;  (* C (Diamond) g/m^3 *)
ELSE
    fbElementDensity(sName:=sName);
    IF fbElementDensity.bFound THEN
        fDensity := fbElementDensity.fValue * 1.0E6; (* g/cm^3 -> g/m^3 *)
    ELSE
        fDensity := 0.0;
    END_IF
END_IF

END_FUNCTION_BLOCK

FB_AttFFO

FUNCTION_BLOCK FB_AttFFO
VAR_IN_OUT
    stMotionStage: DUT_MotionStage;
    enumState: ENUM_EpicsInOut;
    fbFFHWO: FB_HardwareFFOutput;
END_VAR
VAR_OUTPUT
    bIsNotMoving: BOOL;
END_VAR
VAR
    fbFF: FB_FastFault := (i_Desc := 'Device is moving',
                           i_TypeCode := 16#2100,
                           i_xAutoReset := TRUE);
END_VAR
bIsNotMoving := NOT stMotionStage.Axis.Status.Moving;
fbFF(i_DevName := stMotionStage.sName,
     i_xOK := bIsNotMoving AND enumState <> ENUM_EpicsInOut.UNKNOWN,
     io_fbFFHWO := fbFFHWO);

END_FUNCTION_BLOCK

FB_BasicAxisFFO

FUNCTION_BLOCK FB_BasicAxisFFO
(*
    Placeholder FFO logic for no beam allowed, pre-comissioning

    Fast fault is applied if the axis is moving.
*)
VAR_IN_OUT
    Axis: AXIS_REF;
    fbFFHWO: FB_HardwareFFOutput;
END_VAR
VAR_INPUT
    sName: STRING;
END_VAR
VAR_OUTPUT
    bIsNotMoving: BOOL;
END_VAR
VAR
    fbFF: FB_FastFault := (i_Desc := 'Device is moving',
                           i_TypeCode := 16#2100,
                           i_xAutoReset := TRUE);
END_VAR
bIsNotMoving := NOT Axis.Status.Moving;
fbFF(i_DevName := sName,
     i_xOK := bIsNotMoving,
     io_fbFFHWO := fbFFHWO);

END_FUNCTION_BLOCK

FB_BasicMotionStageAltFFO

FUNCTION_BLOCK FB_BasicMotionStageAltFFO
(*
    Alternative to FB_BasicMotionStageFFO for an arbitrary out condition

    Sometimes the out limits is not what we want to use for proto-mps
*)
VAR_IN_OUT
    stMotionStage: DUT_MotionStage;
    fbFFHWO: FB_HardwareFFOutput;
END_VAR
VAR_INPUT
    sName: STRING;
    bFFOk: BOOL;
END_VAR
VAR_OUTPUT
    bIsOut: BOOL;
    bIsNotMoving: BOOL;
END_VAR
VAR
    fbBasicAxisFFO: FB_BasicAxisFFO := (sName := sName);
    fbFF: FB_FastFault := (i_Desc := 'Device is not out',
                           i_TypeCode := 16#2200,
                           i_xAutoReset := TRUE);
END_VAR
fbBasicAxisFFO(Axis := stMotionStage.Axis,
               fbFFHWO := fbFFHWO,
               sName := sName,
               bIsNotMoving => bIsNotMoving);

fbFF(i_DevName := sName,
     i_xOK := bFFOk,
     io_fbFFHWO := fbFFHWO);

END_FUNCTION_BLOCK
Related:

FB_BasicMotionStageFFO

FUNCTION_BLOCK FB_BasicMotionStageFFO
(*
    Placeholder FFO logic for no beam allowed, pre-comissioning

    Fast fault is applied if the motor is moving or is not at the out switch.
*)
VAR_IN_OUT
    stMotionStage: DUT_MotionStage;
    fbFFHWO: FB_HardwareFFOutput;
END_VAR
VAR_INPUT
    sName: STRING;
    bForwardIsOut: BOOL := TRUE;
END_VAR
VAR_OUTPUT
    bIsOut: BOOL;
    bIsNotMoving: BOOL;
END_VAR
VAR
    fbBasicAxisFFO: FB_BasicAxisFFO := (sName := sName);
    fbFF: FB_FastFault := (i_Desc := 'Device is not out',
                           i_TypeCode := 16#2200,
                           i_xAutoReset := TRUE);
END_VAR
fbBasicAxisFFO(Axis := stMotionStage.Axis,
               fbFFHWO := fbFFHWO,
               sName := sName,
               bIsNotMoving => bIsNotMoving);

IF bForwardIsOut THEN
    bIsOut := NOT stMotionStage.bLimitForwardEnable;
ELSE
    bIsOut := NOT stMotionStage.bLimitBackwardEnable;
END_IF

fbFF(i_DevName := sName,
     i_xOK := bIsOut,
     io_fbFFHWO := fbFFHWO);

END_FUNCTION_BLOCK
Related:

FB_DoubleActingMPA

FUNCTION_BLOCK FB_DoubleActingMPA
VAR_IN_OUT
    iq_MPA : DUT_DoubleActPneumaticActuator;
END_VAR

VAR


END_VAR
///Check valve postion



IF iq_MPA.i_xInsertLS AND iq_MPA.i_xRetractLS THEN
    iq_MPA.eState:=INVALID;
ELSIF NOT iq_MPA.i_xInsertLS AND iq_MPA.i_xRetractLS AND iq_MPA.q_xRetractDO THEN
    iq_MPA.eState:=RETRACTED;
ELSIF iq_MPA.i_xInsertLS AND NOT iq_MPA.i_xRetractLS AND NOT iq_MPA.q_xInsertDO THEN
    iq_MPA.eState:=INSERTED;
ELSIF NOT iq_MPA.i_xInsertLS AND NOT iq_MPA.i_xInsertLS THEN
    iq_MPA.eState:=MOVING;
ELSE
    iq_MPA.eState:=INVALID;
END_IF



IF iq_MPA._xInsertSW  THEN
    iq_MPA._xRetractSW := FALSE;
    iq_MPA.q_xRetractDO := FALSE;
    iq_MPA.q_xInsertDO := TRUE;
END_IF

IF iq_MPA._xRetractSW THEN
    iq_MPA._xInsertSW := FALSE;
    iq_MPA.q_xInsertDO:= FALSE;
    iq_MPA.q_xRetractDO := TRUE;
END_IF

END_FUNCTION_BLOCK

FB_MPA

FUNCTION_BLOCK FB_MPA
VAR_INPUT
    (*EPS Interlock Bits*)
    ibInsertOK: BOOL;
    ibRetractOK: BOOL;
    ibPMPS_OK:BOOL;
    ibOverrideInterlock:BOOL; (*if true interlocks are ignored*)
    // Reset fault
    {attribute 'pytmc' := '
    pv: FF_Reset
    '}
    i_xReset: BOOL;
    sName: STRING;
    bEnableFF: BOOL := TRUE;
END_VAR
VAR_OUTPUT
    {attribute 'pytmc' := '
    pv:
    '}
    q_stAct     :    ST_MPA;
    {attribute 'pytmc' := '
    pv: MPS_FAULT
    '}
    xMPS_OK:BOOL;
    {attribute 'pytmc' := '
    pv: MOT_DONE
    '}
    xDone:Bool; // Motion is Done
END_VAR
VAR_IN_OUT
    io_fbFFHWO    :    FB_HardwareFFOutput;
END_VAR
VAR
    // PMPS
    fbFF    :    FB_FastFault :=(
        i_xAutoReset := TRUE,
        i_Desc := 'Device is moving',
        i_TypeCode := 16#1010);

    (*Init*)
    xFirstPass    :    BOOL;
    fbFSInit        :    R_TRIG;

    (* Timeouts*)
    tTimeOutDuration: TIME:= T#5S;
    tInserttimeout: TON;
    tRetracttimeout:TON;

    (*IO*)
    i_xInsertedLS    AT%I*: BOOL;
    i_xRetractedLS    AT%I*: BOOL;
    q_xInsert_DO    AT%Q*: BOOL;
    q_xRetract_DO    AT%Q*: BOOL;

    (* Reset Triggers *)
    rtInsert: R_TRIG;
    rtRemove: R_TRIG;
END_VAR
(*Initialize*)
fbFSInit( CLK := TRUE, Q => xFirstPass);
(*IO Mapping*)
ACT_IO();

IF xFirstPass THEN
    q_stAct.eState := INVALID;
    q_stAct.bRetract_SW := FALSE;
    q_stAct.bInsert_SW := FALSE;
END_IF


(* Manage States*)
IF q_stAct.i_bInLS AND  q_stAct.i_bOutLS THEN
    q_stAct.eState:=INVALID;
ELSIF NOT q_stAct.i_bInLS AND q_stAct.i_bOutLS THEN
    q_stAct.eState:=RETRACTED;
ELSIF q_stAct.i_bInLS AND NOT q_stAct.i_bOutLS THEN
    q_stAct.eState:=INSERTED;
ELSIF NOT q_stAct.i_bInLS AND NOT q_stAct.i_bOutLS THEN
    q_stAct.eState:=MOVING;
ELSE
    q_stAct.eState:=INVALID;
END_IF

(*Set the Done signal*)
xDone := (q_stAct.bRetract_SW AND q_stAct.eState=RETRACTED) OR (q_stAct.eState=INSERTED AND q_stAct.bInsert_SW);


(*MPS FAULT*)
(**)
xMPS_OK := (q_stAct.bRetract_SW AND i_xRetractedLS) XOR (i_xInsertedLS AND q_stAct.bInsert_SW);
//xMPS_OK := i_xRetractedLS XOR i_xInsertedLS;
//xMPS_OK := (q_stAct.eState=RETRACTED) OR (q_stAct.eState=INSERTED);
//xMPS_OK := (q_stAct.eState=RETRACTED) ;

(*PMPS PERMISSION*)

(* Reset the other command bit when one goes high *)
rtInsert(CLK:=q_stAct.bInsert_SW);
IF rtInsert.Q THEN
    q_stAct.bRetract_SW := FALSE;
END_IF
rtRemove(CLK:=q_stAct.bRetract_SW);
IF rtRemove.Q THEN
    q_stAct.bInsert_SW := FALSE;
END_IF

(* Can't have bRetract_SW and  bInsert_SW both be true*)
If (q_stAct.bRetract_SW) and (q_stAct.bInsert_SW) THEN
    q_stAct.bRetract_SW := FALSE;
    q_stAct.bInsert_SW := FALSE;
END_IF

(* Make the state consistent if we can *)
IF NOT (q_stAct.bRetract_SW OR q_stAct.bInsert_SW) THEN
    IF q_stAct.eState = RETRACTED THEN
        q_stAct.bRetract_SW := TRUE;
    ELSIF q_stAct.eState = INSERTED THEN
        q_stAct.bInsert_SW := TRUE;
    END_IF
END_IF

q_stAct.bRetractOK := ibRetractOK;
q_stAct.bInsertOK := ibInsertOK;

(*Actuate the device*)
q_stAct.q_bRetract := q_stAct.bRetractOK AND q_stAct.bRetract_SW;
q_stAct.q_bInsert := q_stAct.bInsertOK AND q_stAct.bInsert_SW;

IF q_stAct.q_bInsert THEN
    q_stAct.q_bRetract := FALSE;
    q_stAct.bRetract_SW:= FALSE;
ELSIF q_stAct.q_bRetract THEN
    q_stAct.q_bInsert := FALSE;
    q_stAct.bInsert_SW:= FALSE;
END_IF;




(*Timers*)
tInserttimeout(IN:= q_stAct.q_bInsert, PT := tTimeOutDuration );
tRetracttimeout(IN:= q_stAct.q_bRetract, PT := tTimeOutDuration);

///Check moving postion timout
IF NOT q_stAct.i_bInLS AND tInserttimeout.Q THEN
    q_stAct.bErrorPresent := TRUE;
ELSIF NOT q_stAct.i_bOutLS AND tRetracttimeout.Q THEN
    q_stAct.bErrorPresent := TRUE;
END_IF

(*FAST FAULT*)
IF bEnableFF THEN
    fbFF(i_DevName := sName,
        i_xOK := xMPS_OK,
        i_xReset := i_xReset,
        io_fbFFHWO := io_fbFFHWO);
END_IF

(*Soft IO Mapping*)
ACT_IO();

END_FUNCTION_BLOCK

ACTION ACT_IO:
(*Inputs*)
q_stAct.i_bInLS :=  i_xInsertedLS;
q_stAct.i_bOutLS := i_xRetractedLS;

(*outputs*)
q_xInsert_DO:=q_stAct.q_bInsert;
q_xRetract_DO:=q_stAct.q_bRetract;
END_ACTION
Related:

FB_SimMotor

FUNCTION_BLOCK FB_SimMotor
VAR_IN_OUT
    stMotionStage: DUT_MotionStage;
END_VAR
VAR
    fbMotionStage: FB_MotionStage;
END_VAR
stMotionStage.bLimitBackwardEnable := TRUE;
stMotionStage.bLimitForwardEnable := TRUE;
stMotionStage.bHardwareEnable := TRUE;
stMotionStage.bPowerSelf := TRUE;
stMotionStage.nEnableMode := ENUM_StageEnableMode.ALWAYS;
fbMotionStage(stMotionStage := stMotionStage);

END_FUNCTION_BLOCK

FB_SLITS

FUNCTION_BLOCK FB_SLITS
VAR_IN_OUT
    stTopBlade: DUT_MotionStage;
    stBottomBlade: DUT_MotionStage;
    stNorthBlade: DUT_MotionStage;
    stSouthBlade: DUT_MotionStage;
    bExecuteMotion:BOOL ;
END_VAR

VAR_INPUT

    {attribute 'pytmc' := '
    pv: PMPS_OK;
    io: i;
    field: ZNAM False
    field: ONAM True
    '}
    bMoveOk:BOOL;
    (*Offsets*)
    {attribute 'pytmc' := '
    pv: Offset_Top;
    io: io;
    '}
    rEncoderOffsetTop: REAL;
    {attribute 'pytmc' := '
    pv: ZeroOffset_Bottom;
    io: io;
    '}
    rEncoderOffsetBottom: REAL;
    {attribute 'pytmc' := '
    pv: ZeroOffset_North;
    io: io;
    '}
    rEncoderOffsetNorth: REAL;
    {attribute 'pytmc' := '
    pv: ZeroOffset_South;
    io: io;
    '}
    rEncoderOffsetSouth: REAL;
END_VAR

VAR
    fbTopBlade: FB_MotionStage;
    fbBottomBlade: FB_MotionStage;
    fbNorthBlade: FB_MotionStage;
    fbSouthBlade: FB_MotionStage;
    fPosTopBlade: LREAL;
    fPosBottomBlade: LREAL;
    fPosNorthBlade: LREAL;
    fPosSouthBlade: LREAL;

    (*Motion Parameters*)
    fSmallDelta: LREAL := 0.01;
    fBigDelta: LREAL := 10;
    fMaxVelocity: LREAL := 0.2;
    fHighAccel: LREAL := 0.8;
    fLowAccel: LREAL := 0.1;

    stTop: DUT_PositionState;
    stBOTTOM: DUT_PositionState;
    stNorth: DUT_PositionState;
    stSouth: DUT_PositionState;

    {attribute 'pytmc' := 'pv: TOP'}
    fbTop: FB_StatePTPMove;
    {attribute 'pytmc' := 'pv: BOTTOM'}
    fbBottom: FB_StatePTPMove;
    {attribute 'pytmc' := 'pv: NORTH'}
    fbNorth: FB_StatePTPMove;
    {attribute 'pytmc' := 'pv: SOUTH'}
    fbSouth: FB_StatePTPMove;

    (*EPICS pvs*)
    {attribute 'pytmc' := '
    pv: XWID_REQ;
    io: io;
    '}
    rReqApertureSizeX : REAL;
    {attribute 'pytmc' := '
    pv: YWID_REQ;
    io: io;
    '}
    rReqApertureSizeY : REAL;
    {attribute 'pytmc' := '
    pv: XCEN_REQ;
    io: io;
    '}
    rReqCenterX: REAL;
    {attribute 'pytmc' := '
    pv: YCEN_REQ;
    io: io;
    '}
    rReqCenterY: REAL;

    {attribute 'pytmc' := '
    pv: ACTUAL_XWIDTH;
    io: io;
    '}
    rActApertureSizeX : REAL;

    {attribute 'pytmc' := '
    pv: ACTUAL_YWIDTH;
    io: io;
    '}
    rActApertureSizeY : REAL;
    {attribute 'pytmc' := '
    pv: ACTUAL_XCENTER;
    io: io;
    '}
    rActCenterX: REAL;
    {attribute 'pytmc' := '
    pv: ACTUAL_YCENTER;
    io: io;
    '}
    rActCenterY: REAL;

    {attribute 'pytmc' := '
    pv: XCEN_SETZERO;
    io: io;
    '}
    rSetCenterX: BOOL;
    {attribute 'pytmc' := '
    pv: YCEN_SETZERO;
    io: io;
    '}
    rSetCenterY: BOOL;


    {attribute 'pytmc' := '
    pv: OPEN;
    io: io;
    field: ZNAM False
    field: ONAM True
    '}
    bOpen: BOOL;

    {attribute 'pytmc' := '
    pv: CLOSE;
    io: io;
    field: ZNAM False
    field: ONAM True
    '}
    bClose: BOOL;

    {attribute 'pytmc' := '
    pv: BLOCK;
    io: io;
    field: ZNAM False
    field: ONAM True
    '}
    bBlock: BOOL;



        //Local variables
    bInit: BOOL :=true;
    rTrig_Block: R_TRIG;
    rTrig_Open: R_TRIG;
    rTrig_Close: R_TRIG;

        //old values
    rOldReqApertureSizeX : REAL;
    rOldReqApertureSizeY : REAL;
    rOldReqCenterX: REAL;
    rOldReqCenterY: REAL;

    bExecuteMotionX: BOOL;
    bExecuteMotionY: BOOL;


    fPosBlock: LREAL;
    fPosClose: LREAL;
    fPosOpen: LREAL;

    stSetPositionOptions:ST_SetPositionOptions;
    fbSetPosition_TOP: MC_SetPosition;
    fbSetPosition_Bottom: MC_SetPosition;
    fbSetPosition_North: MC_SetPosition;
    fbSetPosition_South: MC_SetPosition;

    // For logging
    fbLogger : FB_LogMessage := (eSubsystem:=E_SubSystem.MOTION);

END_VAR


END_FUNCTION_BLOCK

ACTION ACT_BLOCK:
rTrig_Block (CLK:= bBlock);
rTrig_Open (CLK:= bOpen);
rTrig_Close (CLK:= bClose);

if (rTrig_Block.Q) THEN
    //BLOCK

    bBlock := false;
END_IF

if (rTrig_Open.Q) THEN


    bOpen := false;
END_IF

if (rTrig_Close.Q) THEN


    bClose := false;
END_IF
END_ACTION

ACTION ACT_CalculatePositions:
//check if requested center or gap has changed
//check that the requested values are within acceptable motion range
IF (rOldReqApertureSizeX <> rReqApertureSizeX) THEN
    rOldReqApertureSizeX := rReqApertureSizeX;
    bExecuteMotionX := TRUE;
    fbLogger(sMsg:='Requested new X gap.', eSevr:=TcEventSeverity.Verbose);
END_IF

IF (rOldReqCenterX <> rReqCenterX) THEN
    rOldReqCenterX := rReqCenterX;
    bExecuteMotionX := TRUE;
    fbLogger(sMsg:='Requested new X center', eSevr:=TcEventSeverity.Verbose);

END_IF

IF (rOldReqApertureSizeY <> rReqApertureSizeY) THEN
    rOldReqApertureSizeY := rReqApertureSizeY;
    bExecuteMotionY := TRUE;
    fbLogger(sMsg:='Requested new Y gap.', eSevr:=TcEventSeverity.Verbose);
END_IF

IF (rOldReqCenterY <> rReqCenterY) THEN
   rOldReqCenterY := rReqCenterY;
   bExecuteMotionY := TRUE;
   fbLogger(sMsg:='Requested new Y center.', eSevr:=TcEventSeverity.Verbose);

END_IF


//Calculate requested target positions from requested gap and center
fPosTopBlade := (rReqApertureSizeY/2) + (rReqCenterY + rEncoderOffsetTop) ;
fPosBottomBlade := (-1*rReqApertureSizeY/2) + (rReqCenterY+rEncoderOffsetBottom);

fPosNorthBlade := (rReqApertureSizeX/2) + (rReqCenterX + rEncoderOffsetNorth);
fPosSouthBlade := (-1*rReqApertureSizeX/2) + (rReqCenterX + rEncoderOffsetSouth);


//Calculate actual gap and center from actual stages positions
rActApertureSizeX := LREAL_TO_REAL((stNorthBlade.stAxisStatus.fActPosition - rEncoderOffsetNorth) - (stSouthBlade.stAxisStatus.fActPosition- rEncoderOffsetSouth));

rActApertureSizeY := LREAL_TO_REAL((stTopBlade.stAxisStatus.fActPosition - rEncoderOffsetTop) - (stBottomBlade.stAxisStatus.fActPosition - rEncoderOffsetBottom));

rActCenterX := LREAL_TO_REAL((((stNorthBlade.stAxisStatus.fActPosition - rEncoderOffsetNorth)  + (stSouthBlade.stAxisStatus.fActPosition - rEncoderOffsetSouth ))/2));

rActCenterY := LREAL_TO_REAL((((stTopBlade.stAxisStatus.fActPosition - rEncoderOffsetTop) + (stBottomBlade.stAxisStatus.fActPosition - rEncoderOffsetBottom))/2));



//Update PMPS Arbiter with the Actual Size and Center of the Aperture
END_ACTION

ACTION ACT_Home:

END_ACTION

ACTION ACT_Init:
//  init the motion stages parameters
IF ( bInit) THEN
    stTopBlade.bHardwareEnable := TRUE;
    stBottomBlade.bHardwareEnable := TRUE;
    stNorthBlade.bHardwareEnable := TRUE;
    stSouthBlade.bHardwareEnable := TRUE;
    stTopBlade.bPowerSelf :=TRUE;
    stBottomBlade.bPowerSelf :=TRUE;
    stNorthBlade.bPowerSelf :=TRUE;
    stSouthBlade.bPowerSelf :=TRUE;
    stTopBlade.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    stBottomBlade.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    stNorthBlade.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    stSouthBlade.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
END_IF
END_ACTION

ACTION ACT_Motion:
// Instantiate Function block for all the blades
fbTopBlade(stMotionStage:=stTopBlade);
fbBottomBlade(stMotionStage:=stBottomBlade);
fbNorthBlade(stMotionStage:=stNorthBlade);
fbSouthBlade(stMotionStage:=stSouthBlade);

// PTP Motion for each blade
stTop.sName := 'Top';
stTop.fPosition := fPosTopBlade;
stTop.fDelta := fSmallDelta;
stTop.fVelocity := fMaxVelocity;
stTop.fAccel := fHighAccel;
stTop.fDecel := fHighAccel;

stBOTTOM.sName := 'Bottom';
stBOTTOM.fPosition := fPosBottomBlade;
stBOTTOM.fDelta := fSmallDelta;
stBOTTOM.fVelocity := fMaxVelocity;
stBOTTOM.fAccel := fHighAccel;
stBOTTOM.fDecel := fHighAccel;

stNorth.sName := 'North';
stNorth.fPosition := fPosNorthBlade;
stNorth.fDelta := fSmallDelta;
stNorth.fVelocity := fMaxVelocity;
stNorth.fAccel := fHighAccel;
stNorth.fDecel := fHighAccel;

stSouth.sName := 'South';
stSouth.fPosition := fPosSouthBlade;
stSouth.fDelta := fSmallDelta;
stSouth.fVelocity := fMaxVelocity;
stSouth.fAccel := fHighAccel;
stSouth.fDecel := fHighAccel;

IF (bExecuteMotionY) THEN
    fbTop.bExecute := fbBottom.bExecute := bExecuteMotionY;
    bExecuteMotionY:= FALSE;
END_IF

IF (bExecuteMotionX) THEN
    fbNorth.bExecute := fbSouth.bExecute := bExecuteMotionX;
    bExecuteMotionX:= FALSE;
END_IF


fbTop(
    stPositionState:=stTop,
    bMoveOk:=bMoveOk,
    stMotionStage:=stTopBlade);

fbBottom(
    stPositionState:=stBOTTOM,
    bMoveOk:=bMoveOk,
    stMotionStage:=stBottomBlade);

fbNorth(
    stPositionState:=stNorth,
    bMoveOk:=bMoveOk,
    stMotionStage:=stNorthBlade);

fbSouth(
    stPositionState:=stSouth,
    bMoveOk:=bMoveOk,
    stMotionStage:=stSouthBlade);
END_ACTION

ACTION ACT_Zero:
//ZERO BIAS

// Set Y center to zero

// Set X center to zero

if (rSetCenterY)THEN
        rSetCenterY := false;
        // Set Current Position
        fbSetPosition_TOP.Position :=  stTopBlade.stAxisStatus.fActPosition - rActCenterY ;
        fbSetPosition_TOP.Execute := TRUE;
        fbSetPosition_Bottom.Position := stBottomBlade.stAxisStatus.fActPosition - rActCenterY;
        fbSetPosition_Bottom.Execute := TRUE;
END_IF

if (rSetCenterX)THEN
        rSetCenterX := false;
        // Set Current Position
        fbSetPosition_North.Position := stNorthBlade.stAxisStatus.fActPosition - rActCenterX ;
        fbSetPosition_North.Execute := TRUE;
        fbSetPosition_South.Position := stSouthBlade.stAxisStatus.fActPosition - rActCenterX ; ;
        fbSetPosition_South.Execute := TRUE;
END_IF


//Reset
if (fbSetPosition_TOP.Done ) THEN
    fbSetPosition_TOP.Execute := FALSE;
END_IF
if (fbSetPosition_Bottom.Done ) THEN
    fbSetPosition_Bottom.Execute := FALSE;
END_IF
if (fbSetPosition_North.Done ) THEN
    fbSetPosition_North.Execute := FALSE;
END_IF
if (fbSetPosition_South.Done ) THEN
    fbSetPosition_South.Execute := FALSE;
END_IF

// Set Encoder Position
//Clear position lag error
stSetPositionOptions.ClearPositionLag := TRUE;
fbSetPosition_TOP(
    Axis:=  stTopBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE,
    Options:= stSetPositionOptions,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );
fbSetPosition_Bottom(
    Axis:= stBottomBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE,
    Options:= stSetPositionOptions,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );
fbSetPosition_North(
    Axis:= stNorthBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE,
    Options:= stSetPositionOptions,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );
fbSetPosition_South(
    Axis:= stSouthBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE,
    Options:= stSetPositionOptions,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );
END_ACTION

FB_SLITS_POWER

FUNCTION_BLOCK FB_SLITS_POWER EXTENDS FB_SLITS
VAR_INPUT
END_VAR
VAR
     {attribute 'pytmc' := '
        pv: FSW
    '}
    fbFlowSwitch: FB_XTES_Flowswitch;


    //RTDs
    {attribute 'pytmc' := '
        pv: TOP:RTD:01
    '}
    RTD_TOP_1: FB_TempSensor;
    {attribute 'pytmc' := '
        pv: TOP:RTD:02
    '}
    RTD_TOP_2: FB_TempSensor;
    {attribute 'pytmc' := '
        pv: BOTTOM:RTD:01
    '}
    RTD_Bottom_1: FB_TempSensor;
    {attribute 'pytmc' := '
        pv: BOTTOM:RTD:02
    '}
    RTD_Bottom_2: FB_TempSensor;

    {attribute 'pytmc' := '
        pv: NORTH:RTD:01
    '}
    RTD_North_1: FB_TempSensor;
    {attribute 'pytmc' := '
        pv: NORTH:RTD:02
    '}
    RTD_North_2: FB_TempSensor;
    {attribute 'pytmc' := '
        pv: SOUTH:RTD:01
    '}
    RTD_South_1: FB_TempSensor;
    {attribute 'pytmc' := '
        pv: SOUTH:RTD:02
    '}
    RTD_South_2: FB_TempSensor;


END_VAR
ACT_init();

// Instantiate Function block for all the blades
ACT_Motion();
//SET and GET the requested and Actual values
ACT_CalculatePositions();
//ACT_Zero();
//ACT_BLOCK();
ACT_RTDs();

END_FUNCTION_BLOCK

ACTION ACT_RTDs:
////RTDs
RTD_TOP_1();
RTD_TOP_2();
RTD_Bottom_1();
RTD_Bottom_2();
RTD_North_1();
RTD_North_2();
RTD_South_1();
RTD_South_2();

//Flow Switch
fbFlowSwitch();
END_ACTION
Related:

FB_SLITS_POWER_1

FUNCTION_BLOCK FB_SLITS_POWER_1
VAR_IN_OUT
    stTopBlade: DUT_MotionStage;
    stBottomBlade: DUT_MotionStage;
    stNorthBlade: DUT_MotionStage;
    stSouthBlade: DUT_MotionStage;
END_VAR
VAR_INPUT
    fPosTopBlade: LREAL;
    fPosBottomBlade: LREAL;
    fPosNorthBlade: LREAL;
    fPosSouthBlade: LREAL;
    bExecuteMotion:bool ;
END_VAR
VAR_OUTPUT
END_VAR
VAR
    fbTopBlade: FB_MotionStage;
    fbBottomBlade: FB_MotionStage;
    fbNorthBlade: FB_MotionStage;
    fbSouthBlade: FB_MotionStage;

    {attribute 'pytmc' := '
        pv: FSW
    '}
    fbFlowSwitch: FB_XTES_Flowswitch;


    //RTDs
    {attribute 'pytmc' := '
        pv: TOP:RTD:01
    '}
    RTD_TOP_1: FB_ThermoCouple;
    {attribute 'pytmc' := '
        pv: TOP:RTD:02
    '}
    RTD_TOP_2: FB_ThermoCouple;
    {attribute 'pytmc' := '
        pv: BOTTOM:RTD:01
    '}
    RTD_Bottom_1: FB_ThermoCouple;
    {attribute 'pytmc' := '
        pv: BOTTOM:RTD:02
    '}
    RTD_Bottom_2: FB_ThermoCouple;

    {attribute 'pytmc' := '
        pv: NORTH:RTD:01
    '}
    RTD_North_1: FB_ThermoCouple;
    {attribute 'pytmc' := '
        pv: NORTH:RTD:02
    '}
    RTD_North_2: FB_ThermoCouple;
    {attribute 'pytmc' := '
        pv: SOUTH:RTD:01
    '}
    RTD_South_1: FB_ThermoCouple;
    {attribute 'pytmc' := '
        pv: SOUTH:RTD:02
    '}
    RTD_South_2: FB_ThermoCouple;

    fSmallDelta: LREAL := 0.01;
    fBigDelta: LREAL := 10;
    fMaxVelocity: LREAL := 0.33;
    fHighAccel: LREAL := 0.8;
    fLowAccel: LREAL := 0.1;

    stTop: DUT_PositionState;
    stBOTTOM: DUT_PositionState;
    stNorth: DUT_PositionState;
    stSouth: DUT_PositionState;

    {attribute 'pytmc' := 'pv: TOP'}
    fbTop: FB_StatePTPMove;
    {attribute 'pytmc' := 'pv: BOTTOM'}
    fbBottom: FB_StatePTPMove;
    {attribute 'pytmc' := 'pv: NORTH'}
    fbNorth: FB_StatePTPMove;
    {attribute 'pytmc' := 'pv: SOUTH'}
    fbSouth: FB_StatePTPMove;


END_VAR
// Instantiate Function block for all the blades
fbTopBlade(stMotionStage:=stTopBlade);
fbBottomBlade(stMotionStage:=stBottomBlade);
fbNorthBlade(stMotionStage:=stNorthBlade);
fbSouthBlade(stMotionStage:=stSouthBlade);

//  no STO
stTopBlade.bHardwareEnable := TRUE;
stBottomBlade.bHardwareEnable := TRUE;
stNorthBlade.bHardwareEnable := TRUE;
stSouthBlade.bHardwareEnable := TRUE;
stTopBlade.bPowerSelf :=TRUE;
stBottomBlade.bPowerSelf :=TRUE;
stNorthBlade.bPowerSelf :=TRUE;
stSouthBlade.bPowerSelf :=TRUE;

//RTDs
RTD_TOP_1();
RTD_TOP_2();
RTD_Bottom_1();
RTD_Bottom_2();
RTD_North_1();
RTD_North_2();
RTD_South_1();
RTD_South_2();

//Flow Switch
fbFlowSwitch();


// PTP Motion for each blade

stTop.sName := 'Top';
stTop.fPosition := fPosTopBlade;
stTop.fDelta := fSmallDelta;
stTop.fVelocity := fMaxVelocity;
stTop.fAccel := fHighAccel;
stTop.fDecel := fHighAccel;

stBOTTOM.sName := 'Bottom';
stBOTTOM.fPosition := fPosBottomBlade;
stBOTTOM.fDelta := fSmallDelta;
stBOTTOM.fVelocity := fMaxVelocity;
stBOTTOM.fAccel := fHighAccel;
stBOTTOM.fDecel := fHighAccel;

stNorth.sName := 'North';
stNorth.fPosition := fPosNorthBlade;
stNorth.fDelta := fSmallDelta;
stNorth.fVelocity := fMaxVelocity;
stNorth.fAccel := fHighAccel;
stNorth.fDecel := fHighAccel;

stSouth.sName := 'South';
stSouth.fPosition := fPosSouthBlade;
stSouth.fDelta := fSmallDelta;
stSouth.fVelocity := fMaxVelocity;
stSouth.fAccel := fHighAccel;
stSouth.fDecel := fHighAccel;

//fbTop.bExecute := fbBottom.bExecute :=fbNorth.bExecute := fbSouth.bExecute := bExecuteMotion;

fbTop(
    stPositionState:=stTop,
    bMoveOk:=TRUE,
    stMotionStage:=stTopBlade);

fbBottom(
    stPositionState:=stBOTTOM,
    bMoveOk:=TRUE,
    stMotionStage:=stBottomBlade);

fbNorth(
    stPositionState:=stNorth,
    bMoveOk:=TRUE,
    stMotionStage:=stNorthBlade);

fbSouth(
    stPositionState:=stSouth,
    bMoveOk:=TRUE,
    stMotionStage:=stSouthBlade);

END_FUNCTION_BLOCK

PRG_1_PlcTask

PROGRAM PRG_1_PlcTask
(*
    Launch site for each component's program
    Only "fast" programs are allowed here,
    anything else needs to be relegated to a second task
*)
PRG_2_PMPS_PRE();

PRG_AT2L0_SOLID();
PRG_IM1L0_XTES();
PRG_IM1L1_PPM();
PRG_IM2L0_XTES();
PRG_IM3L0_PPM();
PRG_IM4L0_XTES();
PRG_PF1L0_WFS();
PRG_RTDSL0();
PRG_SL1L0_POWER();
PRG_SL2L0_POWER();
PRG_SP1L0_KMONO();

PRG_3_PMPS_POST();
PRG_4_LOG();

END_PROGRAM
Related:

PRG_2_PMPS_PRE

PROGRAM PRG_2_PMPS_PRE
VAR
    nCycles: UDINT := 200;
    nStartCycle: UDINT;
    nCycleCount: UDINT;
    nCurrTaskIndex: BYTE;
    getTask: GETCURTASKINDEX;
END_VAR
// Stagger initializations to avoid clogging PMPS Arbiter Queue
getTask();
nCycleCount := _TaskInfo[getTask.index].CycleCount;
IF nStartCycle = 0 THEN
    nStartCycle := nCycleCount;
END_IF

GVL.bInitIM1L0 S= nCycleCount - nStartCycle > nCycles;
GVL.bInitIM1L1 S= nCycleCount - nStartCycle > nCycles * 2;
GVL.bInitIM2L0 S= nCycleCount - nStartCycle > nCycles * 3;
GVL.bInitIM3L0 S= nCycleCount - nStartCycle > nCycles * 4;
GVL.bInitIM4L0 S= nCycleCount - nStartCycle > nCycles * 5;

END_PROGRAM
Related:

PRG_3_PMPS_POST

PROGRAM PRG_3_PMPS_POST
VAR
    fbArbiterIO: FB_SubSysToArbiter_IO;
END_VAR
GVL.fbFastFaultOutput1.Execute();
GVL.fbFastFaultOutput2.Execute();

fbArbiterIO(
    Arbiter:=GVL.fbArbiter,
    fbFFHWO:=GVL.fbFastFaultOutput1);

END_PROGRAM
Related:

PRG_4_LOG

PROGRAM PRG_4_LOG
VAR
    fbLogHandler: FB_LogHandler;
END_VAR
fbLogHandler();

END_PROGRAM

PRG_AT2L0_SOLID

PROGRAM PRG_AT2L0_SOLID
VAR
    bAT2L0_debug: BOOL := FALSE;
    nAT2L0_enableMode: ENUM_StageEnableMode := ENUM_StageEnableMode.DURING_MOTION;

    iIndex: INT;
    fbAT2L0_motion: ARRAY [1..19] OF FB_MotionStage;
    fbAT2L0_axes: ARRAY [1..19] OF POINTER TO DUT_MotionStage;
    fbAT2L0_ffo: ARRAY[1..19] OF FB_AttFFO;

    {attribute 'pytmc' := '
        pv: AT2L0:XTES:MMS
        expand: :%.2d:FILTER
    '}
    fbAT2L0_filters: ARRAY[1..19] OF DUT_SATT_Filter;

    {attribute 'pytmc' := '
        pv: AT2L0:XTES:TRANSMISSION
        field: DESC Overall transmission of AT2L0
    '}
    fTransmission: LREAL;

    {attribute 'pytmc' := '
        pv: AT2L0:XTES:MMS
        expand: :%.2d:STATE
    '}
    fbAT2L0_states: ARRAY[1..19] OF FB_PositionStateInOut;

    stOut: DUT_PositionState := (
        fPosition := 24,
        fDelta := 2,
        fVelocity := 6,
        bMoveOk := TRUE,
        bValid := TRUE);

    stIn: DUT_PositionState := (
        fPosition := 0,
        fDelta := 2,
        fVelocity := 6,
        bMoveOk := TRUE,
        bValid := TRUE);

    // For plotting voltage/current during debugging
    nM1CoilARaw AT %I*: UINT;
    nM1CoilBRaw AT %I*: UINT; // ..CoilBRaw is currently linked to EL7041 'Coil Voltage A'
    nM1CoilA: INT;
    nM1CoilB: INT;
    //nM1Current: INT;
    nM2CoilARaw AT %I*: UINT;
    nM2CoilBRaw AT %I*: UINT;
    nM2CoilA: INT;
    nM2CoilB: INT;
    //nM2Current: INT;
    nM3CoilARaw AT %I*: UINT;
    nM3CoilBRaw AT %I*: UINT;
    nM3CoilA: INT;
    nM3CoilB: INT;
    //nM3Current: INT;
    nM4CoilARaw AT %I*: UINT;
    nM4CoilBRaw AT %I*: UINT;
    nM4CoilA: INT;
    nM4CoilB: INT;
    //nM4Current: INT;
    nM5CoilARaw AT %I*: UINT;
    nM5CoilBRaw AT %I*: UINT;
    nM5CoilA: INT;
    nM5CoilB: INT;
    //nM5Current: INT;
    nM6CoilARaw AT %I*: UINT;
    nM6CoilBRaw AT %I*: UINT;
    nM6CoilA: INT;
    nM6CoilB: INT;
    //nM6Current: INT;
    nM7CoilARaw AT %I*: UINT;
    nM7CoilBRaw AT %I*: UINT;
    nM7CoilA: INT;
    nM7CoilB: INT;
    //nM7Current: INT;
    nM8CoilARaw AT %I*: UINT;
    nM8CoilBRaw AT %I*: UINT;
    nM8CoilA: INT;
    nM8CoilB: INT;
    //nM8Current: INT;
    nM9CoilARaw AT %I*: UINT;
    nM9CoilBRaw AT %I*: UINT;
    nM9CoilA: INT;
    nM9CoilB: INT;
    //nM9Current: INT;
    nM10CoilARaw AT %I*: UINT;
    nM10CoilBRaw AT %I*: UINT;
    nM10CoilA: INT;
    nM10CoilB: INT;
    //nM10Current: INT;
    nM11CoilARaw AT %I*: UINT;
    nM11CoilBRaw AT %I*: UINT;
    nM11CoilA: INT;
    nM11CoilB: INT;
    //nM11Current: INT;
    nM12CoilARaw AT %I*: UINT;
    nM12CoilBRaw AT %I*: UINT;
    nM12CoilA: INT;
    nM12CoilB: INT;
    //nM12Current: INT;
    nM13CoilARaw AT %I*: UINT;
    nM13CoilBRaw AT %I*: UINT;
    nM13CoilA: INT;
    nM13CoilB: INT;
    //nM13Current: INT;
    nM14CoilARaw AT %I*: UINT;
    nM14CoilBRaw AT %I*: UINT;
    nM14CoilA: INT;
    nM14CoilB: INT;
    //nM14Current: INT;
    nM15CoilARaw AT %I*: UINT;
    nM15CoilBRaw AT %I*: UINT;
    nM15CoilA: INT;
    nM15CoilB: INT;
    //nM15Current: INT;
    nM16CoilARaw AT %I*: UINT;
    nM16CoilBRaw AT %I*: UINT;
    nM16CoilA: INT;
    nM16CoilB: INT;
    //nM16Current: INT;
    nM17CoilARaw AT %I*: UINT;
    nM17CoilBRaw AT %I*: UINT;
    nM17CoilA: INT;
    nM17CoilB: INT;
    //nM17Current: INT;
    nM18CoilARaw AT %I*: UINT;
    nM18CoilBRaw AT %I*: UINT;
    nM18CoilA: INT;
    nM18CoilB: INT;
    //nM18Current: INT;
    nM19CoilARaw AT %I*: UINT;
    nM19CoilBRaw AT %I*: UINT;
    nM19CoilA: INT;
    nM19CoilB: INT;
    //nM19Current: INT;

    stFilter : REFERENCE TO DUT_SATT_Filter;
    fFilterDensity : LREAL;
    fFilterAtomicMass : LREAL;
    fbAtomicMass : FB_AtomicMass;
    fbAttenuatorElementDensity : FB_AttenuatorElementDensity;
    fAbsorptionConstant : LREAL;
    bError : BOOL;

END_VAR
fbAT2L0_axes[1]:= ADR(Main.M1);
fbAT2L0_axes[2]:= ADR(Main.M2);
fbAT2L0_axes[3]:= ADR(Main.M3);
fbAT2L0_axes[4]:= ADR(Main.M4);
fbAT2L0_axes[5]:= ADR(Main.M5);
fbAT2L0_axes[6]:= ADR(Main.M6);
fbAT2L0_axes[7]:= ADR(Main.M7);
fbAT2L0_axes[8]:= ADR(Main.M8);
fbAT2L0_axes[9]:= ADR(Main.M9);
fbAT2L0_axes[10]:= ADR(Main.M10);
fbAT2L0_axes[11]:= ADR(Main.M11);
fbAT2L0_axes[12]:= ADR(Main.M12);
fbAT2L0_axes[13]:= ADR(Main.M13);
fbAT2L0_axes[14]:= ADR(Main.M14);
fbAT2L0_axes[15]:= ADR(Main.M15);
fbAT2L0_axes[16]:= ADR(Main.M16);
fbAT2L0_axes[17]:= ADR(Main.M17);
fbAT2L0_axes[18]:= ADR(Main.M18);
fbAT2L0_axes[19]:= ADR(Main.M19);

(* Not a filter *)
fbAT2L0_filters[ 1].fFilterThickness_um := 0;
fbAT2L0_filters[ 1].sFilterMaterial     := '';

fbAT2L0_filters[ 2].fFilterThickness_um := 1280.0;
fbAT2L0_filters[ 2].sFilterMaterial     := 'C';
fbAT2L0_filters[ 3].fFilterThickness_um := 320.0;
fbAT2L0_filters[ 3].sFilterMaterial     := 'C';
fbAT2L0_filters[ 4].fFilterThickness_um := 640.0;
fbAT2L0_filters[ 4].sFilterMaterial     := 'C';
fbAT2L0_filters[ 5].fFilterThickness_um := 160.0;
fbAT2L0_filters[ 5].sFilterMaterial     := 'C';
fbAT2L0_filters[ 6].fFilterThickness_um := 80.0;
fbAT2L0_filters[ 6].sFilterMaterial     := 'C';
fbAT2L0_filters[ 7].fFilterThickness_um := 40.0;
fbAT2L0_filters[ 7].sFilterMaterial     := 'C';
fbAT2L0_filters[ 8].fFilterThickness_um := 20.0;
fbAT2L0_filters[ 8].sFilterMaterial     := 'C';
fbAT2L0_filters[ 9].fFilterThickness_um := 10.0;
fbAT2L0_filters[ 9].sFilterMaterial     := 'C';

fbAT2L0_filters[10].fFilterThickness_um := 10240.0;
fbAT2L0_filters[10].sFilterMaterial     := 'Si';
fbAT2L0_filters[11].fFilterThickness_um := 5120.0;
fbAT2L0_filters[11].sFilterMaterial     := 'Si';
fbAT2L0_filters[12].fFilterThickness_um := 2560.0;
fbAT2L0_filters[12].sFilterMaterial     := 'Si';
fbAT2L0_filters[13].fFilterThickness_um := 1280.0;
fbAT2L0_filters[13].sFilterMaterial     := 'Si';
fbAT2L0_filters[14].fFilterThickness_um := 640.0;
fbAT2L0_filters[14].sFilterMaterial     := 'Si';
fbAT2L0_filters[15].fFilterThickness_um := 320.0;
fbAT2L0_filters[15].sFilterMaterial     := 'Si';
fbAT2L0_filters[16].fFilterThickness_um := 160.0;
fbAT2L0_filters[16].sFilterMaterial     := 'Si';
fbAT2L0_filters[17].fFilterThickness_um := 80.0;
fbAT2L0_filters[17].sFilterMaterial     := 'Si';
fbAT2L0_filters[18].fFilterThickness_um := 40.0;
fbAT2L0_filters[18].sFilterMaterial     := 'Si';
fbAT2L0_filters[19].fFilterThickness_um := 20.0;
fbAT2L0_filters[19].sFilterMaterial     := 'Si';

IF bAT2L0_debug THEN
    nAT2L0_enableMode := ENUM_StageEnableMode.ALWAYS;
ELSE
    nAT2L0_enableMode := ENUM_StageEnableMode.DURING_MOTION;
END_IF


(* Recalculate the overall transmission below *)
fTransmission := 1.0;

FOR iIndex := 1 TO 19 DO
    fbAT2L0_motion[iIndex](stMotionStage := fbAT2L0_axes[iIndex]^);
    fbAT2L0_axes[iIndex]^.nEnableMode := nAT2L0_enableMode;
    fbAT2L0_axes[iIndex]^.bHardwareEnable := TRUE;
    fbAT2L0_axes[iIndex]^.bPowerSelf := TRUE;
    stFilter REF= fbAT2L0_filters[iIndex];

    fbAT2L0_states[iIndex](
        bEnable := TRUE,
        stMotionStage := fbAT2L0_axes[iIndex]^,
        stOut := stOut,
        stIn := stIn);

    fbAT2L0_ffo[iIndex](
        stMotionStage := fbAT2L0_axes[iIndex]^,
        enumState := fbAT2L0_states[iIndex].enumGet,
        fbFFHWO := GVL.fbFastFaultOutput2);

    IF fbAT2L0_states[iIndex].enumGet = ENUM_EpicsInOut.UNKNOWN THEN
        stFilter.fTransmission := 0.0;
    ELSIF fbAT2L0_states[iIndex].enumGet = ENUM_EpicsInOut.OUT OR stFilter.sFilterMaterial = '' THEN
        stFilter.fTransmission := 1.0;
    ELSE
        fbAtomicMass(sName:=stFilter.sFilterMaterial, fValue=>fFilterAtomicMass);
        fbAttenuatorElementDensity(sName:=stFilter.sFilterMaterial, fDensity=>fFilterDensity);

        fAbsorptionConstant := F_CalculateAbsorptionConstant(
            sElement:=stFilter.sFilterMaterial,
            fEnergyEV:=PMPS_GVL.stCurrentBeamParameters.neV,
            fDensity_gm3:=fFilterDensity,
            fAtomicWeight:=fFilterAtomicMass,
            bError=>bError,
        );
        stFilter.fTransmission := F_CalculateTransmission(
            fAbsorptionConstant:=fAbsorptionConstant,
            fThickness_in_m:=stFilter.fFilterThickness_um * 1.0E-6
        );
    END_IF

    fTransmission := fTransmission * stFilter.fTransmission;
END_FOR

IF fbAT2L0_states[1].enumGet = ENUM_EpicsInOut.IN THEN
    (* Inspection mirror blocks the beam *)
    GVL.rCurTrans[PMPS.L_Attenuators.AT2L0].nTran := 0.0;
    (* TODO fast fault as well *)
ELSE
    GVL.rCurTrans[PMPS.L_Attenuators.AT2L0].nTran := LREAL_TO_REAL(fTransmission);
END_IF

iIndex := 0;

nM1CoilA := UINT_TO_INT(nM1CoilARaw);
nM1CoilB := UINT_TO_INT(nM1CoilBRaw);
//nM1Current := ABS(nM1CoilA) + ABS(nM1CoilB);
nM2CoilA := UINT_TO_INT(nM2CoilARaw);
nM2CoilB := UINT_TO_INT(nM2CoilBRaw);
//nM2Current := ABS(nM2CoilA) + ABS(nM2CoilB);
nM3CoilA := UINT_TO_INT(nM3CoilARaw);
nM3CoilB := UINT_TO_INT(nM3CoilBRaw);
//nM3Current := ABS(nM3CoilA) + ABS(nM3CoilB);
nM4CoilA := UINT_TO_INT(nM4CoilARaw);
nM4CoilB := UINT_TO_INT(nM4CoilBRaw);
//nM4Current := ABS(nM4CoilA) + ABS(nM4CoilB);
nM5CoilA := UINT_TO_INT(nM5CoilARaw);
nM5CoilB := UINT_TO_INT(nM5CoilBRaw);
//nM5Current := ABS(nM5CoilA) + ABS(nM5CoilB);
nM5CoilA := UINT_TO_INT(nM5CoilARaw);
nM5CoilB := UINT_TO_INT(nM5CoilBRaw);
//nM5Current := ABS(nM5CoilA) + ABS(nM5CoilB);
nM6CoilA := UINT_TO_INT(nM6CoilARaw);
nM6CoilB := UINT_TO_INT(nM6CoilBRaw);
//nM6Current := ABS(nM6CoilA) + ABS(nM6CoilB);
nM7CoilA := UINT_TO_INT(nM7CoilARaw);
nM7CoilB := UINT_TO_INT(nM7CoilBRaw);
//nM7Current := ABS(nM7CoilA) + ABS(nM7CoilB);
nM8CoilA := UINT_TO_INT(nM8CoilARaw);
nM8CoilB := UINT_TO_INT(nM8CoilBRaw);
//nM8Current := ABS(nM9CoilA) + ABS(nM9CoilB);
nM9CoilA := UINT_TO_INT(nM9CoilARaw);
nM9CoilB := UINT_TO_INT(nM9CoilBRaw);
//nM9Current := ABS(nM9CoilA) + ABS(nM9CoilB);
nM10CoilA := UINT_TO_INT(nM10CoilARaw);
nM10CoilB := UINT_TO_INT(nM10CoilBRaw);
//nM10Current := ABS(nM10CoilA) + ABS(nM10CoilB);
nM11CoilA := UINT_TO_INT(nM11CoilARaw);
nM11CoilB := UINT_TO_INT(nM11CoilBRaw);
//nM11Current := ABS(nM11CoilA) + ABS(nM11CoilB);
nM12CoilA := UINT_TO_INT(nM12CoilARaw);
nM12CoilB := UINT_TO_INT(nM12CoilBRaw);
//nM12Current := ABS(nM12CoilA) + ABS(nM12CoilB);
nM13CoilA := UINT_TO_INT(nM13CoilARaw);
nM13CoilB := UINT_TO_INT(nM13CoilBRaw);
//nM13Current := ABS(nM13CoilA) + ABS(nM13CoilB);
nM14CoilA := UINT_TO_INT(nM14CoilARaw);
nM14CoilB := UINT_TO_INT(nM14CoilBRaw);
//nM14Current := ABS(nM14CoilA) + ABS(nM14CoilB);
nM15CoilA := UINT_TO_INT(nM15CoilARaw);
nM15CoilB := UINT_TO_INT(nM15CoilBRaw);
//nM15Current := ABS(nM15CoilA) + ABS(nM15CoilB);
nM16CoilA := UINT_TO_INT(nM16CoilARaw);
nM16CoilB := UINT_TO_INT(nM16CoilBRaw);
//nM16Current := ABS(nM16CoilA) + ABS(nM16CoilB);
nM17CoilA := UINT_TO_INT(nM17CoilARaw);
nM17CoilB := UINT_TO_INT(nM17CoilBRaw);
//nM17Current := ABS(nM17CoilA) + ABS(nM17CoilB);
nM18CoilA := UINT_TO_INT(nM18CoilARaw);
nM18CoilB := UINT_TO_INT(nM18CoilBRaw);
//nM18Current := ABS(nM2CoilA) + ABS(nM18CoilB);
nM19CoilA := UINT_TO_INT(nM19CoilARaw);
nM19CoilB := UINT_TO_INT(nM19CoilBRaw);
//nM19Current := ABS(nM2CoilA) + ABS(nM2CoilB);

END_PROGRAM
Related:

PRG_IM1L0_XTES

PROGRAM PRG_IM1L0_XTES
VAR
    {attribute 'pytmc' := '
        pv: IM1L0:XTES
        io: io
    '}
    {attribute 'TcLinkTo' := '.bZoomEndFwd := TIIB[IM1L0-EL1088]^Channel 1^Input;
                              .bZoomEndBwd := TIIB[IM1L0-EL1088]^Channel 2^Input;
                              .bFocusEndFwd := TIIB[IM1L0-EL1088]^Channel 3^Input;
                              .bFocusEndBwd := TIIB[IM1L0-EL1088]^Channel 4^Input;
                              .fbOpal.bOpalPower := TIIB[IM1L0-EL2004]^Channel 2^Output;
                              .fbLED.bLedPower := TIIB[IM1L0-EL2004]^Channel 3^Output'}
    fbIM1L0: FB_XPIM;
    {attribute 'pytmc' := '
        pv: IM1L0:XTES:FLOW_OK
        field: ZNAM LOW
        field: ONAM OK
    '}
    {attribute 'TcLinkTo' := 'TIIB[IM1L0-EL7342]^DCM Status Channel 1^Status^Digital input 1'}
    bIM1L0FlowOk AT %I*: BOOL;
    {attribute 'TcLinkTo' := '.Status := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Status;
                              .D[0] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 0;
                              .D[1] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 1;
                              .D[2] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 2;
                              .D[3] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 3;
                              .D[4] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 4;
                              .D[5] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 5;
                              .D[6] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 6;
                              .D[7] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 7;
                              .D[8] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 8;
                              .D[9] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 9;
                              .D[10] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 10;
                              .D[11] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 11;
                              .D[12] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 12;
                              .D[13] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 13;
                              .D[14] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 14;
                              .D[15] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 15;
                              .D[16] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 16;
                              .D[17] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 17;
                              .D[18] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 18;
                              .D[19] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 19;
                              .D[20] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 20;
                              .D[21] := TIIB[IM1L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 21'}
    stEL6In AT %I*: EL6InData22b;
    {attribute 'TcLinkTo' := '.Ctrl := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Ctrl;
                              .D[0] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 0;
                              .D[1] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 1;
                              .D[2] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 2;
                              .D[3] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 3;
                              .D[4] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 4;
                              .D[5] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 5;
                              .D[6] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 6;
                              .D[7] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 7;
                              .D[8] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 8;
                              .D[9] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 9;
                              .D[10] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 10;
                              .D[11] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 11;
                              .D[12] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 12;
                              .D[13] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 13;
                              .D[14] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 14;
                              .D[15] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 15;
                              .D[16] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 16;
                              .D[17] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 17;
                              .D[18] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 18;
                              .D[19] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 19;
                              .D[20] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 20;
                              .D[21] := TIIB[IM1L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 21'}
    stEL6Out AT %Q*: EL6OutData22b;

    bInit: BOOL := TRUE;
END_VAR
IF bInit THEN
    fbIM1L0.nTransitionAssertionID := 16#2100;
    fbIM1L0.nUnknownAssertionID := 16#2109;

    fbIM1L0.stOut.fPosition := 0;
    fbIM1L0.stOut.bUseRawCounts := FALSE;
    fbIM1L0.stOut.nRequestAssertionID := 16#2101;
    fbIM1L0.stOut.stBeamParams := PMPS_GVL.cstFullBeam;
    fbIM1L0.stOut.bValid := TRUE;

    fbIM1L0.stYag.fPosition := -86.65;
    fbIM1L0.stYag.bUseRawCounts := FALSE;
    fbIM1L0.stYag.nRequestAssertionID := 16#2102;
    fbIM1L0.stYag.stBeamParams := PMPS_GVL.cstFullBeam;
    fbIM1L0.stYag.stBeamParams.neVRange := F_eVExcludeRange(2100, 3800) AND F_eVExcludeRange(16900, 24000);
    fbIM1L0.stYag.bValid := TRUE;

    fbIM1L0.stDiamond.fPosition := -56.65;
    fbIM1L0.stDiamond.bUseRawCounts := FALSE;
    fbIM1L0.stDiamond.nRequestAssertionID := 16#2103;
    fbIM1L0.stDiamond.stBeamParams := PMPS_GVL.cstFullBeam;
    fbIM1L0.stDiamond.bValid := TRUE;

    fbIM1L0.stReticle.fPosition := -26.65;
    fbIM1L0.stReticle.bUseRawCounts := FALSE;
    fbIM1L0.stReticle.nRequestAssertionID := 16#2104;
    fbIM1L0.stReticle.stBeamParams := PMPS_GVL.cst0RateBeam;
    fbIM1L0.stReticle.bValid := TRUE;

    bInit := FALSE;
END_IF

fbIM1L0(
    fbArbiter := GVL.fbArbiter,
    fbFFHWO := GVL.fbFastFaultOutput1,
    stYStage := Main.M20,
    stZoomStage := Main.M21,
    stFocusStage := Main.M22,
    stEl6In := stEL6In,
    stEl6Out := stEl6Out);

END_PROGRAM
Related:

PRG_IM1L1_PPM

PROGRAM PRG_IM1L1_PPM
VAR
    {attribute 'pytmc' := '
        pv: IM1L1:PPM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbGige.iIlluminatorINT := TIIB[IM1L1-EL4004]^AO Outputs Channel 1^Analog output;
                              .fbGige.bGigePower := TIIB[IM1L1-EL2004]^Channel 2^Output;
                              .fbPowerMeter.iVoltageINT := TIIB[IM1L1-EL3062]^AI Standard Channel 1^Value;
                              .fbPowerMeter.fbThermoCouple.bError := TIIB[IM1L1-EL3314]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbThermoCouple.bUnderrange := TIIB[IM1L1-EL3314]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbThermoCouple.bOverrange := TIIB[IM1L1-EL3314]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbThermoCouple.iRaw := TIIB[IM1L1-EL3314]^TC Inputs Channel 1^Value;
                              .fbYagThermoCouple.bError := TIIB[IM1L1-EL3314]^TC Inputs Channel 2^Status^Error;
                              .fbYagThermoCouple.bUnderrange := TIIB[IM1L1-EL3314]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagThermoCouple.bOverrange := TIIB[IM1L1-EL3314]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagThermoCouple.iRaw := TIIB[IM1L1-EL3314]^TC Inputs Channel 2^Value'}
    fbIM1L1: FB_PPM;

    bInit: BOOL := TRUE;
END_VAR
IF bInit THEN
    fbIM1L1.nTransitionAssertionID := 16#2110;
    fbIM1L1.nUnknownAssertionID := 16#2119;

    fbIM1L1.stOut.fPosition := -11;
    fbIM1L1.stOut.bUseRawCounts := FALSE;
    fbIM1L1.stOut.nRequestAssertionID := 16#2111;
    fbIM1L1.stOut.stBeamParams := PMPS_GVL.cstFullBeam;
    fbIM1L1.stOut.bValid := TRUE;

    fbIM1L1.stPower.fPosition := -47.59;
    fbIM1L1.stPower.bUseRawCounts := FALSE;
    fbIM1L1.stPower.nRequestAssertionID := 16#2112;
    fbIM1L1.stPower.stBeamParams := PMPS_GVL.cstFullBeam;
    // For now, leave this restriction out (doesn't even take beam yet)
    // fbIM1L1.stPower.stBeamParams := F_eVExcludeRange(1, 5000);
    fbIM1L1.stPower.bValid := TRUE;

    fbIM1L1.stYag1.fPosition := -71.69;
    fbIM1L1.stYag1.bUseRawCounts := FALSE;
    fbIM1L1.stYag1.nRequestAssertionID := 16#2113;
    fbIM1L1.stYag1.stBeamParams := PMPS_GVL.cstFullBeam;
    // For now, do not have restrictions on this YAG. Eventually we want to add exclusion ranges where we need to limit transmission to 0.1 (10%) within those ranges. Currently we do not have transmission control via PMPS on LFE.
    // fbIM1L1.stYag1.stBeamParams.neVRange := F_eVExcludeRange(2100, 3800) AND F_eVExcludeRange(16900, 24000);
    fbIM1L1.stYag1.bValid := TRUE;

    fbIM1L1.stYag2.fPosition := -97.70;
    fbIM1L1.stYag2.bUseRawCounts := FALSE;
    fbIM1L1.stYag2.nRequestAssertionID := 16#2114;
    fbIM1L1.stYag2.stBeamParams := PMPS_GVL.cstFullBeam;
    // For now, do not have restrictions on this YAG. Eventually we want to add exclusion ranges where we need to limit transmission to 0.1 (10%) within those ranges. Currently we do not have transmission control via PMPS on LFE.
    // fbIM1L1.stYag2.stBeamParams.neVRange := F_eVExcludeRange(2100, 3800) AND F_eVExcludeRange(16900, 24000);
    fbIM1L1.stYag2.bValid := TRUE;

    bInit := FALSE;
END_IF

fbIM1L1(
    fbArbiter := GVL.fbArbiter,
    fbFFHWO := GVL.fbFastFaultOutput1,
    stYStage := Main.M23);

END_PROGRAM
Related:

PRG_IM2L0_XTES

PROGRAM PRG_IM2L0_XTES
VAR
    {attribute 'pytmc' := '
        pv: IM2L0:XTES
        io: io
    '}
    {attribute 'TcLinkTo' := '.bZoomEndFwd := TIIB[IM2L0-EL1088]^Channel 1^Input;
                              .bZoomEndBwd := TIIB[IM2L0-EL1088]^Channel 2^Input;
                              .bFocusEndFwd := TIIB[IM2L0-EL1088]^Channel 3^Input;
                              .bFocusEndBwd := TIIB[IM2L0-EL1088]^Channel 4^Input;
                              .fbOpal.bOpalPower := TIIB[IM2L0-EL2004]^Channel 2^Output;
                              .fbLED.bLedPower := TIIB[IM2L0-EL2004]^Channel 3^Output'}
    fbIM2L0: FB_XPIM;
    {attribute 'TcLinkTo' := '.Status := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Status;
                              .D[0] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 0;
                              .D[1] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 1;
                              .D[2] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 2;
                              .D[3] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 3;
                              .D[4] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 4;
                              .D[5] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 5;
                              .D[6] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 6;
                              .D[7] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 7;
                              .D[8] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 8;
                              .D[9] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 9;
                              .D[10] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 10;
                              .D[11] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 11;
                              .D[12] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 12;
                              .D[13] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 13;
                              .D[14] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 14;
                              .D[15] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 15;
                              .D[16] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 16;
                              .D[17] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 17;
                              .D[18] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 18;
                              .D[19] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 19;
                              .D[20] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 20;
                              .D[21] := TIIB[IM2L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 21'}
    stEL6In AT %I*: EL6InData22b;
    {attribute 'TcLinkTo' := '.Ctrl := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Ctrl;
                              .D[0] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 0;
                              .D[1] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 1;
                              .D[2] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 2;
                              .D[3] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 3;
                              .D[4] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 4;
                              .D[5] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 5;
                              .D[6] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 6;
                              .D[7] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 7;
                              .D[8] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 8;
                              .D[9] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 9;
                              .D[10] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 10;
                              .D[11] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 11;
                              .D[12] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 12;
                              .D[13] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 13;
                              .D[14] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 14;
                              .D[15] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 15;
                              .D[16] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 16;
                              .D[17] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 17;
                              .D[18] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 18;
                              .D[19] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 19;
                              .D[20] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 20;
                              .D[21] := TIIB[IM2L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 21'}
    stEL6Out AT %Q*: EL6OutData22b;

    bInit: BOOL := TRUE;

    {attribute 'TcLinkTo' := 'TIIB[IM2L0-EL7041]^STM Status^Status^Digital input 1'}
    bDefectiveLimitSwitch AT %I*: BOOL;
END_VAR
IF bInit THEN
    fbIM2L0.nTransitionAssertionID := 16#2200;
    fbIM2L0.nUnknownAssertionID := 16#2209;

    fbIM2L0.stOut.fPosition := 0;
    fbIM2L0.stOut.bUseRawCounts := FALSE;
    fbIM2L0.stOut.nRequestAssertionID := 16#2201;
    fbIM2L0.stOut.stBeamParams := PMPS_GVL.cstFullBeam;
    fbIM2L0.stOut.bValid := TRUE;

    fbIM2L0.stYag.fPosition := -87.65;
    fbIM2L0.stYag.bUseRawCounts := FALSE;
    fbIM2L0.stYag.nRequestAssertionID := 16#2202;
    fbIM2L0.stYag.stBeamParams := PMPS_GVL.cstFullBeam;
    // For now, do not have restrictions on this YAG. Eventually we want to add exclusion ranges where we need to limit transmission to 0.1 (10%) within those ranges. Currently we do not have transmission control via PMPS on LFE.
    // fbIM2L0.stYag.stBeamParams.neVRange := F_eVExcludeRange(2100, 3800) AND F_eVExcludeRange(16900, 24000);
    fbIM2L0.stYag.bValid := TRUE;

    fbIM2L0.stDiamond.fPosition := -57.65;
    fbIM2L0.stDiamond.bUseRawCounts := FALSE;
    fbIM2L0.stDiamond.nRequestAssertionID := 16#2203;
    fbIM2L0.stDiamond.stBeamParams := PMPS_GVL.cstFullBeam;
    fbIM2L0.stDiamond.bValid := TRUE;

    fbIM2L0.stReticle.fPosition := -27.65;
    fbIM2L0.stReticle.bUseRawCounts := FALSE;
    fbIM2L0.stReticle.nRequestAssertionID := 16#2204;
    fbIM2L0.stReticle.stBeamParams := PMPS_GVL.cst0RateBeam;
    fbIM2L0.stReticle.bValid := TRUE;

    bInit := FALSE;
END_IF

Main.M24.bLimitForwardEnable := bDefectiveLimitSwitch OR (Main.M24.stAxisStatus.fActPosition < 0);

fbIM2L0(
    fbArbiter := GVL.fbArbiter,
    fbFFHWO := GVL.fbFastFaultOutput1,
    stYStage := Main.M24,
    stZoomStage := Main.M25,
    stFocusStage := Main.M26,
    stEl6In := stEL6In,
    stEl6Out := stEl6Out);

END_PROGRAM
Related:

PRG_IM3L0_PPM

PROGRAM PRG_IM3L0_PPM
VAR
    {attribute 'pytmc' := '
        pv: IM3L0:PPM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbGige.iIlluminatorINT := TIIB[IM3L0-EL4004]^AO Outputs Channel 1^Analog output;
                              .fbGige.bGigePower := TIIB[IM3L0-EL2004]^Channel 2^Output;
                              .fbPowerMeter.iVoltageINT := TIIB[IM3L0-EL3062]^AI Standard Channel 1^Value;
                              .fbPowerMeter.fbThermoCouple.bError := TIIB[IM3L0-EL3314]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbThermoCouple.bUnderrange := TIIB[IM3L0-EL3314]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbThermoCouple.bOverrange := TIIB[IM3L0-EL3314]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbThermoCouple.iRaw := TIIB[IM3L0-EL3314]^TC Inputs Channel 1^Value;
                              .fbYagThermoCouple.bError := TIIB[IM3L0-EL3314]^TC Inputs Channel 2^Status^Error;
                              .fbYagThermoCouple.bUnderrange := TIIB[IM3L0-EL3314]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagThermoCouple.bOverrange := TIIB[IM3L0-EL3314]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagThermoCouple.iRaw := TIIB[IM3L0-EL3314]^TC Inputs Channel 2^Value'}
    fbIM3L0: FB_PPM;

    bInit: BOOL := TRUE;
END_VAR
IF bInit THEN
    fbIM3L0.nTransitionAssertionID := 16#2300;
    fbIM3L0.nUnknownAssertionID := 16#2309;

    fbIM3L0.stOut.fPosition := -8.40;
    fbIM3L0.stOut.bUseRawCounts := FALSE;
    fbIM3L0.stOut.nRequestAssertionID := 16#2301;
    fbIM3L0.stOut.stBeamParams := PMPS_GVL.cstFullBeam;
    fbIM3L0.stOut.bValid := TRUE;

    fbIM3L0.stPower.fPosition := -47.40;
    fbIM3L0.stPower.bUseRawCounts := FALSE;
    fbIM3L0.stPower.nRequestAssertionID := 16#2302;
    fbIM3L0.stPower.stBeamParams := PMPS_GVL.cstFullBeam;
    fbIM3L0.stPower.stBeamParams.neVRange := F_eVExcludeRange(0, 5000);
    fbIM3L0.stPower.bValid := TRUE;

    fbIM3L0.stYag1.fPosition := -71.50;
    fbIM3L0.stYag1.bUseRawCounts := FALSE;
    fbIM3L0.stYag1.nRequestAssertionID := 16#2303;
    fbIM3L0.stYag1.stBeamParams := PMPS_GVL.cstFullBeam;
    // For now, do not have restrictions on this YAG. Eventually we want to add exclusion ranges where we need to limit transmission to 0.1 (10%) within those ranges. Currently we do not have transmission control via PMPS on LFE.
    // fbIM3L0.stYag1.stBeamParams.neVRange := F_eVExcludeRange(2100, 3800) AND F_eVExcludeRange(16900, 24000);
    fbIM3L0.stYag1.bValid := TRUE;

    fbIM3L0.stYag2.fPosition := -97.51;
    fbIM3L0.stYag2.bUseRawCounts := FALSE;
    fbIM3L0.stYag2.nRequestAssertionID := 16#2304;
    fbIM3L0.stYag2.stBeamParams := PMPS_GVL.cstFullBeam;
    // For now, do not have restrictions on this YAG. Eventually we want to add exclusion ranges where we need to limit transmission to 0.1 (10%) within those ranges. Currently we do not have transmission control via PMPS on LFE.
    // fbIM3L0.stYag2.stBeamParams.neVRange := F_eVExcludeRange(2100, 3800) AND F_eVExcludeRange(16900, 24000);
    fbIM3L0.stYag2.bValid := TRUE;

    bInit := FALSE;
END_IF

fbIM3L0(
    fbArbiter := GVL.fbArbiter,
    fbFFHWO := GVL.fbFastFaultOutput1,
    stYStage := Main.M27);

END_PROGRAM
Related:

PRG_IM4L0_XTES

PROGRAM PRG_IM4L0_XTES
VAR
    {attribute 'pytmc' := '
        pv: IM4L0:XTES
        io: io
    '}
    {attribute 'TcLinkTo' := '.bZoomEndFwd := TIIB[IM4L0-EL1088]^Channel 1^Input;
                              .bZoomEndBwd := TIIB[IM4L0-EL1088]^Channel 2^Input;
                              .bFocusEndFwd := TIIB[IM4L0-EL1088]^Channel 3^Input;
                              .bFocusEndBwd := TIIB[IM4L0-EL1088]^Channel 4^Input;
                              .fbOpal.bOpalPower := TIIB[IM4L0-EL2004]^Channel 2^Output;
                              .fbLED.bLedPower := TIIB[IM4L0-EL2004]^Channel 3^Output'}
    fbIM4L0: FB_XPIM;
    {attribute 'TcLinkTo' := '.Status := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Status;
                              .D[0] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 0;
                              .D[1] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 1;
                              .D[2] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 2;
                              .D[3] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 3;
                              .D[4] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 4;
                              .D[5] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 5;
                              .D[6] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 6;
                              .D[7] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 7;
                              .D[8] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 8;
                              .D[9] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 9;
                              .D[10] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 10;
                              .D[11] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 11;
                              .D[12] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 12;
                              .D[13] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 13;
                              .D[14] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 14;
                              .D[15] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 15;
                              .D[16] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 16;
                              .D[17] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 17;
                              .D[18] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 18;
                              .D[19] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 19;
                              .D[20] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 20;
                              .D[21] := TIIB[IM4L0-EL6002]^COM TxPDO-Map Inputs Channel 1^Data In 21'}
    stEL6In AT %I*: EL6InData22b;
    {attribute 'TcLinkTo' := '.Ctrl := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Ctrl;
                              .D[0] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 0;
                              .D[1] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 1;
                              .D[2] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 2;
                              .D[3] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 3;
                              .D[4] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 4;
                              .D[5] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 5;
                              .D[6] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 6;
                              .D[7] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 7;
                              .D[8] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 8;
                              .D[9] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 9;
                              .D[10] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 10;
                              .D[11] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 11;
                              .D[12] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 12;
                              .D[13] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 13;
                              .D[14] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 14;
                              .D[15] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 15;
                              .D[16] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 16;
                              .D[17] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 17;
                              .D[18] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 18;
                              .D[19] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 19;
                              .D[20] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 20;
                              .D[21] := TIIB[IM4L0-EL6002]^COM RxPDO-Map Outputs Channel 1^Data Out 21'}
    stEL6Out AT %Q*: EL6OutData22b;

     {attribute 'pytmc' := 'pv: IM4L0:SCRP:LED:01:PWR
                        io: io
                        field: ZNAM OFF
                        field: ONAM ON
     '}

     {attribute 'TcLinkTo' := 'TIIB[IM4L0-EL2004]^Channel 4^Output'}
    bIM4L0_SCRP_LED_01 AT %Q*: BOOL;

    bInit: BOOL := TRUE;
END_VAR
IF bInit THEN
    fbIM4L0.nTransitionAssertionID := 16#2400;
    fbIM4L0.nUnknownAssertionID := 16#2409;

    fbIM4L0.stOut.fPosition := 0;
    fbIM4L0.stOut.bUseRawCounts := FALSE;
    fbIM4L0.stOut.nRequestAssertionID := 16#2401;
    fbIM4L0.stOut.stBeamParams := PMPS_GVL.cstFullBeam;
    fbIM4L0.stOut.bValid := TRUE;

    fbIM4L0.stYag.fPosition := -86.65;
    fbIM4L0.stYag.bUseRawCounts := FALSE;
    fbIM4L0.stYag.nRequestAssertionID := 16#2402;
    fbIM4L0.stYag.stBeamParams := PMPS_GVL.cstFullBeam;
    // For now, do not have restrictions on this YAG. Eventually we want to add exclusion ranges where we need to limit transmission to 0.1 (10%) within those ranges. Currently we do not have transmission control via PMPS on LFE.
    // fbIM4L0.stYag.stBeamParams.neVRange := F_eVExcludeRange(2100, 3800) AND F_eVExcludeRange(16900, 24000);
    fbIM4L0.stYag.bValid := TRUE;

    fbIM4L0.stDiamond.fPosition := -56.65;
    fbIM4L0.stDiamond.bUseRawCounts := FALSE;
    fbIM4L0.stDiamond.nRequestAssertionID := 16#2403;
    fbIM4L0.stDiamond.stBeamParams := PMPS_GVL.cstFullBeam;
    fbIM4L0.stDiamond.bValid := TRUE;

    fbIM4L0.stReticle.fPosition := -26.65;
    fbIM4L0.stReticle.bUseRawCounts := FALSE;
    fbIM4L0.stReticle.nRequestAssertionID := 16#2404;
    fbIM4L0.stReticle.stBeamParams := PMPS_GVL.cst0RateBeam;
    fbIM4L0.stReticle.bValid := TRUE;

    bInit := FALSE;
END_IF

fbIM4L0(
    fbArbiter := GVL.fbArbiter,
    fbFFHWO := GVL.fbFastFaultOutput1,
    stYStage := Main.M28,
    stZoomStage := Main.M29,
    stFocusStage := Main.M30,
    stEl6In := stEL6In,
    stEl6Out := stEl6Out);

END_PROGRAM
Related:

PRG_PF1L0_WFS

PROGRAM PRG_PF1L0_WFS
VAR
    {attribute 'pytmc' := '
        pv: PF1L0:WFS
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbThermoCouple1.bError := TIIB[PF1L0-EL3314]^TC Inputs Channel 1^Status^Error;
                              .fbThermoCouple1.bUnderrange := TIIB[PF1L0-EL3314]^TC Inputs Channel 1^Status^Underrange;
                              .fbThermoCouple1.bOverrange := TIIB[PF1L0-EL3314]^TC Inputs Channel 1^Status^Overrange;
                              .fbThermoCouple1.iRaw := TIIB[PF1L0-EL3314]^TC Inputs Channel 1^Value;
                              .fbThermoCouple2.bError := TIIB[PF1L0-EL3314]^TC Inputs Channel 2^Status^Error;
                              .fbThermoCouple2.bUnderrange := TIIB[PF1L0-EL3314]^TC Inputs Channel 2^Status^Underrange;
                              .fbThermoCouple2.bOverrange := TIIB[PF1L0-EL3314]^TC Inputs Channel 2^Status^Overrange;
                              .fbThermoCouple2.iRaw := TIIB[PF1L0-EL3314]^TC Inputs Channel 2^Value'}
    fbPF1L0: FB_WFS;
    stSiBP: ST_BeamParams := PMPS_GVL.cstFullBeam;
    stFoilBP: ST_BeamParams := PMPS_GVL.cstFullBeam;

    bInit: BOOL := TRUE;
END_VAR
IF bInit THEN
    // Avoid damage peak between 3.2 keV and 1.6 keV
    stSiBP.neVRange := F_evExcludeRange(1600, 3200);
    // Drop transmission to 20%
    stSiBP.nTran := 0.2;

    fbPF1L0.nTransitionAssertionID := 16#3100;
    fbPF1L0.nUnknownAssertionID := 16#3109;

    fbPF1L0.stOut.fPosition := -13;
    fbPF1L0.stOut.bUseRawCounts := FALSE;
    fbPF1L0.stOut.nRequestAssertionID := 16#3101;
    fbPF1L0.stOut.stBeamParams := PMPS_GVL.cstFullBeam;
    fbPF1L0.stOut.bValid := TRUE;

    fbPF1L0.stTarget1.fPosition := -93.77;
    fbPF1L0.stTarget1.bUseRawCounts := FALSE;
    fbPF1L0.stTarget1.nRequestAssertionID := 16#3102;
    fbPF1L0.stTarget1.stBeamParams := stSiBP;
    fbPF1L0.stTarget1.bValid := TRUE;

    fbPF1L0.stTarget2.fPosition := -79.402;
    fbPF1L0.stTarget2.bUseRawCounts := FALSE;
    fbPF1L0.stTarget2.nRequestAssertionID := 16#3103;
    fbPF1L0.stTarget2.stBeamParams := stSiBP;
    fbPF1L0.stTarget2.bValid := TRUE;

    fbPF1L0.stTarget3.fPosition := -65.028;
    fbPF1L0.stTarget3.bUseRawCounts := FALSE;
    fbPF1L0.stTarget3.nRequestAssertionID := 16#3104;
    fbPF1L0.stTarget3.stBeamParams := stSiBP;
    fbPF1L0.stTarget3.bValid := TRUE;

    fbPF1L0.stTarget4.fPosition := -50.652;
    fbPF1L0.stTarget4.bUseRawCounts := FALSE;
    fbPF1L0.stTarget4.nRequestAssertionID := 16#3105;
    fbPF1L0.stTarget4.stBeamParams := stSiBP;
    fbPF1L0.stTarget4.bValid := TRUE;

    fbPF1L0.stTarget5.fPosition := -36.277;
    fbPF1L0.stTarget5.bUseRawCounts := FALSE;
    fbPF1L0.stTarget5.nRequestAssertionID := 16#3106;
    fbPF1L0.stTarget5.stBeamParams := stSiBP;
    fbPF1L0.stTarget5.bValid := TRUE;

    bInit := FALSE;
END_IF

fbPF1L0(
    fbArbiter := GVL.fbArbiter,
    fbFFHWO := GVL.fbFastFaultOutput1,
    stYStage := Main.M31,
    stZStage := Main.M32);

END_PROGRAM
Related:

PRG_RTDSL0

PROGRAM PRG_RTDSL0
VAR

    fbRTDSL0_Diode_MMS_01: FB_MotionStage;

    bInit: BOOL := TRUE;
END_VAR
// Placeholder, standard simulated motion for all axes
//fbMotion1(stMotionStage := Main.M33);
//fbMotion2(stMotionStage := Main.M34);
//fbMotion3(stMotionStage := Main.M35);
//fbMotion4(stMotionStage := Main.M36);
//fbMotion5(stMotionStage := Main.M37);
//fbMotion6(stMotionStage := Main.M38);
//fbMotion7(stMotionStage := Main.M39);

//Pneumatic actuators - OTR filters

RTDSL0_MPA_01(
    ibInsertOK:= TRUE,
    ibRetractOK:= TRUE ,
    ibPMPS_OK:= TRUE ,
    ibOverrideInterlock:= ,
    q_stAct=> ,
    xMPS_OK=> ,
    xDone=> ,
    i_xReset := ,
    io_fbFFHWO := GVL.fbFastFaultOutput1,
    bEnableFF := TRUE,
);

RTDSL0_MPA_02(
    ibInsertOK:= TRUE,
    ibRetractOK:= TRUE ,
    ibPMPS_OK:= TRUE ,
    ibOverrideInterlock:= ,
    q_stAct=> ,
    xMPS_OK=> ,
    xDone=> ,
    i_xReset := ,
    io_fbFFHWO := GVL.fbFastFaultOutput1,
    bEnableFF := TRUE,
);

RTDSL0_MPA_03(
    ibInsertOK:= TRUE,
    ibRetractOK:= TRUE ,
    ibPMPS_OK:= TRUE ,
    ibOverrideInterlock:= ,
    q_stAct=> ,
    xMPS_OK=> ,
    xDone=> ,
    i_xReset := ,
    io_fbFFHWO := GVL.fbFastFaultOutput1,
    bEnableFF := FALSE,
);
//  init the motion stages parameters
IF ( bInit) THEN
    Main.M33.bHardwareEnable := TRUE;
    Main.M33.bPowerSelf :=TRUE;
    Main.M33.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    (* uncomment when mccallister goes from RTDSK0 -> RTDSL0
    Main.M34.bHardwareEnable := TRUE;
    Main.M34.bPowerSelf :=TRUE;
    Main.M34.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;

    Main.M35.bHardwareEnable := TRUE;
    Main.M35.bPowerSelf :=TRUE;
    Main.M35.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;

    Main.M36.bHardwareEnable := TRUE;
    Main.M36.bPowerSelf :=TRUE;
    Main.M36.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;

    //LDM motor
    Main.M37.bHardwareEnable := TRUE;
    Main.M37.bPowerSelf :=TRUE;
    Main.M37.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    *)
    Main.M33.nHomingMode := ENUM_EpicsHomeCmd.HIGH_LIMIT;
    //uncomment when mccallister gets moved RTDSK0->RTDSL0
    //Main.M34.nHomingMode := ENUM_EpicsHomeCmd.HIGH_LIMIT;
    //Main.M35.nHomingMode := ENUM_EpicsHomeCmd.HIGH_LIMIT;
    //Main.M36.nHomingMode := ENUM_EpicsHomeCmd.HIGH_LIMIT;
    Main.M37.nHomingMode := ENUM_EpicsHomeCmd.HIGH_LIMIT;

        bInit := FALSE;

END_IF


fbRTDSL0_Diode_MMS_01 (stMotionStage := Main.M33);
//uncomment when mccallister stage RTDSK0 -> RTDSL0
//fbRTDSL0_SCRP_MMS_01 (stMotionStage := Main.M34);
//fbRTDSL0_SCRP_MMS_02 (stMotionStage := Main.M35);
//fbRTDSL0_SCRP_MMS_03 (stMotionStage := Main.M36);
//fbRTDSL0_LDM_MMS_01 (stMotionStage := Main.M37);
//uncomment when mccallister stage RTDSK0->RTDSL0
//fbRTDSK0_SCRP_LED_01 (enumXPIM := Main.LED1);

END_PROGRAM
Related:

PRG_SL1L0_POWER

PROGRAM PRG_SL1L0_POWER
VAR // fix linking to rtd in the following order Bottom - South - TOP - NORTH
    {attribute 'pytmc' := '
        pv: SL1L0:POWER
        io: io
    '}
    {attribute 'TcLinkTo' := '.RTD_Bottom_1.iRaw := TIIB[SL1L0-EL3202-E8]^RTD Inputs Channel 1^Value;
                              .RTD_Bottom_1.bError := TIIB[SL1L0-EL3202-E8]^RTD Inputs Channel 1^Status^Error;
                              .RTD_Bottom_1.bUnderrange := TIIB[SL1L0-EL3202-E8]^RTD Inputs Channel 1^Status^Underrange;
                              .RTD_Bottom_1.bOverrange := TIIB[SL1L0-EL3202-E8]^RTD Inputs Channel 1^Status^Overrange;
                              .RTD_Bottom_2.iRaw := TIIB[SL1L0-EL3202-E8]^RTD Inputs Channel 2^Value;
                              .RTD_Bottom_2.bError := TIIB[SL1L0-EL3202-E8]^RTD Inputs Channel 2^Status^Error;
                              .RTD_Bottom_2.bUnderrange := TIIB[SL1L0-EL3202-E8]^RTD Inputs Channel 2^Status^Underrange;
                              .RTD_Bottom_2.bOverrange := TIIB[SL1L0-EL3202-E8]^RTD Inputs Channel 2^Status^Overrange;
                              .RTD_South_1.iRaw := TIIB[SL1L0-EL3202-E9]^RTD Inputs Channel 1^Value;
                              .RTD_South_1.bError := TIIB[SL1L0-EL3202-E9]^RTD Inputs Channel 1^Status^Error;
                              .RTD_South_1.bUnderrange := TIIB[SL1L0-EL3202-E9]^RTD Inputs Channel 1^Status^Underrange;
                              .RTD_South_1.bOverrange := TIIB[SL1L0-EL3202-E9]^RTD Inputs Channel 1^Status^Overrange;
                              .RTD_South_2.iRaw := TIIB[SL1L0-EL3202-E9]^RTD Inputs Channel 2^Value;
                              .RTD_South_2.bError := TIIB[SL1L0-EL3202-E9]^RTD Inputs Channel 2^Status^Error;
                              .RTD_South_2.bUnderrange := TIIB[SL1L0-EL3202-E9]^RTD Inputs Channel 2^Status^Underrange;
                              .RTD_South_2.bOverrange := TIIB[SL1L0-EL3202-E9]^RTD Inputs Channel 2^Status^Overrange;
                              .RTD_TOP_1.iRaw := TIIB[SL1L0-EL3202-E10]^RTD Inputs Channel 1^Value;
                              .RTD_TOP_1.bError := TIIB[SL1L0-EL3202-E10]^RTD Inputs Channel 1^Status^Error;
                              .RTD_TOP_1.bUnderrange := TIIB[SL1L0-EL3202-E10]^RTD Inputs Channel 1^Status^Underrange;
                              .RTD_TOP_1.bOverrange := TIIB[SL1L0-EL3202-E10]^RTD Inputs Channel 1^Status^Overrange;
                              .RTD_TOP_2.iRaw := TIIB[SL1L0-EL3202-E10]^RTD Inputs Channel 2^Value;
                              .RTD_TOP_2.bError := TIIB[SL1L0-EL3202-E10]^RTD Inputs Channel 2^Status^Error;
                              .RTD_TOP_2.bUnderrange := TIIB[SL1L0-EL3202-E10]^RTD Inputs Channel 2^Status^Underrange;
                              .RTD_TOP_2.bOverrange := TIIB[SL1L0-EL3202-E10]^RTD Inputs Channel 2^Status^Overrange;
                              .RTD_North_1.iRaw := TIIB[SL1L0-EL3202-E11]^RTD Inputs Channel 1^Value;
                              .RTD_North_1.bError := TIIB[SL1L0-EL3202-E11]^RTD Inputs Channel 1^Status^Error;
                              .RTD_North_1.bUnderrange := TIIB[SL1L0-EL3202-E11]^RTD Inputs Channel 1^Status^Underrange;
                              .RTD_North_1.bOverrange := TIIB[SL1L0-EL3202-E11]^RTD Inputs Channel 1^Status^Overrange;
                              .RTD_North_2.iRaw := TIIB[SL1L0-EL3202-E11]^RTD Inputs Channel 2^Value;
                              .RTD_North_2.bError := TIIB[SL1L0-EL3202-E11]^RTD Inputs Channel 2^Status^Error;
                              .RTD_North_2.bUnderrange := TIIB[SL1L0-EL3202-E11]^RTD Inputs Channel 2^Status^Underrange;
                              .RTD_North_2.bOverrange := TIIB[SL1L0-EL3202-E11]^RTD Inputs Channel 2^Status^Overrange'}
    fbSL1L0: FB_SLITS_POWER;

    {attribute 'pytmc' := '
    pv: SL1L0:POWER:GO;
    io: io;
    field: ZNAM False;
    field: ONAM True;
    '}
    bExecuteMotion:BOOL ;

    // Default True until it is properly linked to PMPS bit
    bMoveOk:BOOL :=TRUE;


    mcPower : ARRAY [1..4] OF MC_POWER;

        (*Offsets*)
    (* Absolute encoder value at the HLS + Absolute encoder value at the centered beam *)
    rEncoderOffsetTop: REAL := 15.55;
    rEncoderOffsetBottom: REAL := -12.99;
    rEncoderOffsetNorth: REAL := 12.2;
    rEncoderOffsetSouth: REAL := -16.8;

END_VAR
(*
--MAPPING TO PHYSICAL TERMINAL--
Main.41 -> M1    (Bottom)
Main.42 -> M2    (South)
Main.43 -> M3    (Top)
Main.44 -> M4    (North)
*)

fbSL1L0.rEncoderOffsetTop := rEncoderOffsetTop;
fbSL1L0.rEncoderOffsetBottom := rEncoderOffsetBottom;
fbSL1L0.rEncoderOffsetNorth := rEncoderOffsetNorth;
fbSL1L0.rEncoderOffsetSouth := rEncoderOffsetSouth;

//fbSL1L0.bExecuteMotion := bExecuteMotion;
fbSL1L0.bMoveOk := bMoveOk;
fbSL1L0(stTopBlade:=  Main.M43,
        stBottomBlade:= Main.M41,
        stNorthBlade:=  Main.M44,
        stSouthBlade:=  Main.M42,
        bExecuteMotion:=bExecuteMotion);

//for testing purposes only. comment-out/delete once done.
(*mcPower[1](axis:=Main.M41.Axis, Enable:=TRUE, enable_positive:=Main.M41.bLimitForwardEnable, enable_negative:=Main.M41.bLimitBackwardEnable);
mcPower[2](axis:=Main.M42.Axis, Enable:=TRUE, enable_positive:=Main.M42.bLimitForwardEnable, enable_negative:=Main.M42.bLimitBackwardEnable);
mcPower[3](axis:=Main.M43.Axis, Enable:=TRUE, enable_positive:=Main.M43.bLimitForwardEnable, enable_negative:=Main.M43.bLimitBackwardEnable);
mcPower[4](axis:=Main.M44.Axis, Enable:=TRUE, enable_positive:=Main.M44.bLimitForwardEnable, enable_negative:=Main.M44.bLimitBackwardEnable);*)

END_PROGRAM
Related:

PRG_SL2L0_POWER

PROGRAM PRG_SL2L0_POWER
VAR // linking to rtd in the following order Bottom - South - TOP - NORTH
    {attribute 'pytmc' := '
        pv: SL2L0:POWER
        io: io
    '}
    {attribute 'TcLinkTo' := '.RTD_Bottom_1.iRaw := TIIB[SL2L0-EL3202-E8]^RTD Inputs Channel 1^Value;
                              .RTD_Bottom_1.bError := TIIB[SL2L0-EL3202-E8]^RTD Inputs Channel 1^Status^Error;
                              .RTD_Bottom_1.bUnderrange := TIIB[SL2L0-EL3202-E8]^RTD Inputs Channel 1^Status^Underrange;
                              .RTD_Bottom_1.bOverrange := TIIB[SL2L0-EL3202-E8]^RTD Inputs Channel 1^Status^Overrange;
                              .RTD_Bottom_2.iRaw := TIIB[SL2L0-EL3202-E8]^RTD Inputs Channel 2^Value;
                              .RTD_Bottom_2.bError := TIIB[SL2L0-EL3202-E8]^RTD Inputs Channel 2^Status^Error;
                              .RTD_Bottom_2.bUnderrange := TIIB[SL2L0-EL3202-E8]^RTD Inputs Channel 2^Status^Underrange;
                              .RTD_Bottom_2.bOverrange := TIIB[SL2L0-EL3202-E8]^RTD Inputs Channel 2^Status^Overrange;
                              .RTD_South_1.iRaw := TIIB[SL2L0-EL3202-E9]^RTD Inputs Channel 1^Value;
                              .RTD_South_1.bError := TIIB[SL2L0-EL3202-E9]^RTD Inputs Channel 1^Status^Error;
                              .RTD_South_1.bUnderrange := TIIB[SL2L0-EL3202-E9]^RTD Inputs Channel 1^Status^Underrange;
                              .RTD_South_1.bOverrange := TIIB[SL2L0-EL3202-E9]^RTD Inputs Channel 1^Status^Overrange;
                              .RTD_South_2.iRaw := TIIB[SL2L0-EL3202-E9]^RTD Inputs Channel 2^Value;
                              .RTD_South_2.bError := TIIB[SL2L0-EL3202-E9]^RTD Inputs Channel 2^Status^Error;
                              .RTD_South_2.bUnderrange := TIIB[SL2L0-EL3202-E9]^RTD Inputs Channel 2^Status^Underrange;
                              .RTD_South_2.bOverrange := TIIB[SL2L0-EL3202-E9]^RTD Inputs Channel 2^Status^Overrange;
                              .RTD_TOP_1.iRaw := TIIB[SL2L0-EL3202-E10]^RTD Inputs Channel 1^Value;
                              .RTD_TOP_1.bError := TIIB[SL2L0-EL3202-E10]^RTD Inputs Channel 1^Status^Error;
                              .RTD_TOP_1.bUnderrange := TIIB[SL2L0-EL3202-E10]^RTD Inputs Channel 1^Status^Underrange;
                              .RTD_TOP_1.bOverrange := TIIB[SL2L0-EL3202-E10]^RTD Inputs Channel 1^Status^Overrange;
                              .RTD_TOP_2.iRaw := TIIB[SL2L0-EL3202-E10]^RTD Inputs Channel 2^Value;
                              .RTD_TOP_2.bError := TIIB[SL2L0-EL3202-E10]^RTD Inputs Channel 2^Status^Error;
                              .RTD_TOP_2.bUnderrange := TIIB[SL2L0-EL3202-E10]^RTD Inputs Channel 2^Status^Underrange;
                              .RTD_TOP_2.bOverrange := TIIB[SL2L0-EL3202-E10]^RTD Inputs Channel 2^Status^Overrange;
                              .RTD_North_1.iRaw := TIIB[SL2L0-EL3202-E10]^RTD Inputs Channel 1^Value;
                              .RTD_North_1.bError := TIIB[SL2L0-EL3202-E10]^RTD Inputs Channel 1^Status^Error;
                              .RTD_North_1.bUnderrange := TIIB[SL2L0-EL3202-E11]^RTD Inputs Channel 1^Status^Underrange;
                              .RTD_North_1.bOverrange := TIIB[SL2L0-EL3202-E11]^RTD Inputs Channel 1^Status^Overrange;
                              .RTD_North_2.iRaw := TIIB[SL2L0-EL3202-E11]^RTD Inputs Channel 2^Value;
                              .RTD_North_2.bError := TIIB[SL2L0-EL3202-E11]^RTD Inputs Channel 2^Status^Error;
                              .RTD_North_2.bUnderrange := TIIB[SL2L0-EL3202-E11]^RTD Inputs Channel 2^Status^Underrange;
                              .RTD_North_2.bOverrange := TIIB[SL2L0-EL3202-E11]^RTD Inputs Channel 2^Status^Overrange'}
    fbSL2L0: FB_SLITS_POWER;

    {attribute 'pytmc' := '
    pv: SL2L0:POWER:GO;
    io: io;
    field: ZNAM False;
    field: ONAM True;
    '}
    bExecuteMotion:BOOL ;


    (*fbMotion1: FB_SimMotor;
    fbMotion2: FB_SimMotor;
    fbMotion3: FB_SimMotor;
    fbMotion4: FB_SimMotor;*)
    bMoveOk:BOOL :=TRUE;

     (*Offsets*)
    (* Absolute encoder value at the HLS + Absolute encoder value at the centered beam *)
    rEncoderOffsetTop: REAL := 0;
    rEncoderOffsetBottom: REAL := 0;
    rEncoderOffsetNorth: REAL := 0;
    rEncoderOffsetSouth: REAL := 0;

    fbSL1L0: INT;
END_VAR
(*
--MAPPING TO PHYSICAL TERMINAL--
Main.M45 -> M1    (Bottom)
Main.M46 -> M2    (South)
Main.M47 -> M3    (Top)
Main.M48 -> M4    (North)
*)

fbSL2L0.rEncoderOffsetTop := rEncoderOffsetTop;
fbSL2L0.rEncoderOffsetBottom := rEncoderOffsetBottom;
fbSL2L0.rEncoderOffsetNorth := rEncoderOffsetNorth;
fbSL2L0.rEncoderOffsetSouth := rEncoderOffsetSouth;

fbSL2L0.bMoveOk := bMoveOk;
fbSL2L0(stTopBlade:=  Main.M47,
        stBottomBlade:= Main.M45,
        stNorthBlade:=  Main.M48,
        stSouthBlade:=  Main.M46,
        bExecuteMotion:=bExecuteMotion);

END_PROGRAM
Related:

PRG_SP1L0_KMONO

PROGRAM PRG_SP1L0_KMONO
VAR
    fbMotion1: FB_MotionStage;
    fbMotion2: FB_MotionStage;
    fbMotion3: FB_MotionStage;
    fbMotion4: FB_MotionStage;
    fbMotion5: FB_MotionStage;
    fbMotion6: FB_MotionStage;

    (*
    fbFFO2: FB_BasicMotionStageAltFFO := (sName := 'SP1L0:KMONO:MMS:02');
    fbFFO4: FB_BasicMotionStageFFO := (sName := 'SP1L0:KMONO:MMS:04');
    fbFFO6: FB_BasicMotionStageFFO := (sName := 'SP1L0:KMONO:MMS:06');
    *)
    stOkBeam: ST_BeamParams := PMPS_GVL.cstFullBeam;
    bEnergyOk: BOOL;

    fbXTALFFO: FB_FastFault;
    bXtalOut: BOOL;
    bXtalIn: BOOL;

    fbRetFFO: FB_FastFault;
    bRetOut: BOOL;

    fbDiodeFFOAtPos: FB_FastFault;
    fbDiodeFFOEnergy: FB_FastFault;
    bDiodeOut: BOOL;
    bDiodeIn: BOOL;

    bInit: BOOL := TRUE;
END_VAR
IF bInit THEN
    // Only allow 7.7-8.9 keV
    stOkBeam.neVRange := F_eVIncludeRange(7700, 8900);
    bInit := FALSE;
END_IF
bEnergyOK := F_SafeBPCompare(PMPS_GVL.stCurrentBeamParameters, stOkBeam);

// Motor 1 XTAL ANGLE X (SP1L0-KMONO-MMS-01)
Main.M49.bLimitForwardEnable  := TRUE;    //TRUE
Main.M49.bLimitBackwardEnable := TRUE;    //TRUE
Main.M49.nEnableMode          := Enum_StageEnableMode.ALWAYS;
Main.M49.bHardwareEnable      := TRUE;
Main.M49.bPowerSelf           := TRUE;
fbMotion1(stMotionStage:=Main.M49);

// Motor 2 XTAL VERT Y (SP1L0-KMONO-MMS-02)
//Main.M50.bLimitForwardEnable  := bM2CCWLimit;    //(+Y)
//Main.M50.bLimitBackwardEnable := bM2CWLimit;    //(-Y)
Main.M50.nEnableMode          := Enum_StageEnableMode.ALWAYS;
Main.M50.bHardwareEnable      := TRUE;
Main.M50.bPowerSelf           := TRUE;
fbMotion2(stMotionStage:=Main.M50);
//fbFFO2(stMotionStage := Main.M50,
//       fbFFHWO := GVL.fbFastFaultOutput1,
//       bFFOk := Main.M50.stAxisStatus.fActPosition < 0.1);
// Andy says trip if IN and not between 7.7 and 8.9 keV
// Andy says reset if IN and between 7.7 and 8.9 keV OR at OUT
// IN is >50, out is at 0 (+-2)
bXtalOut := Main.M50.stAxisStatus.fActPosition < 2;
bXtalIn := Main.M50.stAxisStatus.fActPosition > 50;

fbXTALFFO(
    i_xOK := bEnergyOk OR NOT bXtalIn,
    i_xReset := bXtalOut OR (bXtalIn AND bEnergyOk),
    i_xAutoReset := TRUE,
    i_DevName := Main.M50.sName,
    i_Desc := 'Unsafe eV Range: needs 7.7-8.9keV',
    io_fbFFHWO := GVL.fbFastFaultOutput1);

// Motor 3 RETICLE HORIZ X (SP1L0-KMONO-MMS-03)
//Main.M51.bLimitForwardEnable  := bM3CCWLimit;    //(+X)
//Main.M51.bLimitBackwardEnable := bM3CWLimit;    //(-X)
Main.M51.nEnableMode          := Enum_StageEnableMode.DURING_MOTION;
Main.M51.bHardwareEnable      := TRUE;
Main.M51.bPowerSelf           := TRUE;
fbMotion3(stMotionStage:=Main.M51);

// Motor 4 RETICLE VERT Y (SP1L0-KMONO-MMS-04)
//Main.M52.bLimitForwardEnable  := bM4CWLimit;    //(+Y)
//Main.M52.bLimitBackwardEnable := bM4CCWLimit;    //(-Y)
Main.M52.nEnableMode          := Enum_StageEnableMode.ALWAYS;
Main.M52.bHardwareEnable      := TRUE;
Main.M52.bPowerSelf           := TRUE;
fbMotion4(stMotionStage:=Main.M52);
//fbFFO4(stMotionStage := Main.M52,
//       fbFFHWO := GVL.fbFastFaultOutput1);
// Andy says: trip reticle if not OUT
// OUT is 1.55843, in is high limit switch
// NOTE: we don't have an encoder or an LVDT on this axis! We will use the out switch
bRetOut := NOT Main.M52.bLimitForwardEnable;
fbRetFFO(
    i_xOk := bRetOut,
    i_xAutoReset := TRUE,
    i_DevName := Main.M52.sName,
    i_Desc := 'Reticle not OUT (y>0)',
    io_fbFFHWO := GVL.fbFastFaultOutput1);

// Motor 5 DIODE HORIZ X (SP1L0-KMONO-MMS-05)
//Main.M53.bLimitForwardEnable  := bM5CCWLimit;    //(+X)
//Main.M53.bLimitBackwardEnable := bM5CWLimit;    //(-X)
Main.M53.nEnableMode          := Enum_StageEnableMode.DURING_MOTION;
Main.M53.bHardwareEnable      := TRUE;
Main.M53.bPowerSelf           := TRUE;
fbMotion5(stMotionStage:=Main.M53);

// Motor 6 DIODE VERT Y (SP1L0-KMONO-MMS-06)
//Main.M54.bLimitForwardEnable  := bM6CWLimit;    //(+Y)
//Main.M54.bLimitBackwardEnable := bM6CCWLimit;    //(-Y)
Main.M54.nEnableMode          := Enum_StageEnableMode.ALWAYS;
Main.M54.bHardwareEnable      := TRUE;
Main.M54.bPowerSelf           := TRUE;
fbMotion6(stMotionStage:=Main.M54);
//fbFFO6(stMotionStage := Main.M54,
//       fbFFHWO := GVL.fbFastFaultOutput1);
// Andy says trip if NOT IN or NOT OUT
// Andy says trip if IN AND NOT (7.7 to 8.9 keV)
// IN is 0, OUT is 98.5
bDiodeOut := Main.M54.stAxisStatus.fActPosition > 96.5;
bDiodeIn := Main.M54.stAxisStatus.fActPosition < 2;
fbDiodeFFOAtPos(
    i_xOk := bDiodeOut XOR bDiodeIn,
    i_xAutoReset := TRUE,
    i_DevName := Main.M54.sName,
    i_Desc := 'Diode between states.',
    io_fbFFHWO := GVL.fbFastFaultOutput1);
fbDiodeFFOEnergy(
    i_xOk := bEnergyOk OR NOT bDiodeIn,
    i_xReset := bDiodeOut OR (bDiodeIn AND bEnergyOk),
    i_xAutoReset := TRUE,
    i_DevName := Main.M54.sName,
    //i_Desc := 'Unsafe eV Range',
    i_Desc := 'Override if 7.7-8.9keV',
    io_fbFFHWO := GVL.fbFastFaultOutput1);

END_PROGRAM
Related: