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 := 0, iMinor := 0, iBuild := 0, iRevision := 0, nFlags := 0, sVersion := '0.0.0');
END_VAR

GVL

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

    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:ARB:02'}
    fbArbiter2: FB_Arbiter(2);

    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:ARB:03'}
    fbArbiter3: FB_Arbiter(3);

    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:ARB:04'}
    fbArbiter4: FB_Arbiter(4);

    //all Group 1 faults Upstream on Optics and Stopper
    {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'}
    fbFastFaultOutput1a: FB_HardwareFFOutput := (bAutoReset := TRUE, i_sNetID := '172.21.88.66.1.1');
    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:FFO:03'}
    fbFastFaultOutput1b: FB_HardwareFFOutput := (bAutoReset := TRUE, i_sNetID := '172.21.88.66.1.1');
    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:FFO:04'}
    fbFastFaultOutput1c: FB_HardwareFFOutput := (bAutoReset := TRUE, i_sNetID := '172.21.88.66.1.1');

    //all Group 2 faults Downstream of MR1L1 Optics and Upstream of the stopper
     {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:FFO:05'}
    fbFastFaultOutput2: FB_HardwareFFOutput := (bAutoReset := TRUE, i_sNetID := '172.21.88.66.1.1');
    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:FFO:06'}
    fbFastFaultOutput2b: FB_HardwareFFOutput := (bAutoReset := TRUE, i_sNetID := '172.21.88.66.1.1');
    //all Group 3 faults Downstream of MR1L1 Optics the stopper
    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:FFO:07'}
    fbFastFaultOutput3: FB_HardwareFFOutput := (bAutoReset := TRUE, i_sNetID := '172.21.88.66.1.1');
    //TXI faults Downstream of MR1L1 Optics
    {attribute 'pytmc' := 'pv: PLC:LFE:MOTION:FFO:08'}
    {attribute 'TcLinkTo' := '.q_xFastFaultOut:=TIIB[PMPS_FFO]^Channel 2^Output'}
    fbFastFaultOutput4: FB_HardwareFFOutput := (bAutoReset := TRUE, i_sNetID := '172.21.88.66.1.1');
    {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;

    ePF1L0State: E_WFS_States;
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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_MotionStage := (sName := 'IM1L0:XTES:MMS');
    {attribute 'pytmc' := 'pv: IM1L0:XTES:CLZ'}
    {attribute 'TcLinkTo' := '.bHome := TIIB[IM1L0-EL1088]^Channel 2^Input'}
    M21: ST_MotionStage := (sName := 'IM1L0:XTES:CLZ');
    {attribute 'pytmc' := 'pv: IM1L0:XTES:CLF'}
    {attribute 'TcLinkTo' := '.bHome := TIIB[IM1L0-EL1088]^Channel 4^Input'}
    M22: ST_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: ST_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: ST_MotionStage := (sName := 'IM2L0:XTES:MMS');
    {attribute 'pytmc' := 'pv: IM2L0:XTES:CLZ'}
    {attribute 'TcLinkTo' := '.bHome := TIIB[IM2L0-EL1088]^Channel 2^Input'}
    M25: ST_MotionStage := (sName := 'IM2L0:XTES:CLZ');
    {attribute 'pytmc' := 'pv: IM2L0:XTES:CLF'}
    {attribute 'TcLinkTo' := '.bHome := TIIB[IM2L0-EL1088]^Channel 4^Input'}
    M26: ST_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: ST_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: ST_MotionStage := (sName := 'IM4L0:XTES:MMS');
    {attribute 'pytmc' := 'pv: IM4L0:XTES:CLZ'}
    {attribute 'TcLinkTo' := '.bHome := TIIB[IM4L0-EL1088]^Channel 2^Input'}
    M29: ST_MotionStage := (sName := 'IM4L0:XTES:CLZ');
    {attribute 'pytmc' := 'pv: IM4L0:XTES:CLF'}
    {attribute 'TcLinkTo' := '.bHome := TIIB[IM4L0-EL1088]^Channel 4^Input'}
    M30: ST_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: ST_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: ST_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: ST_MotionStage := (sName := 'RTDSL0:DIODE:MMS:01');
    M34: ST_MotionStage;
    M35: ST_MotionStage;
    M36: ST_MotionStage;
    M37: ST_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: ST_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: ST_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: ST_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: ST_MotionStage := (sName := 'RTDSL0:LDM:MMS:01');
    M38: ST_MotionStage;
    M39: ST_MotionStage;
    M40: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_MotionStage := (sName := 'SL2L0:POWER:MMS:NORTH');

    // SP1L0-KMONO: 6 Axes
    {attribute 'pytmc' := 'pv: SP1L0:KMONO:MMS:XTAL_ANGLE'}
    M49: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_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: ST_MotionStage := (sName := 'RTDSX0:MMS:03');
    *)

    {attribute 'pytmc' := 'pv: EM3L0:IPM:MMS:X'}
    {attribute 'TcLinkTo' := '.nRawEncoderULINT     := TIIB[EM3L0-EL5042-E2]^FB Inputs Channel 1^Position'}
    M55: ST_MotionStage := (sName := 'EM3L0:IPM:MMS:X');
    {attribute 'pytmc' := 'pv: EM3L0:IPM:MMS:Y'}
    {attribute 'TcLinkTo' := '.bBrakeRelease        := TIIB[EM3L0-EL2004-E4]^Channel 1^Output;
                              .nRawEncoderULINT     := TIIB[EM3L0-EL5042-E2]^FB Inputs Channel 2^Position'}
    M56: ST_MotionStage := (sName := 'EM3L0:IPM:MMS:Y');

    {attribute 'pytmc' := 'pv: IM5L0:PPM:MMS'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[IM5L0-EL1084-E4]^Channel 3^Input;
                              .bLimitBackwardEnable := TIIB[IM5L0-EL1084-E4]^Channel 4^Input;
                              .bBrakeRelease        := TIIB[IM5L0-EL2004-E3]^Channel 1^Output;
                              .nRawEncoderULINT     := TIIB[IM5L0-EL5042-E2]^FB Inputs Channel 1^Position'}
    M57: ST_MotionStage := (sName := 'IM5L0:PPM:MMS');

    {attribute 'pytmc' := 'pv: AL1L0:REF:MMS'}
    {attribute 'TcLinkTo' := '.nRawEncoderULINT     := TIIB[AL1L0-EL5042-E2]^FB Inputs Channel 2^Position'}
    M58: ST_MotionStage := (sName := 'AL1L0:REF:MMS');

     // SL2L0-SCATTER: 4 Axes
    {attribute 'pytmc' := 'pv: SL3L0:SCATTER:MMS:BOTTOM'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL3L0-EL7037-E6]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[SL3L0-EL7037-E6]^STM Status^Status^Digital input 2;
                              .nRawEncoderULINT     := TIIB[SL3L0-EL5042-E5]^FB Inputs Channel 1^Position'}
    M59: ST_MotionStage := (sName := 'SL3L0:SCATTER:MMS:BOTTOM');
        {attribute 'pytmc' := 'pv: SL3L0:SCATTER:MMS:TOP'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL3L0-EL7037-E4]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[SL3L0-EL7037-E4]^STM Status^Status^Digital input 2;
                               .nRawEncoderULINT     := TIIB[SL3L0-EL5042-E5]^FB Inputs Channel 2^Position'}
    M60: ST_MotionStage := (sName := 'SL3L0:SCATTER:MMS:TOP');
        {attribute 'pytmc' := 'pv: SL3L0:SCATTER:MMS:SOUTH'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL3L0-EL7037-E3]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[SL3L0-EL7037-E3]^STM Status^Status^Digital input 2;
                                .nRawEncoderULINT     := TIIB[SL3L0-EL5042-E2]^FB Inputs Channel 1^Position'}
    M61: ST_MotionStage := (sName := 'SL3L0:SCATTER:MMS:SOUTH');
    {attribute 'pytmc' := 'pv: SL3L0:SCATTER:MMS:NORTH'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL3L0-EL7037-E1]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[SL3L0-EL7037-E1]^STM Status^Status^Digital input 2;
                            .nRawEncoderULINT     := TIIB[SL3L0-EL5042-E2]^FB Inputs Channel 2^Position'}
    M62: ST_MotionStage := (sName := 'SL3L0:SCATTER:MMS:NORTH');

    {attribute 'pytmc' := 'pv: PF2L0:GBS:MMS:Y'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[PF2L0-EL1084-E4]^Channel 3^Input;
                              .bLimitBackwardEnable := TIIB[PF2L0-EL1084-E4]^Channel 4^Input;
                              .bBrakeRelease        := TIIB[PF2L0-EL2004-E3]^Channel 1^Output;
                              .nRawEncoderULINT     := TIIB[PF2L0-EL5042-E2]^FB Inputs Channel 2^Position'}
    M63: ST_MotionStage := (sName := 'PF2L0:GBS:MMS:Y');


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_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_SCATTER

FUNCTION_BLOCK FB_SLITS_SCATTER EXTENDS FB_SLITS
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
END_VAR
ACT_init();
// Instantiate Function block for all the blades
ACT_Motion();
//SET and GET the requested and Actual values
ACT_CalculatePositions();

END_FUNCTION_BLOCK
Related:

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_IM5L0_PPM();
PRG_PF1L0_WFS();
PRG_RTDSL0();
PRG_SL1L0_POWER();
PRG_SL2L0_POWER();
//PRG_SP1L0_KMONO();
PRG_PF2L0_GBS();
PRG_EM3L0_IPM();
PRG_AL1L0_REF();
PRG_SL3L0_SCATTER();

PRG_3_PMPS_POST();
PRG_4_LOG();

END_PROGRAM
Related:

PRG_2_PMPS_PRE

PROGRAM PRG_2_PMPS_PRE
VAR

END_VAR
MOTION_GVL.fbStandardPMPSDB(
    io_fbFFHWO:=GVL.fbFastFaultOutput1,
    bEnable:=TRUE,
    sPLCName:='plc-lfe-motion',
);

END_PROGRAM
Related:

PRG_3_PMPS_POST

PROGRAM PRG_3_PMPS_POST
VAR
    fbArbiterIO: FB_SubSysToArbiter_IO;
    bMR1L1_Veto_OUT: BOOL;
    bMR1L1_Veto_IN:BOOL;
    fbVetoArbiter_L1: FB_VetoArbiter;
    fbVetoArbiter_G2: FB_VetoArbiter;
    fbVetoArbiter_G3: FB_VetoArbiter;
    //Fast Fault to Aggregate all Groups
    g_FastFault             :       FB_FastFault();
    //Fast Fault to Aggregate


    q_xFastFaultOut: INT;
END_VAR
bMR1L1_Veto_OUT := PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.L_Stopper.MR1L1_OUT] AND NOT PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.L_Stopper.MR1L1_IN];
bMR1L1_Veto_IN := NOT PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.L_Stopper.MR1L1_OUT] AND PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.L_Stopper.MR1L1_IN];
//Veto Group 1
//all Group 1 faults Upstream on Optics and Stopper
GVL.fbFastFaultOutput1.Execute();
GVL.fbFastFaultOutput1a.Execute();
GVL.fbFastFaultOutput1b.Execute();
GVL.fbFastFaultOutput1c.Execute();
//Veto Group 2
//all Group 2 faults Downstream of MR1L1 Optics and Upstream of the stopper
GVL.fbFastFaultOutput2.Execute(i_xVeto:=bMR1L1_Veto_IN);
GVL.fbFastFaultOutput2b.Execute(i_xVeto:=bMR1L1_Veto_IN);
//Veto Group 3
//all Group 3 faults Downstream of MR1L1 Optics the stopper
GVL.fbFastFaultOutput3.Execute(i_xVeto:=bMR1L1_Veto_IN OR PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.L_Stopper.ST1L0]);
//Veto Group 4
//TXI faults Downstream of MR1L1 Optics
GVL.fbFastFaultOutput4.Execute(i_xVeto:=bMR1L1_Veto_OUT);

// Aggregate FastFaultOutputs of all into a single FastFault
g_FastFault(
    io_fbFFHWO := GVL.fbFastFaultOutput1,
    i_xOK := (  GVL.fbFastFaultOutput1a.q_xFastFaultOut
                AND GVL.fbFastFaultOutput1b.q_xFastFaultOut
                AND GVL.fbFastFaultOutput1c.q_xFastFaultOut
                AND GVL.fbFastFaultOutput2.q_xFastFaultOut
                AND GVL.fbFastFaultOutput2b.q_xFastFaultOut
                AND GVL.fbFastFaultOutput3.q_xFastFaultOut
             ),
    i_xAutoReset:=TRUE,
    i_DevName :='Aggregate LFE CC FastFaultOutputs'
);



fbVetoArbiter_G2(bVeto:=bMR1L1_Veto_IN,
                HigherAuthority := GVL.fbArbiter,
                LowerAuthority := GVL.fbArbiter2,
                FFO := GVL.fbFastFaultOutput1);
fbVetoArbiter_G3(bVeto:=bMR1L1_Veto_IN OR PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.L_Stopper.ST1L0],
                HigherAuthority := GVL.fbArbiter,
                LowerAuthority := GVL.fbArbiter3,
                FFO := GVL.fbFastFaultOutput1);

fbVetoArbiter_L1(bVeto:=bMR1L1_Veto_OUT,
                HigherAuthority := GVL.fbArbiter,
                LowerAuthority := GVL.fbArbiter4,
                FFO := GVL.fbFastFaultOutput1);

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_AL1L0_REF

PROGRAM PRG_AL1L0_REF
VAR
    {attribute 'pytmc' := 'pv: AL1L0:REF'}
    {attribute 'TcLinkTo' := '.fbLaser.iLaserINT := TIIB[AL1L0-EL4004-E4]^AO Outputs Channel 3^Analog output;
                              .fbLaser.iShutdownINT := TIIB[AL1L0-EL4004-E4]^AO Outputs Channel 2^Analog output'}
    fbAL1L0: FB_REF;

    fbStateSetup: FB_StateSetupHelper;
    stDefault: ST_PositionState := (
        fVelocity := 1,
        bMoveOk := TRUE,
        bValid := TRUE
    );

    fTermMax: LREAL := 131;
END_VAR
//Device doesn't have end of travel limits switches
MAIN.M58.bLimitBackwardEnable := TRUE;
MAIN.M58.bLimitForwardEnable := TRUE;


fbStateSetup(stPositionState:=stDefault, bSetDefault:=TRUE);
fbStateSetup(stPositionState:=fbAL1L0.stOut, fPosition:=0, sPmpsState:='AL1L0:REF-OUT');
fbStateSetup(stPositionState:=fbAL1L0.stIn, fPosition:=-43.38, fDelta:=2, sPmpsState:='AL1L0:REF-IN');

fbAL1L0(
    fbFFHWO := GVL.fbFastFaultOutput3,
    fbArbiter := GVL.fbArbiter3,
    stYStage := MAIN.M58,
    sDeviceName := 'AL1L0:REF',
    sTransitionKey := 'AL1L0:REF-TRANSITION',
    bEnableMotion := TRUE,
    bEnableBeamParams := TRUE,
    bEnablePositionLimits := TRUE,
    fTermMax := fTermMax,
);
// Needed to prevent gravity from pulling the stage down since there is no brake
MAIN.M58.nEnableMode := ENUM_StageEnableMode.ALWAYS;

END_PROGRAM
Related:

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
    '}
    fbAT2L0_states: ARRAY[1..19] OF FB_PositionState1D_InOut;

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

    stIn: ST_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](
        stMotionStage := fbAT2L0_axes[iIndex]^,
        stOut := stOut,
        stIn := stIn);

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

    IF fbAT2L0_states[iIndex].eStateGet = ENUM_EpicsInOut.UNKNOWN THEN
        stFilter.fTransmission := 0.0;
    ELSIF fbAT2L0_states[iIndex].eStateGet = 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].eStateGet = 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_EM3L0_IPM

PROGRAM PRG_EM3L0_IPM
VAR
    {attribute 'pytmc' := '
        pv: EM3L0:IPM
        io: io
    '}
    fbEM3L0: FB_IPM;

    fbStateSetup: FB_StateSetupHelper;
    stDefault: ST_PositionState :=(
        fVelocity := 0.5,
        bMoveOK := TRUE,
        bValid := TRUE
    );
END_VAR
fbStateSetup(StPositionState:=stDefault, bSetDefault:=TRUE);
fbStateSetup(StPositionState:=fbEM3L0.stOut, fposition:=0, sPmpsState := 'EM3L0:IPM-OUT');
fbStateSetup(StPositionState:=fbEM3L0.stTarget1, fposition:=-17, sPmpsState := 'EM3L0:IPM-TARGET1');
fbStateSetup(StPositionState:=fbEM3L0.stTarget2, fposition:=-37.5, sPmpsState := 'EM3L0:IPM-TARGET2');
fbStateSetup(StPositionState:=fbEM3L0.stTarget3, fposition:=-58.23, sPmpsState := 'EM3L0:IPM-TARGET3');
fbStateSetup(StPositionState:=fbEM3L0.stTarget4, fposition:=-78.85, sPmpsState := 'EM3L0:IPM-TARGET4');

fbEM3L0.stOut.fPosition:=0;
fbEM3L0.stTarget1.fPosition:=-17;
fbEM3L0.stTarget2.fPosition:=-37.5;
fbEM3L0.stTarget3.fPosition:=-58.23;
fbEM3L0.stTarget4.fPosition:=-78.85;

fbEM3L0(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stXStage := MAIN.M55,
    stYStage := MAIN.M56,
    sDeviceName := 'EM3L0:IPM',
    sTransitionKey := 'EM3L0:IPM-TRANSITION',
    bEnableMotion := TRUE,
    bEnableBeamParams := TRUE,
    bEnablePositionLimits := TRUE
);

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;

    fbStateSetup: FB_StateSetupHelper;
    stDefault: ST_PositionState := (
        fVelocity := 1,
        bMoveOk := TRUE,
        bValid := TRUE
    );
END_VAR
fbStateSetup(stPositionState:=stDefault, bSetDefault:=TRUE);
fbStateSetup(stPositionState:=fbIM1L0.stOut, fPosition:=0,          sPmpsState:='IM1L0:XTES-OUT');
fbStateSetup(stPositionState:=fbIM1L0.stYag, fPosition:=-86.65,     sPmpsState:='IM1L0:XTES-YAG');
fbStateSetup(stPositionState:=fbIM1L0.stDiamond, fPosition:=-56.65, sPmpsState:='IM1L0:XTES-DIAMOND');
fbStateSetup(stPositionState:=fbIM1L0.stReticle, fPosition:=-26.65, sPmpsState:='IM1L0:XTES-RETICLE');

fbIM1L0(
    fbArbiter := GVL.fbArbiter,
    fbFFHWO := GVL.fbFastFaultOutput1a,
    stYStage := Main.M20,
    stZoomStage := Main.M21,
    stFocusStage := Main.M22,
    stEl6In := stEL6In,
    stEl6Out := stEl6Out,
    sDeviceName := 'IM1L0:XTES',
    sTransitionKey := 'IM1L0:XTES-TRANSITION',
    bEnableMotion := TRUE,
    bEnableBeamParams := TRUE,
    bEnablePositionLimits := TRUE,
);

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.fbTempSensor.bError := TIIB[IM1L1-EL3314]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbTempSensor.bUnderrange := TIIB[IM1L1-EL3314]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbTempSensor.bOverrange := TIIB[IM1L1-EL3314]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbTempSensor.iRaw := TIIB[IM1L1-EL3314]^TC Inputs Channel 1^Value;
                              .fbYagTempSensor.bError := TIIB[IM1L1-EL3314]^TC Inputs Channel 2^Status^Error;
                              .fbYagTempSensor.bUnderrange := TIIB[IM1L1-EL3314]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagTempSensor.bOverrange := TIIB[IM1L1-EL3314]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagTempSensor.iRaw := TIIB[IM1L1-EL3314]^TC Inputs Channel 2^Value'}
    fbIM1L1: FB_PPM;

    fbStateSetup: FB_StateSetupHelper;
    stDefault: ST_PositionState := (
        fVelocity := 10,
        bMoveOk := TRUE,
        bValid := TRUE
    );
END_VAR
fbStateSetup(stPositionState:=stDefault, bSetDefault:=TRUE);
fbStateSetup(stPositionState:=fbIM1L1.stOut, fPosition:=-11,    sPmpsState:='IM1L1:PPM-OUT');
fbStateSetup(stPositionState:=fbIM1L1.stPower, fPosition:=-47.59, sPmpsState:='IM1L1:PPM-POWERMETER');
fbStateSetup(stPositionState:=fbIM1L1.stYag1, fPosition:=-71.69,  sPmpsState:='IM1L1:PPM-YAG1');
fbStateSetup(stPositionState:=fbIM1L1.stYag2, fPosition:=-97.70,  sPmpsState:='IM1L1:PPM-YAG2');

fbIM1L1(
    fbArbiter := GVL.fbArbiter4,
    fbFFHWO := GVL.fbFastFaultOutput4,
    stYStage := Main.M23,
    sDeviceName := 'IM1L1:PPM',
    sTransitionKey := 'IM1L1:PPM-TRANSITION',
    bEnableMotion := TRUE,
    bEnableBeamParams := TRUE,
    bEnablePositionLimits := TRUE,
    fResponsivity := 0.0640, //probably wrong, check with Phil
);

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;

    fbStateSetup: FB_StateSetupHelper;
    stDefault: ST_PositionState := (
        fVelocity := 1,
        bMoveOk := TRUE,
        bValid := TRUE
    );

    {attribute 'TcLinkTo' := 'TIIB[IM2L0-EL7041]^STM Status^Status^Digital input 1'}
    bDefectiveLimitSwitch AT %I*: BOOL;
END_VAR
fbStateSetup(stPositionState:=stDefault, bSetDefault:=TRUE);
fbStateSetup(stPositionState:=fbIM2L0.stOut, fPosition:=0,          sPmpsState:='IM2L0:XTES-OUT');
fbStateSetup(stPositionState:=fbIM2L0.stYag, fPosition:=-87.65,     sPmpsState:='IM2L0:XTES-YAG');
fbStateSetup(stPositionState:=fbIM2L0.stDiamond, fPosition:=-57.65, sPmpsState:='IM2L0:XTES-DIAMOND');
fbStateSetup(stPositionState:=fbIM2L0.stReticle, fPosition:=-27.65, sPmpsState:='IM2L0:XTES-RETICLE');

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

fbIM2L0(
    fbArbiter := GVL.fbArbiter,
    fbFFHWO := GVL.fbFastFaultOutput1a,
    stYStage := Main.M24,
    stZoomStage := Main.M25,
    stFocusStage := Main.M26,
    stEl6In := stEL6In,
    stEl6Out := stEl6Out,
    sDeviceName := 'IM2L0:XTES',
    sTransitionKey := 'IM2L0:XTES-TRANSITION',
    bEnableMotion := TRUE,
    bEnableBeamParams := TRUE,
    bEnablePositionLimits := TRUE,
);

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.fbTempSensor.bError := TIIB[IM3L0-EL3314]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbTempSensor.bUnderrange := TIIB[IM3L0-EL3314]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbTempSensor.bOverrange := TIIB[IM3L0-EL3314]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbTempSensor.iRaw := TIIB[IM3L0-EL3314]^TC Inputs Channel 1^Value;
                              .fbYagTempSensor.bError := TIIB[IM3L0-EL3314]^TC Inputs Channel 2^Status^Error;
                              .fbYagTempSensor.bUnderrange := TIIB[IM3L0-EL3314]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagTempSensor.bOverrange := TIIB[IM3L0-EL3314]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagTempSensor.iRaw := TIIB[IM3L0-EL3314]^TC Inputs Channel 2^Value'}
    fbIM3L0: FB_PPM;

    fbStateSetup: FB_StateSetupHelper;
    stDefault: ST_PositionState := (
        fVelocity := 10,
        bMoveOk := TRUE,
        bValid := TRUE
    );
END_VAR
fbStateSetup(stPositionState:=stDefault, bSetDefault:=TRUE);
fbStateSetup(stPositionState:=fbIM3L0.stOut, fPosition:=-8.40,    sPmpsState:='IM3L0:PPM-OUT');
fbStateSetup(stPositionState:=fbIM3L0.stPower, fPosition:=-47.40, sPmpsState:='IM3L0:PPM-POWERMETER');
fbStateSetup(stPositionState:=fbIM3L0.stYag1, fPosition:=-71.50,  sPmpsState:='IM3L0:PPM-YAG1');
fbStateSetup(stPositionState:=fbIM3L0.stYag2, fPosition:=-97.51,  sPmpsState:='IM3L0:PPM-YAG2');

fbIM3L0(
    fbArbiter := GVL.fbArbiter,
    fbFFHWO := GVL.fbFastFaultOutput1c,
    stYStage := Main.M27,
    sDeviceName := 'IM3L0:PPM',
    sTransitionKey := 'IM3L0:PPM-TRANSITION',
    bEnableMotion := TRUE,
    bEnableBeamParams := TRUE,
    bEnablePositionLimits := TRUE,
    fResponsivity := 0.0506,
);

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;

    fbStateSetup: FB_StateSetupHelper;
    stDefault: ST_PositionState := (
        fVelocity := 10.0,
        bMoveOk := TRUE,
        bValid := TRUE
    );
END_VAR
fbStateSetup(stPositionState:=stDefault, bSetDefault:=TRUE);
fbStateSetup(stPositionState:=fbIM4L0.stOut, fPosition:=0,          sPmpsState:='IM4L0:XTES-OUT');
fbStateSetup(stPositionState:=fbIM4L0.stYag, fPosition:=-86.65,     sPmpsState:='IM4L0:XTES-YAG');
fbStateSetup(stPositionState:=fbIM4L0.stDiamond, fPosition:=-56.65, sPmpsState:='IM4L0:XTES-DIAMOND');
fbStateSetup(stPositionState:=fbIM4L0.stReticle, fPosition:=-26.65, sPmpsState:='IM4L0:XTES-RETICLE');

fbIM4L0(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2b,
    stYStage := Main.M28,
    stZoomStage := Main.M29,
    stFocusStage := Main.M30,
    stEl6In := stEL6In,
    stEl6Out := stEl6Out,
    sDeviceName := 'IM4L0:XTES',
    sTransitionKey := 'IM4L0:XTES-TRANSITION',
    bEnableMotion := TRUE,
    bEnableBeamParams := TRUE,
    bEnablePositionLimits := TRUE,
);

END_PROGRAM
Related:

PRG_IM5L0_PPM

PROGRAM PRG_IM5L0_PPM
VAR
    {attribute 'pytmc' := '
        pv: IM5L0:PPM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbGige.iIlluminatorINT := TIIB[IM5L0-EL4004-E7]^AO Outputs Channel 1^Analog output;
                              .fbPowerMeter.iVoltageINT := TIIB[IM5L0-EL3602-E6]^AI Inputs Channel 1^Value;
                              .fbPowerMeter.fbTempSensor.bError := TIIB[IM5L0-EL3202-0010-E5]^RTD Inputs Channel 2^Status^Error;
                              .fbPowerMeter.fbTempSensor.bUnderrange := TIIB[IM5L0-EL3202-0010-E5]^RTD Inputs Channel 2^Status^Underrange;
                              .fbPowerMeter.fbTempSensor.bOverrange := TIIB[IM5L0-EL3202-0010-E5]^RTD Inputs Channel 2^Status^Overrange;
                              .fbPowerMeter.fbTempSensor.iRaw := TIIB[IM5L0-EL3202-0010-E5]^RTD Inputs Channel 2^Value;
                              .fbYagTempSensor.bError := TIIB[IM5L0-EL3202-0010-E5]^RTD Inputs Channel 1^Status^Error;
                              .fbYagTempSensor.bUnderrange := TIIB[IM5L0-EL3202-0010-E5]^RTD Inputs Channel 1^Status^Underrange;
                              .fbYagTempSensor.bOverrange := TIIB[IM5L0-EL3202-0010-E5]^RTD Inputs Channel 1^Status^Overrange;
                              .fbYagTempSensor.iRaw := TIIB[IM5L0-EL3202-0010-E5]^RTD Inputs Channel 1^Value'}
    fbIM5L0: FB_PPM;

    fbStateSetup: FB_StateSetupHelper;
    stDefault: ST_PositionState := (
        fVelocity := 7.0,
        bMoveOk := TRUE,
        bValid := TRUE
    );
END_VAR
//'fbIM5L0.fbPowerMeter.fbTempSensor.fResolution :=0.01;

fbStateSetup(stPositionState:=stDefault, bSetDefault:=TRUE);
fbStateSetup(stPositionState:=fbIM5L0.stOut, fPosition:=0,  sPmpsState:='IM5L0:PPM-OUT');
fbStateSetup(stPositionState:=fbIM5L0.stPower, fPosition:=-40.3451, sPmpsState:='IM5L0:PPM-POWERMETER');
fbStateSetup(stPositionState:=fbIM5L0.stYag1, fPosition:=-62.39670, sPmpsState:='IM5L0:PPM-YAG1');
fbStateSetup(stPositionState:=fbIM5L0.stYag2, fPosition:=-73.0395,  sPmpsState:='IM5L0:PPM-YAG2');

fbIM5L0.stOut.fPosition:=0;
fbIM5L0.stPower.fPosition:=-40.3451;
fbIM5L0.stYag1.fPosition:=-62.39670;
fbIM5L0.stYag2.fPosition:=-73.0395;

fbIM5L0(
    fbArbiter := GVL.fbArbiter3,
    fbFFHWO := GVL.fbFastFaultOutput3,
    stYStage := Main.M57,
    sDeviceName := 'IM5L0:PPM',
    sTransitionKey := 'IM5L0:PPM-TRANSITION',
    bEnableMotion := TRUE,
    bEnableBeamParams := TRUE,
    bEnablePositionLimits := TRUE,
    fResponsivity := 1.0,
    iTermBits := 31,
    fTermMax := 10000,
    fTermMin := 0
);

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;

    fbStateSetup: FB_StateSetupHelper;
    stDefault: ST_PositionState := (
        fVelocity := 2,
        bMoveOk := TRUE,
        bValid := TRUE
    );
END_VAR
fbStateSetup(stPositionState:=stDefault, bSetDefault:=TRUE);
fbStateSetup(stPositionState:=fbPF1L0.stOut, fPosition:=0,         sPmpsState:='PF1L0:WFS-OUT');
fbStateSetup(stPositionState:=fbPF1L0.stTarget1, fPosition:=-23.3,  sPmpsState:='PF1L0:WFS-TARGET1');
fbStateSetup(stPositionState:=fbPF1L0.stTarget2, fPosition:=-37.65, sPmpsState:='PF1L0:WFS-TARGET2');
fbStateSetup(stPositionState:=fbPF1L0.stTarget3, fPosition:=-52, sPmpsState:='PF1L0:WFS-TARGET3');
fbStateSetup(stPositionState:=fbPF1L0.stTarget4, fPosition:=-66.4, sPmpsState:='PF1L0:WFS-TARGET4');
fbStateSetup(stPositionState:=fbPF1L0.stTarget5, fPosition:=-80.77, sPmpsState:='PF1L0:WFS-TARGET5');
// When the IOC restarts Auto save overrites teh psotions.
// Hard coding the position so they are not overriden with ioc restart
fbPF1L0.stOut.fPosition:=0;
fbPF1L0.stTarget1.fPosition:=-23.3;
fbPF1L0.stTarget2.fPosition:=-37.65;
fbPF1L0.stTarget3.fPosition:=-52;
fbPF1L0.stTarget4.fPosition:=-66.4;
fbPF1L0.stTarget5.fPosition:=-80.77;

fbPF1L0(
    fbArbiter := GVL.fbArbiter,
    fbFFHWO := GVL.fbFastFaultOutput1b,
    stYStage := Main.M31,
    stZStage := Main.M32,
    sDeviceName := 'PF1L0:WFS',
    sTransitionKey := 'PF1L0:WFS-TRANSITION',
    bEnableMotion := TRUE,
    bEnableBeamParams := TRUE,
    bEnablePositionLimits := TRUE,
    eEnumGet => GVL.ePF1L0State,
);

END_PROGRAM
Related:

PRG_PF2L0_GBS

PROGRAM PRG_PF2L0_GBS
VAR
    {attribute 'pytmc' := '
        pv: PF2L0:GBS
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbRTD1.bError := TIIB[PF2L0-EL3202-0010-E5]^RTD Inputs Channel 1^Status^Error;
                              .fbRTD1.bUnderrange := TIIB[PF2L0-EL3202-0010-E5]^RTD Inputs Channel 1^Status^Underrange;
                              .fbRTD1.bOverrange := TIIB[PF2L0-EL3202-0010-E5]^RTD Inputs Channel 1^Status^Overrange;
                              .fbRTD1.iRaw := TIIB[PF2L0-EL3202-0010-E5]^RTD Inputs Channel 1^Value;
                              .fbRTD2.bError := TIIB[PF2L0-EL3202-0010-E5]^RTD Inputs Channel 2^Status^Error;
                              .fbRTD2.bUnderrange := TIIB[PF2L0-EL3202-0010-E5]^RTD Inputs Channel 2^Status^Underrange;
                              .fbRTD2.bOverrange := TIIB[PF2L0-EL3202-0010-E5]^RTD Inputs Channel 2^Status^Overrange;
                              .fbRTD2.iRaw := TIIB[PF2L0-EL3202-0010-E5]^RTD Inputs Channel 2^Value'}
    fbPF2L0: FB_GBS;

    fbStateSetup: FB_StateSetupHelper;
    stDefault: ST_PositionState :=(
        fVelocity := 7,
        fDelta:=0.5,
        bMoveOK := TRUE,
        bValid := TRUE
    );
END_VAR
fbStateSetup(StPositionState:=stDefault, bSetDefault:=TRUE);

fbStateSetup(StPositionState:=fbPF2L0.stOut,         fposition:=0,          sPmpsState := 'PF2L0:GBS-OUT');
fbStateSetup(StPositionState:=fbPF2L0.stTarget1a, fposition:=-31.605, sPmpsState := 'PF2L0:GBS-TARGET1a');
fbStateSetup(StPositionState:=fbPF2L0.stTarget1b, fposition:=-33.105, sPmpsState := 'PF2L0:GBS-TARGET1b');
fbStateSetup(StPositionState:=fbPF2L0.stTarget2a, fposition:=-43.264, sPmpsState := 'PF2L0:GBS-TARGET2a');
fbStateSetup(StPositionState:=fbPF2L0.stTarget2b, fposition:=-44.776, sPmpsState := 'PF2L0:GBS-TARGET2b');
fbStateSetup(StPositionState:=fbPF2L0.stTarget3a, fposition:=-54.618, sPmpsState := 'PF2L0:GBS-TARGET3a');
fbStateSetup(StPositionState:=fbPF2L0.stTarget3b, fposition:=-56.120, sPmpsState := 'PF2L0:GBS-TARGET3b');
fbStateSetup(StPositionState:=fbPF2L0.stTarget4, fposition:=-68.01, sPmpsState := 'PF2L0:GBS-TARGET4');
fbStateSetup(StPositionState:=fbPF2L0.stTarget5, fposition:=-79.47, sPmpsState := 'PF2L0:GBS-TARGET5');
fbStateSetup(StPositionState:=fbPF2L0.stTarget6, fposition:=-91.07, sPmpsState := 'PF2L0:GBS-TARGET6');
// When the IOC restarts Auto save overrites teh psotions.
// Hard coding the position so they are not overriden with ioc restart
fbPF2L0.stOut.fPosition:=0;
fbPF2L0.stTarget1a.fposition:=-31.605;
fbPF2L0.stTarget1b.fposition:=-33.105;
fbPF2L0.stTarget2a.fposition:=-43.264;
fbPF2L0.stTarget2b.fposition:=-44.776;
fbPF2L0.stTarget3a.fposition:=-54.618;
fbPF2L0.stTarget3b.fposition:=-56.120;
fbPF2L0.stTarget4.fposition:=-68.01;
fbPF2L0.stTarget5.fposition:=-79.47;
fbPF2L0.stTarget6.fposition:=-91.07;

fbPF2L0(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stYStage := MAIN.M63,
    sDeviceName := 'PF2L0:GBS',
    sTransitionKey := 'PF2L0:GBS-TRANSITION',
    bEnableMotion := TRUE,
    bEnableBeamParams := TRUE,
    bEnablePositionLimits := TRUE
);

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 := 16.6;
    rEncoderOffsetBottom: REAL := -11.65;
    rEncoderOffsetNorth: REAL := 12.45;
    rEncoderOffsetSouth: REAL := -16.45;

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_SL3L0_SCATTER

PROGRAM PRG_SL3L0_SCATTER
VAR // linking to rtd in the following order Bottom - South - TOP - NORTH
    {attribute 'pytmc' := '
        pv: SL3L0:SCATTER
        io: io
    '}
    fbSL3L0: FB_SLITS_SCATTER;

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

    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;

END_VAR
(*
--MAPPING TO PHYSICAL TERMINAL--
Main.M59     (Bottom)
Main.M61     (South)
Main.M60     (Top)
Main.M62     (North)
*)
//Absolute enocders
Main.M59.nHomingMode := ENUM_EpicsHomeCmd.NONE;
Main.M60.nHomingMode := ENUM_EpicsHomeCmd.NONE;
Main.M61.nHomingMode := ENUM_EpicsHomeCmd.NONE;
Main.M62.nHomingMode := ENUM_EpicsHomeCmd.NONE;

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

fbSL3L0.bMoveOk := bMoveOk;
fbSL3L0(stTopBlade:=  Main.M60,
        stBottomBlade:= Main.M59,
        stNorthBlade:=  Main.M62,
        stSouthBlade:=  Main.M61,
        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: