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;
END_STRUCT
END_TYPE
Related:

ENUM_SXR_SATT_Position

{attribute 'qualified_only'}
TYPE ENUM_SXR_SATT_Position :
(
    UNKNOWN := 0, // UNKNOWN must be in slot 0 or the FB breaks
    OUT := 1, // OUT at slot 1 is a convention
    FILTER1 := 2,
    FILTER2 := 3,
    FILTER3 := 4,
    FILTER4 := 5,
    FILTER5 := 6,
    FILTER6 := 7,
    FILTER7 := 8,
    FILTER8 := 9
);
END_TYPE

ENUM_TM2K2_States

{attribute 'qualified_only'}
TYPE ENUM_TM2K2_States :
// Adapted from ENUM_ATM_States to add TARGET6
(
    Unknown := 0,
    OUT := 1,
    TARGET1 := 2,
    TARGET2 := 3,
    TARGET3 := 4,
    TARGET4 := 5,
    TARGET5 := 6,
    TARGET6 := 7
);
END_TYPE

GVLs

Global_Version

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

GVL

{attribute 'qualified_only'}
VAR_GLOBAL
    {attribute 'pytmc' := 'pv: PLC:RIX:MOTION:ARB:01'}
    fbArbiter1: FB_Arbiter(1);
    {attribute 'pytmc' := 'pv: PLC:RIX:MOTION:ARB:02'}
    fbArbiter2: FB_Arbiter(2);

    // For devices between the mirror and the stopper
    {attribute 'pytmc' := 'pv: PLC:RIX:MOTION:FFO:01'}
    {attribute 'TcLinkTo' := '.q_xFastFaultOut:=TIIB[PMPS_FFO]^Channel 1^Output'}
    fbFastFaultOutput1: FB_HardwareFFOutput := (bAutoReset := TRUE, i_sNetID:='172.21.42.126.1.1');

    // For devices after the stopper
    {attribute 'pytmc' := 'pv: PLC:RIX:MOTION:FFO:02'}
    {attribute 'TcLinkTo' := '.q_xFastFaultOut:=TIIB[PMPS_FFO]^Channel 2^Output'}
    fbFastFaultOutput2: FB_HardwareFFOutput := (bAutoReset := TRUE, i_sNetID:='172.21.42.126.1.1');

    fbAtomicMass : FB_AtomicMass;
    fbAttenuatorElementDensity : FB_AttenuatorElementDensity;

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

END_VAR

VAR_GLOBAL CONSTANT
    iFiltersPerSATTBlade : INT := 8;
END_VAR
Related:

Main

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

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

    // SPARE (Previously ZOS)
    M3: DUT_MotionStage;

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

    // AL1K2-L2SI: 1 Axis
    {attribute 'pytmc' := 'pv: AL1K2:L2SI:MMS'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AL1K2-EL7041-E1]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[AL1K2-EL7041-E1]^STM Status^Status^Digital input 2;
                              .bBrakeRelease        := TIIB[AL1K2-EL2004-E3]^Channel 1^Output;
                              .nRawEncoderULINT     := TIIB[AL1K2-EL5042-E2]^FB Inputs Channel 1^Position'}
    M5: DUT_MotionStage := (sName := 'AL1K2:L2SI:MMS');

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

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

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

    // TM1K2: 2 Axes
    {attribute 'pytmc' := 'pv: TM1K2:ATM:MMS:Y'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[TM1K2-EL7041-E1]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[TM1K2-EL7041-E1]^STM Status^Status^Digital input 2;
                              .bBrakeRelease        := TIIB[TM1K2-EL2004-E4]^Channel 1^Output;
                              .nRawEncoderULINT     := TIIB[TM1K2-EL5042-E3]^FB Inputs Channel 1^Position'}
    M9: DUT_MotionStage := (sName := 'TM1K2:ATM:MMS:Y');
    {attribute 'pytmc' := 'pv: TM1K2:ATM:MMS:X'}
    {attribute 'TcLinkTo' := '.nRawEncoderULINT     := TIIB[TM1K2-EL5042-E3]^FB Inputs Channel 2^Position'}
    M10: DUT_MotionStage := (sName := 'TM1K2:ATM:MMS:X');

    // LI2K2-K2A_OUT: 1 Axis
    {attribute 'pytmc' := 'pv: LI2K2:K2A:MMS'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[LI2K2-EL7041-E1]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[LI2K2-EL7041-E1]^STM Status^Status^Digital input 2;
                              .bBrakeRelease        := TIIB[LI2K2-EL2004-E2]^Channel 1^Output;
                              .nRawEncoderULINT     := TIIB[LI2K2-EL5042-E3]^FB Inputs Channel 1^Position'}
    M11: DUT_MotionStage := (sName := 'LI2K2:K2A:MMS');

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

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

    // TM2K2: 2 Axes
    {attribute 'pytmc' := 'pv: TM2K2:ATM:MMS:Y'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[TM2K2-EL7041-E1]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[TM2K2-EL7041-E1]^STM Status^Status^Digital input 2;
                              .bBrakeRelease        := TIIB[TM2K2-EL2004-E4]^Channel 1^Output;
                              .nRawEncoderULINT     := TIIB[TM2K2-EL5042-E3]^FB Inputs Channel 1^Position'}
    M15: DUT_MotionStage := (sName := 'TM2K2:ATM:MMS:Y');
    {attribute 'pytmc' := 'pv: TM2K2:ATM:MMS:X'}
    {attribute 'TcLinkTo' := '.nRawEncoderULINT     := TIIB[TM2K2-EL5042-E3]^FB Inputs Channel 2^Position'}
    M16: DUT_MotionStage := (sName := 'TM2K2:ATM:MMS:X');

    //AT2K2: 4 Axes
(*

    AT2K2 Solid Attenuator notes (JJ-xray SN-11343)

    JJ    Label   EPICS    Stage     NC   Location

    1087      1   MMS:01   fbStage1  M17  Upstream-most
    1088      2   MMS:02   fbStage2  M18
    1086      3   MMS:03   fbStage3  M19
    1089      4   MMS:04   fbStage4  M20  Downstream-most

*)
    {attribute 'pytmc' := 'pv: AT2K2:L2SI:MMS:01'}
    {attribute 'TcLinkTo' := '
        .bLimitForwardEnable  := TIIB[AT2K2-EL7047-01]^STM Status^Status^Digital input 1;
        .bLimitBackwardEnable := TIIB[AT2K2-EL7047-01]^STM Status^Status^Digital input 2;
        .nRawEncoderULINT     := TIIB[AT2K2-EL5042-01]^FB Inputs Channel 1^Position;
    '}
    M17: DUT_MotionStage := (sName := 'AT2K2:L2SI:MMS:01');

    {attribute 'pytmc' := 'pv: AT2K2:L2SI:MMS:02'}
    {attribute 'TcLinkTo' := '
        .bLimitForwardEnable  := TIIB[AT2K2-EL7047-02]^STM Status^Status^Digital input 1;
        .bLimitBackwardEnable := TIIB[AT2K2-EL7047-02]^STM Status^Status^Digital input 2;
        .nRawEncoderULINT     := TIIB[AT2K2-EL5042-01]^FB Inputs Channel 2^Position;
    '}
    M18: DUT_MotionStage := (sName := 'AT2K2:L2SI:MMS:02');

    {attribute 'pytmc' := 'pv: AT2K2:L2SI:MMS:03'}
    {attribute 'TcLinkTo' := '
        .bLimitForwardEnable  := TIIB[AT2K2-EL7047-03]^STM Status^Status^Digital input 1;
        .bLimitBackwardEnable := TIIB[AT2K2-EL7047-03]^STM Status^Status^Digital input 2;
        .nRawEncoderULINT     := TIIB[AT2K2-EL5042-02]^FB Inputs Channel 1^Position;
    '}
    M19: DUT_MotionStage := (sName := 'AT2K2:L2SI:MMS:03');

    {attribute 'pytmc' := 'pv: AT2K2:L2SI:MMS:04'}
    {attribute 'TcLinkTo' := '
        .bLimitForwardEnable  := TIIB[AT2K2-EL7047-04]^STM Status^Status^Digital input 1;
        .bLimitBackwardEnable := TIIB[AT2K2-EL7047-04]^STM Status^Status^Digital input 2;
        .nRawEncoderULINT     := TIIB[AT2K2-EL5042-02]^FB Inputs Channel 2^Position;
    '}
    M20: DUT_MotionStage := (sName := 'AT2K2:L2SI:MMS:04');

    //LI3K2-K2B: 1 Axis
    {attribute 'pytmc' := 'pv: LI3K2:K2B:MMS'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[LI3K2-EL7041-E1]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[LI3K2-EL7041-E1]^STM Status^Status^Digital input 2;
                              .bBrakeRelease        := TIIB[LI3K2-EL2004-E3]^Channel 1^Output;
                              .nRawEncoderULINT     := TIIB[LI3K2-EL5042-E2]^FB Inputs Channel 1^Position'}
    M21: DUT_MotionStage := (sName := 'LI3K2:K2B:MMS');

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


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


    //AT1K2: Blade 1


    {attribute 'pytmc' := 'pv: AT1K2:L2SI:MMS:01'}
    {attribute 'TcLinkTo' := '
        .bLimitForwardEnable  := TIIB[AT1K2-EL7047-01]^STM Status^Status^Digital input 1;
        .bLimitBackwardEnable := TIIB[AT1K2-EL7047-01]^STM Status^Status^Digital input 2;
        .nRawEncoderULINT     := TIIB[AT1K2-EL5042-01]^FB Inputs Channel 1^Position';
    ;}
    M25: DUT_MotionStage := (sName := 'AT1K2:L2SI:MMS:01');

    //AT1K2: Blade 2

    {attribute 'pytmc' := 'pv: AT1K2:L2SI:MMS:02'}
    {attribute 'TcLinkTo' := '
        .bLimitForwardEnable  := TIIB[AT1K2-EL7047-02]^STM Status^Status^Digital input 1;
        .bLimitBackwardEnable := TIIB[AT1K2-EL7047-02]^STM Status^Status^Digital input 2;
        .nRawEncoderULINT     := TIIB[AT1K2-EL5042-01]^FB Inputs Channel 2^Position';
    ;}
    M26: DUT_MotionStage := (sName := 'AT1K2:L2SI:MMS:02');

    //AT1K2: Mirror

    {attribute 'pytmc' := 'pv: AT1K2:L2SI:MMS:03'}
    {attribute 'TcLinkTo' := '
        .nRawEncoderULINT     := TIIB[AT1K2-EL5042-02]^FB Inputs Channel 1^Position';
    ;}
    M27: DUT_MotionStage := (sName := 'AT1K2:L2SI:MMS:03');


END_VAR

POUs

FB_AT1K2

FUNCTION_BLOCK FB_AT1K2
VAR_IN_OUT
    fbFFHWO: FB_HardwareFFOutput;
    stAxis: DUT_MotionStage;
END_VAR
VAR_INPUT
    nEnableMode : ENUM_StageEnableMode;

    stOut           : DUT_PositionState;
    stIn        : DUT_PositionState;

END_VAR
VAR_OUTPUT
    fTransmission : LREAL;
    bMirrorOut : BOOL;

END_VAR
VAR
    fbMotion: FB_MotionStage;

    {attribute 'pytmc' := '
         pv: STATE
    '}

    fbState: FB_PositionStateInOut;

    bInitialized: BOOL := FALSE;

    fbFF: FB_FastFault := (i_Desc := 'Device is moving',
                       i_TypeCode := 16#2100,
                       i_xAutoReset := TRUE);
END_VAR
IF NOT bInitialized THEN
    bInitialized := TRUE;

    (* Defaults for DUT_MotionStage *)
    stAxis.bHardwareEnable      := TRUE;
    stAxis.bLimitBackwardEnable := TRUE;
    stAxis.bLimitForwardEnable  := TRUE;
    stAxis.bPowerSelf           := TRUE;
    stAxis.nBrakeMode           := ENUM_StageBrakeMode.NO_BRAKE;
    stAxis.nHomingMode          := ENUM_EpicsHomeCmd.NONE;

END_IF

stAxis.nEnableMode := nEnableMode;
fbMotion(stMotionStage:=stAxis);
fbState(
    bEnable:=TRUE,
    stMotionStage:=stAxis,
    stOut:=stOut,
    stIn:=stIn,
);

bMirrorOut := fbState.enumGet = ENUM_EpicsInOut.OUT;
// If Mirror is in, fTransmission of mirror is 0. If out, fTransmission is 1
IF bMirrorOut THEN
    fTransmission := 1.0;
ELSE
    fTransmission := 0.0;
END_IF


fbFF(
    i_DevName:=stAxis.sName,
    i_xOK:= fbState.enumGet = ENUM_EpicsInOut.OUT,
    io_fbFFHWO := fbFFHWO
);

END_FUNCTION_BLOCK

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_SXR_SATT_PositionState

FUNCTION_BLOCK FB_SXR_SATT_PositionState EXTENDS FB_PositionStateBase
VAR_INPUT
     // The enum position to move to
     {attribute 'pytmc' := '
         pv: SET
         io: io
     '}
     enumSet: ENUM_SXR_SATT_Position;

    // NOTE: Do not pragma these, let it happen in the manager.
     // Information about the OUT position
     stOut          : DUT_PositionState;
     stFilter1      : DUT_PositionState;
     stFilter2      : DUT_PositionState;
     stFilter3      : DUT_PositionState;
     stFilter4      : DUT_PositionState;
     stFilter5      : DUT_PositionState;
     stFilter6      : DUT_PositionState;
     stFilter7      : DUT_PositionState;
     stFilter8      : DUT_PositionState;

END_VAR
VAR_OUTPUT
    // The enum state readback
    {attribute 'pytmc' := '
        pv: GET
        io: i
    '}
    enumGet: ENUM_SXR_SATT_Position;

END_VAR
VAR
    bInitialized: BOOL := FALSE;
END_VAR
IF NOT bInitialized THEN
    bInitialized := TRUE;

    arrStates[1] := stOut;

    arrStates[2] := stFilter1;
    arrStates[3] := stFilter2;
    arrStates[4] := stFilter3;
    arrStates[5] := stFilter4;

    arrStates[6] := stFilter5;
    arrStates[7] := stFilter6;
    arrStates[8] := stFilter7;
    arrStates[9] := stFilter8;

END_IF
setState := enumSet;
Exec();
enumGet := getState;
enumSet := setState;

END_FUNCTION_BLOCK
Related:

FB_SXR_SATT_Stage

FUNCTION_BLOCK FB_SXR_SATT_Stage
VAR_IN_OUT
    stAxis : DUT_MotionStage;
    fbFFHWO: FB_HardwareFFOutput;
END_VAR
VAR_INPUT
    nEnableMode : ENUM_StageEnableMode;

    stOut           : DUT_PositionState;
    stFilter1       : DUT_PositionState;
    stFilter2       : DUT_PositionState;
    stFilter3       : DUT_PositionState;
    stFilter4       : DUT_PositionState;
    stFilter5       : DUT_PositionState;
    stFilter6       : DUT_PositionState;
    stFilter7       : DUT_PositionState;
    stFilter8       : DUT_PositionState;

    {attribute 'pytmc' := 'pv: FILTERS'}
    arrFilters: ARRAY[1..8] OF DUT_SATT_Filter;

END_VAR
VAR_OUTPUT
    // stExtra : DUT_MotionStage_Extras;
    fTemp1 : LREAL;
    fTemp2 : LREAL;
    bIsStationary : BOOL;
    bError : BOOL;

    {attribute 'pytmc' := '
        pv: MATERIAL
        io: i
    '}
    sActiveFilterMaterial : STRING;

    {attribute 'pytmc' := '
        pv: THICKNESS
        io: i
        field: EGU um
    '}
    fActiveFilterThickness_um : LREAL;

    {attribute 'pytmc' := '
        pv: TRANSMISSION
        io: i
        field: DESC Filter transmission
    '}
    fTransmission : LREAL;
    fActiveFilterDensity : LREAL;
    fActiveFilterAtomicMass : LREAL;
    fAbsorptionConstant : LREAL;

    iFilterIndex: INT := 0;

END_VAR
VAR
    fbMotion: FB_MotionStage;

    {attribute 'pytmc' := '
         pv: STATE
    '}
    fbState         : FB_SXR_SATT_PositionState;

    bInitialized: BOOL := FALSE;

    fbAtomicMass : FB_AtomicMass;
    fbAttenuatorElementDensity : FB_AttenuatorElementDensity;

    (* EL3202-0020: 0.01 °C per digit *)
    {attribute 'pytmc' := 'pv: RTD:1'}
    fbRTD_1: FB_TempSensor := ( fResolution:=0.01 );
    {attribute 'pytmc' := 'pv: RTD:2'}
    fbRTD_2: FB_TempSensor := ( fResolution:=0.01 );

    fbFF: FB_FastFault := (i_Desc := 'Device is moving',
                           i_TypeCode := 16#2100,
                           i_xAutoReset := TRUE);
END_VAR
IF NOT bInitialized THEN
    bInitialized := TRUE;

    (* Defaults for DUT_MotionStage *)
    stAxis.bHardwareEnable      := TRUE;
    stAxis.bLimitBackwardEnable := TRUE;
    stAxis.bLimitForwardEnable  := TRUE;
    stAxis.bPowerSelf           := TRUE;
    stAxis.nBrakeMode           := ENUM_StageBrakeMode.NO_BRAKE;
    stAxis.nHomingMode          := ENUM_EpicsHomeCmd.NONE;

    (* Defaults for visualization *)
    // stExtra.fVisuStep                    := 0.1;

END_IF

fbRTD_1();
fTemp1 := fbRTD_1.fTemp;

fbRTD_2();
fTemp2 := fbRTD_2.fTemp;

stAxis.nEnableMode := nEnableMode;
fbMotion(stMotionStage:=stAxis);
fbState(
    bEnable:=TRUE,
    stMotionStage:=stAxis,
    stOut:=stOut,
    stFilter1:=stFilter1,
    stFilter2:=stFilter2,
    stFilter3:=stFilter3,
    stFilter4:=stFilter4,
    stFilter5:=stFilter5,
    stFilter6:=stFilter6,
    stFilter7:=stFilter7,
    stFilter8:=stFilter8,
);

(* Filter indices are off by one due to "Out" being in position 1. *)
iFilterIndex := fbState.enumGet - 1;

IF iFilterIndex >= 1 AND iFilterIndex <= GVL.iFiltersPerSATTBlade THEN
    sActiveFilterMaterial := arrFilters[iFilterIndex].sFilterMaterial;
    fActiveFilterThickness_um := arrFilters[iFilterIndex].fFilterThickness_um;

    fbAtomicMass(sName:=sActiveFilterMaterial, fValue=>fActiveFilterAtomicMass);
    fbAttenuatorElementDensity(sName:=sActiveFilterMaterial, fDensity=>fActiveFilterDensity);

    fAbsorptionConstant := F_CalculateAbsorptionConstant(
        sElement:=sActiveFilterMaterial,
        fEnergyEV:=PMPS_GVL.stCurrentBeamParameters.neV,
        fDensity_gm3:=fActiveFilterDensity,
        fAtomicWeight:=fActiveFilterAtomicMass,
        bError=>bError,
    );
    fTransmission := F_CalculateTransmission(
        fAbsorptionConstant:=fAbsorptionConstant,
        fThickness_in_m:=fActiveFilterThickness_um * 1.0E-6
    );
ELSE
    sActiveFilterMaterial := '';
    fActiveFilterThickness_um := 0.0;
    fAbsorptionConstant := 0.0;
    fActiveFilterDensity := 0.0;
    fActiveFilterAtomicMass := 0.0;
    fTransmission := 1.0;
END_IF


bIsStationary := NOT stAxis.Axis.Status.Moving;
fbFF(
    i_DevName:=stAxis.sName,
    i_xOK:=bIsStationary AND fbState.enumGet <> ENUM_SXR_SATT_Position.UNKNOWN,
    io_fbFFHWO := fbFFHWO
);

// stExtra.bVisuHighLim := NOT stAxis.bAllForwardEnable;
// stExtra.bVisuLowLim := NOT stAxis.bAllBackwardEnable;

END_FUNCTION_BLOCK
Related:

FB_TM2K2

FUNCTION_BLOCK FB_TM2K2
(*
    Adapted from FB_ATM to:
    - Add stTarget6 to the inputs
    - Change the arrStates.array pragma from 1..6 to 1..7 (out and 6 in states, up from 5)
    - Swap out FB_ATM_States for FB_TM2K2_States
*)
VAR_IN_OUT
    stYStage: DUT_MotionStage;
    stXStage: DUT_MotionStage;
    fbArbiter: FB_Arbiter;
    fbFFHWO: FB_HardwareFFOutput;
END_VAR
VAR_INPUT
    stOut: DUT_PositionState;
    stTarget1: DUT_PositionState;
    stTarget2: DUT_PositionState;
    stTarget3: DUT_PositionState;
    stTarget4: DUT_PositionState;
    stTarget5: DUT_PositionState;
    stTarget6: DUT_PositionState;
    sPmpsDeviceName: STRING;
    sTransitionKey: STRING;
END_VAR
VAR
    fbYStage: FB_MotionStage;
    fbXStage: FB_MotionStage;

    {attribute 'pytmc' := '
        pv: MMS:STATE
        io: i
        arrStates.array: 1..7
    '}
    fbStates: FB_TM2K2_States;

    {attribute 'pytmc' := '
        pv: STC:01
        io: input
    '}
    fbThermoCouple1: FB_TempSensor;
END_VAR
fbYStage(stMotionStage:=stYStage);
stYStage.bHardwareEnable := TRUE;
stYStage.bPowerSelf := FALSE;
stYStage.nEnableMode := ENUM_StageEnableMode.DURING_MOTION;

fbXStage(stMotionStage:=stXStage);
stXStage.bLimitForwardEnable := TRUE;
stXStage.bLimitBackwardEnable := TRUE;
stXStage.bHardwareEnable := TRUE;
stXStage.bPowerSelf := TRUE;
stXStage.nEnableMode := ENUM_StageEnableMode.DURING_MOTION;

fbStates(
    fbArbiter:=fbArbiter,
    fbFFHWO:=fbFFHWO,
    stMotionStage:=stYStage,
    bEnable := TRUE,
    stOut:=stOut,
    stTarget1:=stTarget1,
    stTarget2:=stTarget2,
    stTarget3:=stTarget3,
    stTarget4:=stTarget4,
    stTarget5:=stTarget5,
    stTarget6:=stTarget6,
    sPmpsDeviceName:=sPmpsDeviceName,
    sTransitionKey:=sTransitionKey);

fbThermoCouple1();

END_FUNCTION_BLOCK
Related:

FB_TM2K2_States

FUNCTION_BLOCK FB_TM2K2_States EXTENDS FB_PositionStateBase_WithPMPS
// Adapted from TB_ATM_States to add TARGET6 and to switch the enumSet and enumGet ENUM types
VAR_INPUT
    {attribute 'pytmc' := '
        pv: SET
        io: io
    '}
    enumSet: ENUM_TM2K2_states;

    stOut: DUT_PositionState;
    stTarget1: DUT_PositionState;
    stTarget2: DUT_PositionState;
    stTarget3: DUT_PositionState;
    stTarget4: DUT_PositionState;
    stTarget5: DUT_PositionState;
    stTarget6: DUT_PositionState;

    bStatesLock: BOOL;
END_VAR
VAR_OUTPUT
    {attribute 'pytmc' := '
        pv: GET
        io: i
    '}
    enumGet: ENUM_TM2K2_States;
END_VAR
VAR
    bATMInit: BOOL;
END_VAR
VAR CONSTANT
    fInDelta: LREAL := 2;
    fOutDelta: LREAL := 2;
    fInVelocity: LREAL := 5;
    fOutVelocity: LREAL := 5;
    fAccel: LREAL := 200;
    fOutDecel: LREAL := 25;
END_VAR
IF NOT bATMInit THEN
    bATMInit := TRUE;

    stOut.sName := 'OUT';
    stOut.fVelocity := fOutVelocity;
    stOut.fDelta := fOutDelta;
    stOut.fAccel := fAccel;
    stOut.fDecel := fOutDecel;
    stOut.bMoveOk := TRUE;

    stTarget1.sName := 'TARGET1';
    stTarget1.fVelocity := fInVelocity;
    stTarget1.fDelta := fInDelta;
    stTarget1.fAccel := fAccel;
    stTarget1.fDecel := fAccel;
    stTarget1.bMoveOk := TRUE;

    stTarget2.sName := 'TARGET2';
    stTarget2.fVelocity := fInVelocity;
    stTarget2.fDelta := fInDelta;
    stTarget2.fAccel := fAccel;
    stTarget2.fDecel := fAccel;
    stTarget2.bMoveOk := TRUE;

    stTarget3.sName := 'TARGET3';
    stTarget3.fVelocity := fInVelocity;
    stTarget3.fDelta := fInDelta;
    stTarget3.fAccel := fAccel;
    stTarget3.fDecel := fAccel;
    stTarget3.bMoveOk := TRUE;

    stTarget4.sName := 'TARGET4';
    stTarget4.fVelocity := fInVelocity;
    stTarget4.fDelta := fInDelta;
    stTarget4.fAccel := fAccel;
    stTarget4.fDecel := fAccel;
    stTarget4.bMoveOk := TRUE;

    stTarget5.sName := 'TARGET5';
    stTarget5.fVelocity := fInVelocity;
    stTarget5.fDelta := fInDelta;
    stTarget5.fAccel := fAccel;
    stTarget5.fDecel := fAccel;
    stTarget5.bMoveOk := TRUE;

    stTarget6.sName := 'TARGET6';
    stTarget6.fVelocity := fInVelocity;
    stTarget6.fDelta := fInDelta;
    stTarget6.fAccel := fAccel;
    stTarget6.fDecel := fAccel;
    stTarget6.bMoveOk := TRUE;

    arrStates[1] := stOut;
    arrStates[2] := stTarget1;
    arrStates[3] := stTarget2;
    arrStates[4] := stTarget3;
    arrStates[5] := stTarget4;
    arrStates[6] := stTarget5;
    arrStates[7] := stTarget6;
END_IF

setState := enumSet;
Exec();
enumGet := getState;
enumSet := setState;

END_FUNCTION_BLOCK
Related:

PRG_1_PlcTask

PROGRAM PRG_1_PlcTask
VAR
    bDebug: BOOL := FALSE;
END_VAR
PRG_2_PMPS_PRE();

// Temporarily disable motors by setting bHardwareEnable to FALSE prior to running motion FB
//Main.M5.bHardwareEnable := bDebug;
//Main.M6.bHardwareEnable := bDebug;
//Main.M7.bHardwareEnable := bDebug;
//Main.M8.bHardwareEnable := bDebug;
//Main.M9.bHardwareEnable := bDebug;
//Main.M10.bHardwareEnable := bDebug;
//Main.M11.bHardwareEnable := bDebug;
//Main.M12.bHardwareEnable := bDebug;
//Main.M13.bHardwareEnable := bDebug;
//Main.M14.bHardwareEnable := bDebug;
//Main.M15.bHardwareEnable := bDebug;
//Main.M16.bHardwareEnable := bDebug;
// Note: AT2K2 has its own built-in debugging interface; see PRG_AT2K2_SOLID
// and its ``bDebug`` variable.

PRG_IM1K1_PPM();
PRG_IM2K1_PPM();
PRG_IM1K2_PPM();
PRG_AL1K2_L2SI();
PRG_IM2K2_PPM();
PRG_IM3K2_PPM();
PRG_IM4K2_PPM();
PRG_TM1K2_ATM();
PRG_LI2K2_K2A();
PRG_PF1K2_WFS();
PRG_IM5K2_PPM();
PRG_TM2K2_ATM();
PRG_AT1K2_SOLID();
PRG_AT2K2_SOLID();
PRG_LI3K2_K2B();
PRG_PF2K2_WFS();
PRG_IM6K2_PPM();

PRG_3_PMPS_POST();
PRG_4_LOG();

END_PROGRAM
Related:

PRG_2_PMPS_PRE

PROGRAM PRG_2_PMPS_PRE
VAR
END_VAR


END_PROGRAM

PRG_3_PMPS_POST

PROGRAM PRG_3_PMPS_POST
VAR
    fbArbiterIO: FB_SubSysToArbiter_IO;
    bMR1K1_Veto: BOOL;
    bST1K2_Veto: BOOL;
    bST1K2_Veto_Override: BOOL := FALSE;
    fb_vetoArbiter: FB_VetoArbiter;
    ff2_ff1_link_motion: FB_FastFault := (i_xAutoReset := TRUE, i_DevName := 'FF2 to FF1 Link Motion', i_Desc := 'Please DONT BYPASS ME!! This is virtual FF2 fault, Please check faulting motion devices', i_TypeCode := 16#FFFF);
END_VAR
bMR1K1_Veto := PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.K_Stopper.MR1K1_OUT] AND NOT PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.K_Stopper.MR1K1_IN];
bST1K2_Veto := bST1K2_Veto_Override OR PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.K_Stopper.ST1K2];

fbArbiterIO(
    i_bVeto:=bMR1K1_Veto,
    Arbiter:=GVL.fbArbiter1,
    fbFFHWO:=GVL.fbFastFaultOutput1);

GVL.fbFastFaultOutput1.Execute(i_xVeto:=bMR1K1_Veto);
GVL.fbFastFaultOutput2.Execute(i_xVeto:=bMR1K1_Veto OR bST1K2_Veto);

//create a preemptive request from Arbiter 2 in Arbiter 1
fb_vetoArbiter(bVeto:= bST1K2_Veto,
                HigherAuthority := GVL.fbArbiter1,
                LowerAuthority := GVL.fbArbiter2,
                FFO := GVL.fbFastFaultOutput2);

ff2_ff1_link_motion(
    io_fbFFHWO := GVL.fbFastFaultOutput1,
    i_xOK :=  GVL.fbFastFaultOutput2.q_xFastFaultOut OR bST1K2_Veto);


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

END_PROGRAM
Related:

PRG_4_LOG

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

END_PROGRAM

PRG_AL1K2_L2SI

PROGRAM PRG_AL1K2_L2SI
VAR
    {attribute 'pytmc' := '
        pv: AL1K2:L2SI
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbLaser.iLaserINT := TIIB[AL1K2-EL4004-E4]^AO Outputs Channel 1^Analog output;
                              .fbLaser.iShutdownINT := TIIB[AL1K2-EL4004-E4]^AO Outputs Channel 2^Analog output'}
    fbAL1K2: FB_REF;
END_VAR
fbAL1K2.stOut.fPosition := -33.5; // Upper limit
fbAL1K2.stOut.bUseRawCounts := FALSE;
fbAL1K2.stOut.bValid := TRUE;
fbAL1K2.stOut.stPMPS.sPmpsState := 'AL1K2:L2SI-OUT';

fbAL1K2.stIn.fPosition := -75; // Current position at time of edit
fbAL1K2.stIn.bUseRawCounts := FALSE;
fbAL1K2.stIn.bValid := TRUE;
fbAL1K2.stIn.stPMPS.sPmpsState := 'AL1K2:L2SI-IN';

fbAL1K2(
    stYStage := Main.M5,
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    sPmpsDeviceName := 'AL1K2:L2SI',
    sTransitionKey := 'AL1K2:L2SI-TRANSITION',
);

END_PROGRAM
Related:

PRG_AT1K2_SOLID

PROGRAM PRG_AT1K2_SOLID
VAR
    (* NOTE: use FALSE for simulation and production *)
    (* NOTE: use TRUE when relying on visualization + actual hardware *)
    bDebug : BOOL := FALSE;

    nEnableMode : ENUM_StageEnableMode;

    {attribute 'pytmc' := '
        pv: AT1K2:L2SI:MMS:01

    '}
    {attribute 'TcLinkTo' := '

        .fbRTD_1.iRaw := TIIB[AT1K2-EL3202-01]^RTD Inputs Channel 1^Value;
        .fbRTD_1.bError := TIIB[AT1K2-EL3202-01]^RTD Inputs Channel 1^Status^Error;
        .fbRTD_1.bUnderrange := TIIB[AT1K2-EL3202-01]^RTD Inputs Channel 1^Status^Underrange;
        .fbRTD_1.bOverrange := TIIB[AT1K2-EL3202-01]^RTD Inputs Channel 1^Status^Overrange;

        .fbRTD_2.iRaw := TIIB[AT1K2-EL3202-01]^RTD Inputs Channel 2^Value;
        .fbRTD_2.bError := TIIB[AT1K2-EL3202-01]^RTD Inputs Channel 2^Status^Error;
        .fbRTD_2.bUnderrange := TIIB[AT1K2-EL3202-01]^RTD Inputs Channel 2^Status^Underrange;
        .fbRTD_2.bOverrange := TIIB[AT1K2-EL3202-01]^RTD Inputs Channel 2^Status^Overrange;

    '}
    fbStage1: FB_SXR_SATT_Stage;

    {attribute 'pytmc' := 'pv: AT1K2:L2SI:MMS:02'}
    {attribute 'TcLinkTo' := '

        .fbRTD_1.iRaw := TIIB[AT1K2-EL3202-02]^RTD Inputs Channel 1^Value;
        .fbRTD_1.bError := TIIB[AT1K2-EL3202-02]^RTD Inputs Channel 1^Status^Error;
        .fbRTD_1.bUnderrange := TIIB[AT1K2-EL3202-02]^RTD Inputs Channel 1^Status^Underrange;
        .fbRTD_1.bOverrange := TIIB[AT1K2-EL3202-02]^RTD Inputs Channel 1^Status^Overrange;

        .fbRTD_2.iRaw := TIIB[AT1K2-EL3202-02]^RTD Inputs Channel 2^Value;
        .fbRTD_2.bError := TIIB[AT1K2-EL3202-02]^RTD Inputs Channel 2^Status^Error;
        .fbRTD_2.bUnderrange := TIIB[AT1K2-EL3202-02]^RTD Inputs Channel 2^Status^Underrange;
        .fbRTD_2.bOverrange := TIIB[AT1K2-EL3202-02]^RTD Inputs Channel 2^Status^Overrange;
    '}
    fbStage2: FB_SXR_SATT_Stage;

    {attribute 'pytmc' := 'pv: AT1K2:L2SI:MMS:03'}

    fbStage3: FB_AT1K2;

END_VAR
VAR CONSTANT
    DEFAULT_VELOCITY : LREAL := 1;
END_VAR
IF bDebug THEN
    // NEVER: checkouts with the TwinCAT NC GUI.
    nEnableMode := ENUM_StageEnableMode.NEVER;
ELSE
    // ALWAYS: want active position correction at all times
    nEnableMode := ENUM_StageEnableMode.ALWAYS;
END_IF

(*

    Solid Attenuator notes

    AT1K2 is JJ-xray SN-11343.

    JJ    Label   EPICS    Stage     NC   Location

    10XX      1   MMS:01   fbStage1  M25  Upstream-most
    10XX      2   MMS:02   fbStage2  M26  Downstream-most
    10XX      3   MMS:03   fbStage3  M27  Mirror Insertion Stage

*)
(* State setup - stage 1 *)
fbStage1.stOut.sName         := 'Out';
fbStage1.stOut.fPosition     := 66.00;
fbStage1.stOut.fDelta        := 0.2;
fbStage1.stOut.fVelocity     := DEFAULT_VELOCITY;
fbStage1.stOut.bValid        := TRUE;
fbStage1.stOut.bMoveOk       := TRUE;

fbStage1.stFilter1.sName                   := 'Filter 1';
fbStage1.stFilter1.fPosition               := 500.0;
fbStage1.stFilter1.fDelta                  := 0.2;
fbStage1.stFilter1.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter1.bValid                  := FALSE;
fbStage1.stFilter1.bMoveOk                 := FALSE;
fbStage1.arrFilters[1].fFilterThickness_um := 0;
fbStage1.arrFilters[1].sFilterMaterial     := '';

fbStage1.stFilter2.sName                   := 'Filter 2';
fbStage1.stFilter2.fPosition               := 500.0;
fbStage1.stFilter2.fDelta                  := 0.2;
fbStage1.stFilter2.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter2.bValid                  := FALSE;
fbStage1.stFilter2.bMoveOk                 := FALSE;
fbStage1.arrFilters[2].fFilterThickness_um := 0;
fbStage1.arrFilters[2].sFilterMaterial     := '';

fbStage1.stFilter3.sName                   := '(3) 11.5 um Al';
fbStage1.stFilter3.fPosition               := 75.0;
fbStage1.stFilter3.fDelta                  := 0.2;
fbStage1.stFilter3.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter3.bValid                  := TRUE;
fbStage1.stFilter3.bMoveOk                 := TRUE;
fbStage1.arrFilters[3].fFilterThickness_um := 11.5;
fbStage1.arrFilters[3].sFilterMaterial     := 'Al';

fbStage1.stFilter4.sName                   := '(4) 6.18 um Al';
fbStage1.stFilter4.fPosition               := 90.5;
fbStage1.stFilter4.fDelta                  := 0.2;
fbStage1.stFilter4.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter4.bValid                  := TRUE;
fbStage1.stFilter4.bMoveOk                 := TRUE;
fbStage1.arrFilters[4].fFilterThickness_um := 6.18;
fbStage1.arrFilters[4].sFilterMaterial     := 'Al';

fbStage1.stFilter5.sName                   := '(5) 2.85 um Al';
fbStage1.stFilter5.fPosition               := 105.5;
fbStage1.stFilter5.fDelta                  := 0.2;
fbStage1.stFilter5.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter5.bValid                  := TRUE;
fbStage1.stFilter5.bMoveOk                 := TRUE;
fbStage1.arrFilters[5].fFilterThickness_um := 2.85;
fbStage1.arrFilters[5].sFilterMaterial     := 'Al';

fbStage1.stFilter6.sName                   := '(6) 1.52 um Al';
fbStage1.stFilter6.fPosition               := 122.0;
fbStage1.stFilter6.fDelta                  := 0.2;
fbStage1.stFilter6.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter6.bValid                  := TRUE;
fbStage1.stFilter6.bMoveOk                 := TRUE;
fbStage1.arrFilters[6].fFilterThickness_um := 1.52;
fbStage1.arrFilters[6].sFilterMaterial     := 'Al';

fbStage1.stFilter7.sName                   := '(7) 0.78 um Al';
fbStage1.stFilter7.fPosition               := 136.5;
fbStage1.stFilter7.fDelta                  := 0.2;
fbStage1.stFilter7.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter7.bValid                  := TRUE;
fbStage1.stFilter7.bMoveOk                 := TRUE;
fbStage1.arrFilters[7].fFilterThickness_um := 0.78;
fbStage1.arrFilters[7].sFilterMaterial     := 'Al';

fbStage1.stFilter8.sName                   := '(8) 0.39 um Al';
fbStage1.stFilter8.fPosition               := 152.2;
fbStage1.stFilter8.fDelta                  := 0.2;
fbStage1.stFilter8.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter8.bValid                  := TRUE;
fbStage1.stFilter8.bMoveOk                 := TRUE;
fbStage1.arrFilters[8].fFilterThickness_um := 0.39;
fbStage1.arrFilters[8].sFilterMaterial     := 'Al';

fbStage1(stAxis:=Main.M25, nEnableMode:=nEnableMode, fbFFHWO:=GVL.fbFastFaultOutput2);


(* State setup - stage 2 *)
fbStage2.stOut.sName         := 'Out';
fbStage2.stOut.fPosition     := 66.00;
fbStage2.stOut.fDelta        := 0.2;
fbStage2.stOut.fVelocity     := DEFAULT_VELOCITY;
fbStage2.stOut.bValid        := TRUE;
fbStage2.stOut.bMoveOk       := TRUE;

fbStage2.stFilter1.sName                   := 'Filter 1';
fbStage2.stFilter1.fPosition               := 500.0;
fbStage2.stFilter1.fDelta                  := 0.2;
fbStage2.stFilter1.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter1.bValid                  := FALSE;
fbStage2.stFilter1.bMoveOk                 := FALSE;
fbStage2.arrFilters[1].fFilterThickness_um := 0;
fbStage2.arrFilters[1].sFilterMaterial     := '';

fbStage2.stFilter2.sName                   := 'Filter 2';
fbStage2.stFilter2.fPosition               := 500.0;
fbStage2.stFilter2.fDelta                  := 0.2;
fbStage2.stFilter2.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter2.bValid                  := FALSE;
fbStage2.stFilter2.bMoveOk                 := FALSE;
fbStage2.arrFilters[2].fFilterThickness_um := 0;
fbStage2.arrFilters[2].sFilterMaterial     := '';

fbStage2.stFilter3.sName                   := '(3) 11.5 um Al';
fbStage2.stFilter3.fPosition               := 75.0;
fbStage2.stFilter3.fDelta                  := 0.2;
fbStage2.stFilter3.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter3.bValid                  := TRUE;
fbStage2.stFilter3.bMoveOk                 := TRUE;
fbStage2.arrFilters[3].fFilterThickness_um := 11.5;
fbStage2.arrFilters[3].sFilterMaterial     := 'Al';

fbStage2.stFilter4.sName                   := '(4) 6.18 um Al';
fbStage2.stFilter4.fPosition               := 90.5;
fbStage2.stFilter4.fDelta                  := 0.2;
fbStage2.stFilter4.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter4.bValid                  := TRUE;
fbStage2.stFilter4.bMoveOk                 := TRUE;
fbStage2.arrFilters[4].fFilterThickness_um := 6.18;
fbStage2.arrFilters[4].sFilterMaterial     := 'Al';

fbStage2.stFilter5.sName                   := '(5) 1.52 um Al';
fbStage2.stFilter5.fPosition               := 105.5;
fbStage2.stFilter5.fDelta                  := 0.2;
fbStage2.stFilter5.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter5.bValid                  := TRUE;
fbStage2.stFilter5.bMoveOk                 := TRUE;
fbStage2.arrFilters[5].fFilterThickness_um := 1.52;
fbStage2.arrFilters[5].sFilterMaterial     := 'Al';

fbStage2.stFilter6.sName                   := '(6) 0.78 um Al';
fbStage2.stFilter6.fPosition               := 122.0;
fbStage2.stFilter6.fDelta                  := 0.2;
fbStage2.stFilter6.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter6.bValid                  := TRUE;
fbStage2.stFilter6.bMoveOk                 := TRUE;
fbStage2.arrFilters[6].fFilterThickness_um := 0.78;
fbStage2.arrFilters[6].sFilterMaterial     := 'Al';

fbStage2.stFilter7.sName                   := '(7) 0.39 um Al';
fbStage2.stFilter7.fPosition               := 136.5;
fbStage2.stFilter7.fDelta                  := 0.2;
fbStage2.stFilter7.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter7.bValid                  := TRUE;
fbStage2.stFilter7.bMoveOk                 := TRUE;
fbStage2.arrFilters[7].fFilterThickness_um := 0.39;
fbStage2.arrFilters[7].sFilterMaterial     := 'Al';

fbStage2.stFilter8.sName                   := '(8) 0.2 um Al';
fbStage2.stFilter8.fPosition               := 152.2;
fbStage2.stFilter8.fDelta                  := 0.2;
fbStage2.stFilter8.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter8.bValid                  := TRUE;
fbStage2.stFilter8.bMoveOk                 := TRUE;
fbStage2.arrFilters[8].fFilterThickness_um := 0.2;
fbStage2.arrFilters[8].sFilterMaterial     := 'Al';

fbStage2(stAxis:=Main.M26, nEnableMode:=nEnableMode, fbFFHWO:=GVL.fbFastFaultOutput2);



(* State setup - stage 3 *)
fbStage3.stOut.sName         := 'Out';
fbStage3.stOut.fPosition     := 65.00;
fbStage3.stOut.fDelta        := 0.2;
fbStage3.stOut.fVelocity     := DEFAULT_VELOCITY;
fbStage3.stOut.bValid        := TRUE;
fbStage3.stOut.bMoveOk       := TRUE;

fbStage3.stIn.sName         := 'In';
fbStage3.stIn.fPosition     := 25.00;
fbStage3.stIn.fDelta        := 0.2;
fbStage3.stIn.fVelocity     := DEFAULT_VELOCITY;
fbStage3.stIn.bValid        := TRUE;
fbStage3.stIn.bMoveOk       := TRUE;

fbStage3(stAxis:=Main.M27, fbFFHWO:=GVL.fbFastFaultOutput2);



GVL.rCurTrans[PMPS.K_Attenuators.AT1K2].nTran := LREAL_TO_REAL(
    fbStage1.fTransmission *
    fbStage2.fTransmission *
    fbStage3.fTransmission

);

END_PROGRAM
Related:

PRG_AT2K2_SOLID

PROGRAM PRG_AT2K2_SOLID
VAR
    (* NOTE: use FALSE for simulation and production *)
    (* NOTE: use TRUE when relying on visualization + actual hardware *)
    bDebug : BOOL := FALSE;

    nEnableMode : ENUM_StageEnableMode;

    {attribute 'pytmc' := '
        pv: AT2K2:L2SI:MMS:01

    '}
    {attribute 'TcLinkTo' := '

        .fbRTD_1.iRaw := TIIB[AT2K2-EL3202-04]^RTD Inputs Channel 1^Value;
        .fbRTD_1.bError := TIIB[AT2K2-EL3202-04]^RTD Inputs Channel 1^Status^Error;
        .fbRTD_1.bUnderrange := TIIB[AT2K2-EL3202-04]^RTD Inputs Channel 1^Status^Underrange;
        .fbRTD_1.bOverrange := TIIB[AT2K2-EL3202-04]^RTD Inputs Channel 1^Status^Overrange;

        .fbRTD_2.iRaw := TIIB[AT2K2-EL3202-04]^RTD Inputs Channel 2^Value;
        .fbRTD_2.bError := TIIB[AT2K2-EL3202-04]^RTD Inputs Channel 2^Status^Error;
        .fbRTD_2.bUnderrange := TIIB[AT2K2-EL3202-04]^RTD Inputs Channel 2^Status^Underrange;
        .fbRTD_2.bOverrange := TIIB[AT2K2-EL3202-04]^RTD Inputs Channel 2^Status^Overrange;

    '}
    fbStage1: FB_SXR_SATT_Stage;

    {attribute 'pytmc' := 'pv: AT2K2:L2SI:MMS:02'}
    {attribute 'TcLinkTo' := '

        .fbRTD_1.iRaw := TIIB[AT2K2-EL3202-03]^RTD Inputs Channel 1^Value;
        .fbRTD_1.bError := TIIB[AT2K2-EL3202-03]^RTD Inputs Channel 1^Status^Error;
        .fbRTD_1.bUnderrange := TIIB[AT2K2-EL3202-03]^RTD Inputs Channel 1^Status^Underrange;
        .fbRTD_1.bOverrange := TIIB[AT2K2-EL3202-03]^RTD Inputs Channel 1^Status^Overrange;

        .fbRTD_2.iRaw := TIIB[AT2K2-EL3202-03]^RTD Inputs Channel 2^Value;
        .fbRTD_2.bError := TIIB[AT2K2-EL3202-03]^RTD Inputs Channel 2^Status^Error;
        .fbRTD_2.bUnderrange := TIIB[AT2K2-EL3202-03]^RTD Inputs Channel 2^Status^Underrange;
        .fbRTD_2.bOverrange := TIIB[AT2K2-EL3202-03]^RTD Inputs Channel 2^Status^Overrange;

    '}
    fbStage2: FB_SXR_SATT_Stage;

    {attribute 'pytmc' := 'pv: AT2K2:L2SI:MMS:03'}
    {attribute 'TcLinkTo' := '

        .fbRTD_1.iRaw := TIIB[AT2K2-EL3202-02]^RTD Inputs Channel 1^Value;
        .fbRTD_1.bError := TIIB[AT2K2-EL3202-02]^RTD Inputs Channel 1^Status^Error;
        .fbRTD_1.bUnderrange := TIIB[AT2K2-EL3202-02]^RTD Inputs Channel 1^Status^Underrange;
        .fbRTD_1.bOverrange := TIIB[AT2K2-EL3202-02]^RTD Inputs Channel 1^Status^Overrange;

        .fbRTD_2.iRaw := TIIB[AT2K2-EL3202-02]^RTD Inputs Channel 2^Value;
        .fbRTD_2.bError := TIIB[AT2K2-EL3202-02]^RTD Inputs Channel 2^Status^Error;
        .fbRTD_2.bUnderrange := TIIB[AT2K2-EL3202-02]^RTD Inputs Channel 2^Status^Underrange;
        .fbRTD_2.bOverrange := TIIB[AT2K2-EL3202-02]^RTD Inputs Channel 2^Status^Overrange;
    '}
    fbStage3: FB_SXR_SATT_Stage;

    {attribute 'pytmc' := 'pv: AT2K2:L2SI:MMS:04'}
    {attribute 'TcLinkTo' := '

        .fbRTD_1.iRaw := TIIB[AT2K2-EL3202-01]^RTD Inputs Channel 1^Value;
        .fbRTD_1.bError := TIIB[AT2K2-EL3202-01]^RTD Inputs Channel 1^Status^Error;
        .fbRTD_1.bUnderrange := TIIB[AT2K2-EL3202-01]^RTD Inputs Channel 1^Status^Underrange;
        .fbRTD_1.bOverrange := TIIB[AT2K2-EL3202-01]^RTD Inputs Channel 1^Status^Overrange;

        .fbRTD_2.iRaw := TIIB[AT2K2-EL3202-01]^RTD Inputs Channel 2^Value;
        .fbRTD_2.bError := TIIB[AT2K2-EL3202-01]^RTD Inputs Channel 2^Status^Error;
        .fbRTD_2.bUnderrange := TIIB[AT2K2-EL3202-01]^RTD Inputs Channel 2^Status^Underrange;
        .fbRTD_2.bOverrange := TIIB[AT2K2-EL3202-01]^RTD Inputs Channel 2^Status^Overrange;
    '}
    fbStage4: FB_SXR_SATT_Stage;

END_VAR
VAR CONSTANT
    DEFAULT_VELOCITY : LREAL := 1;
END_VAR
IF bDebug THEN
    // NEVER: checkouts with the TwinCAT NC GUI.
    nEnableMode := ENUM_StageEnableMode.NEVER;
ELSE
    // ALWAYS: want active position correction at all times
    nEnableMode := ENUM_StageEnableMode.ALWAYS;
END_IF

(*

    Solid Attenuator notes

    AT2K2 is JJ-xray SN-11343.

    JJ    Label   EPICS    Stage     NC   Location

    1087      1   MMS:01   fbStage1  M17  Upstream-most
    1088      2   MMS:02   fbStage2  M18
    1086      3   MMS:03   fbStage3  M19
    1089      4   MMS:04   fbStage4  M20  Downstream-most

*)



(* State setup - stage 1 *)
fbStage1.stOut.sName         := 'Out';
fbStage1.stOut.fPosition     := 27.00;
fbStage1.stOut.fDelta        := 0.2;
fbStage1.stOut.fVelocity     := DEFAULT_VELOCITY;
fbStage1.stOut.bValid        := TRUE;
fbStage1.stOut.bMoveOk       := TRUE;

fbStage1.stFilter1.sName                   := 'Filter 1';
fbStage1.stFilter1.fPosition               := 500.0;
fbStage1.stFilter1.fDelta                  := 0.2;
fbStage1.stFilter1.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter1.bValid                  := FALSE;
fbStage1.stFilter1.bMoveOk                 := FALSE;
fbStage1.arrFilters[1].fFilterThickness_um := 0;
fbStage1.arrFilters[1].sFilterMaterial     := '';

fbStage1.stFilter2.sName                   := 'Filter 2';
fbStage1.stFilter2.fPosition               := 500.0;
fbStage1.stFilter2.fDelta                  := 0.2;
fbStage1.stFilter2.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter2.bValid                  := FALSE;
fbStage1.stFilter2.bMoveOk                 := FALSE;
fbStage1.arrFilters[2].fFilterThickness_um := 0;
fbStage1.arrFilters[2].sFilterMaterial     := '';

fbStage1.stFilter3.sName                   := 'Filter 3';
fbStage1.stFilter3.fPosition               := 500.0;
fbStage1.stFilter3.fDelta                  := 0.2;
fbStage1.stFilter3.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter3.bValid                  := FALSE;
fbStage1.stFilter3.bMoveOk                 := FALSE;
fbStage1.arrFilters[3].fFilterThickness_um := 0;
fbStage1.arrFilters[3].sFilterMaterial     := '';

fbStage1.stFilter4.sName                   := 'Filter 4';
fbStage1.stFilter4.fPosition               := 500.0;
fbStage1.stFilter4.fDelta                  := 0.2;
fbStage1.stFilter4.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter4.bValid                  := FALSE;
fbStage1.stFilter4.bMoveOk                 := FALSE;
fbStage1.arrFilters[4].fFilterThickness_um := 0;
fbStage1.arrFilters[4].sFilterMaterial     := '';

fbStage1.stFilter5.sName                   := '(5) 11.5 um Al';
fbStage1.stFilter5.fPosition               := 103.0;
fbStage1.stFilter5.fDelta                  := 0.2;
fbStage1.stFilter5.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter5.bValid                  := TRUE;
fbStage1.stFilter5.bMoveOk                 := TRUE;
fbStage1.arrFilters[5].fFilterThickness_um := 11.5;
fbStage1.arrFilters[5].sFilterMaterial     := 'Al';

fbStage1.stFilter6.sName                   := '(6) 6.18 um Al';
fbStage1.stFilter6.fPosition               := 119.0;
fbStage1.stFilter6.fDelta                  := 0.2;
fbStage1.stFilter6.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter6.bValid                  := TRUE;
fbStage1.stFilter6.bMoveOk                 := TRUE;
fbStage1.arrFilters[6].fFilterThickness_um := 6.18;
fbStage1.arrFilters[6].sFilterMaterial     := 'Al';

fbStage1.stFilter7.sName                   := '(7) 2.85 um Al';
fbStage1.stFilter7.fPosition               := 135.0;
fbStage1.stFilter7.fDelta                  := 0.2;
fbStage1.stFilter7.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter7.bValid                  := TRUE;
fbStage1.stFilter7.bMoveOk                 := TRUE;
fbStage1.arrFilters[7].fFilterThickness_um := 2.85;
fbStage1.arrFilters[7].sFilterMaterial     := 'Al';

fbStage1.stFilter8.sName                   := '(8) 1.52 um Al';
fbStage1.stFilter8.fPosition               := 150.0;
fbStage1.stFilter8.fDelta                  := 0.2;
fbStage1.stFilter8.fVelocity               := DEFAULT_VELOCITY;
fbStage1.stFilter8.bValid                  := TRUE;
fbStage1.stFilter8.bMoveOk                 := TRUE;
fbStage1.arrFilters[8].fFilterThickness_um := 1.52;
fbStage1.arrFilters[8].sFilterMaterial     := 'Al';

fbStage1(stAxis:=Main.M17, nEnableMode:=nEnableMode, fbFFHWO:=GVL.fbFastFaultOutput2);


(* State setup - stage 2 *)
fbStage2.stOut.sName         := 'Out';
fbStage2.stOut.fPosition     := 27.72;
fbStage2.stOut.fDelta        := 0.2;
fbStage2.stOut.fVelocity     := DEFAULT_VELOCITY;
fbStage2.stOut.bValid        := TRUE;
fbStage2.stOut.bMoveOk       := TRUE;

fbStage2.stFilter1.sName                   := 'Filter 1';
fbStage2.stFilter1.fPosition               := 500.0;
fbStage2.stFilter1.fDelta                  := 0.2;
fbStage2.stFilter1.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter1.bValid                  := FALSE;
fbStage2.stFilter1.bMoveOk                 := FALSE;
fbStage2.arrFilters[1].fFilterThickness_um := 0;
fbStage2.arrFilters[1].sFilterMaterial     := '';

fbStage2.stFilter2.sName                   := 'Filter 2';
fbStage2.stFilter2.fPosition               := 500.0;
fbStage2.stFilter2.fDelta                  := 0.2;
fbStage2.stFilter2.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter2.bValid                  := FALSE;
fbStage2.stFilter2.bMoveOk                 := FALSE;
fbStage2.arrFilters[2].fFilterThickness_um := 0;
fbStage2.arrFilters[2].sFilterMaterial     := '';

fbStage2.stFilter3.sName                   := 'Filter 3';
fbStage2.stFilter3.fPosition               := 500.0;
fbStage2.stFilter3.fDelta                  := 0.2;
fbStage2.stFilter3.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter3.bValid                  := FALSE;
fbStage2.stFilter3.bMoveOk                 := FALSE;
fbStage2.arrFilters[3].fFilterThickness_um := 0;
fbStage2.arrFilters[3].sFilterMaterial     := '';

fbStage2.stFilter4.sName                   := 'Filter 4';
fbStage2.stFilter4.fPosition               := 500.0;
fbStage2.stFilter4.fDelta                  := 0.2;
fbStage2.stFilter4.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter4.bValid                  := FALSE;
fbStage2.stFilter4.bMoveOk                 := FALSE;
fbStage2.arrFilters[4].fFilterThickness_um := 0;
fbStage2.arrFilters[4].sFilterMaterial     := '';

fbStage2.stFilter5.sName                   := '(5) 6.18 um Al';
fbStage2.stFilter5.fPosition               := 103.0;
fbStage2.stFilter5.fDelta                  := 0.2;
fbStage2.stFilter5.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter5.bValid                  := TRUE;
fbStage2.stFilter5.bMoveOk                 := TRUE;
fbStage2.arrFilters[5].fFilterThickness_um := 6.18;
fbStage2.arrFilters[5].sFilterMaterial     := 'Al';

fbStage2.stFilter6.sName                   := '(6) 2.85 um Al';
fbStage2.stFilter6.fPosition               := 119.0;
fbStage2.stFilter6.fDelta                  := 0.2;
fbStage2.stFilter6.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter6.bValid                  := TRUE;
fbStage2.stFilter6.bMoveOk                 := TRUE;
fbStage2.arrFilters[6].fFilterThickness_um := 2.85;
fbStage2.arrFilters[6].sFilterMaterial     := 'Al';

fbStage2.stFilter7.sName                   := '(7) 1.52 um Al';
fbStage2.stFilter7.fPosition               := 135.0;
fbStage2.stFilter7.fDelta                  := 0.2;
fbStage2.stFilter7.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter7.bValid                  := TRUE;
fbStage2.stFilter7.bMoveOk                 := TRUE;
fbStage2.arrFilters[7].fFilterThickness_um := 1.52;
fbStage2.arrFilters[7].sFilterMaterial     := 'Al';

fbStage2.stFilter8.sName                   := '(8) 0.78 um Al';
fbStage2.stFilter8.fPosition               := 150.0;
fbStage2.stFilter8.fDelta                  := 0.2;
fbStage2.stFilter8.fVelocity               := DEFAULT_VELOCITY;
fbStage2.stFilter8.bValid                  := TRUE;
fbStage2.stFilter8.bMoveOk                 := TRUE;
fbStage2.arrFilters[8].fFilterThickness_um := 0.78;
fbStage2.arrFilters[8].sFilterMaterial     := 'Al';

fbStage2(stAxis:=Main.M18, nEnableMode:=nEnableMode, fbFFHWO:=GVL.fbFastFaultOutput2);


(* State setup - stage 3 *)
fbStage3.stOut.sName         := 'Out';
fbStage3.stOut.fPosition     := 27.00;
fbStage3.stOut.fDelta        := 0.2;
fbStage3.stOut.fVelocity     := DEFAULT_VELOCITY;
fbStage3.stOut.bValid        := TRUE;
fbStage3.stOut.bMoveOk       := TRUE;

fbStage3.stFilter1.sName                   := 'Filter 1';
fbStage3.stFilter1.fPosition               := 500.0;
fbStage3.stFilter1.fDelta                  := 0.2;
fbStage3.stFilter1.fVelocity               := DEFAULT_VELOCITY;
fbStage3.stFilter1.bValid                  := FALSE;
fbStage3.stFilter1.bMoveOk                 := FALSE;
fbStage3.arrFilters[1].fFilterThickness_um := 0;
fbStage3.arrFilters[1].sFilterMaterial     := '';

fbStage3.stFilter2.sName                   := 'Filter 2';
fbStage3.stFilter2.fPosition               := 500.0;
fbStage3.stFilter2.fDelta                  := 0.2;
fbStage3.stFilter2.fVelocity               := DEFAULT_VELOCITY;
fbStage3.stFilter2.bValid                  := FALSE;
fbStage3.stFilter2.bMoveOk                 := FALSE;
fbStage3.arrFilters[2].fFilterThickness_um := 0;
fbStage3.arrFilters[2].sFilterMaterial     := '';

fbStage3.stFilter3.sName                   := 'Filter 3';
fbStage3.stFilter3.fPosition               := 500.0;
fbStage3.stFilter3.fDelta                  := 0.2;
fbStage3.stFilter3.fVelocity               := DEFAULT_VELOCITY;
fbStage3.stFilter3.bValid                  := FALSE;
fbStage3.stFilter3.bMoveOk                 := FALSE;
fbStage3.arrFilters[3].fFilterThickness_um := 0;
fbStage3.arrFilters[3].sFilterMaterial     := '';

fbStage3.stFilter4.sName                   := 'Filter 4';
fbStage3.stFilter4.fPosition               := 500.0;
fbStage3.stFilter4.fDelta                  := 0.2;
fbStage3.stFilter4.fVelocity               := DEFAULT_VELOCITY;
fbStage3.stFilter4.bValid                  := FALSE;
fbStage3.stFilter4.bMoveOk                 := FALSE;
fbStage3.arrFilters[4].fFilterThickness_um := 0;
fbStage3.arrFilters[4].sFilterMaterial     := '';

fbStage3.stFilter5.sName                   := '(5) 2.85 um Al';
fbStage3.stFilter5.fPosition               := 103.0;
fbStage3.stFilter5.fDelta                  := 0.2;
fbStage3.stFilter5.fVelocity               := DEFAULT_VELOCITY;
fbStage3.stFilter5.bValid                  := TRUE;
fbStage3.stFilter5.bMoveOk                 := TRUE;
fbStage3.arrFilters[5].fFilterThickness_um := 2.85;
fbStage3.arrFilters[5].sFilterMaterial     := 'Al';

fbStage3.stFilter6.sName                   := '(6) 1.52 um Al';
fbStage3.stFilter6.fPosition               := 119.0;
fbStage3.stFilter6.fDelta                  := 0.2;
fbStage3.stFilter6.fVelocity               := DEFAULT_VELOCITY;
fbStage3.stFilter6.bValid                  := TRUE;
fbStage3.stFilter6.bMoveOk                 := TRUE;
fbStage3.arrFilters[6].fFilterThickness_um := 1.52;
fbStage3.arrFilters[6].sFilterMaterial     := 'Al';

fbStage3.stFilter7.sName                   := '(7) 0.78 um Al';
fbStage3.stFilter7.fPosition               := 135.0;
fbStage3.stFilter7.fDelta                  := 0.2;
fbStage3.stFilter7.fVelocity               := DEFAULT_VELOCITY;
fbStage3.stFilter7.bValid                  := TRUE;
fbStage3.stFilter7.bMoveOk                 := TRUE;
fbStage3.arrFilters[7].fFilterThickness_um := 0.78;
fbStage3.arrFilters[7].sFilterMaterial     := 'Al';

fbStage3.stFilter8.sName                   := '(8) 0.39 um Al';
fbStage3.stFilter8.fPosition               := 150.0;
fbStage3.stFilter8.fDelta                  := 0.2;
fbStage3.stFilter8.fVelocity               := DEFAULT_VELOCITY;
fbStage3.stFilter8.bValid                  := TRUE;
fbStage3.stFilter8.bMoveOk                 := TRUE;
fbStage3.arrFilters[8].fFilterThickness_um := 0.39;
fbStage3.arrFilters[8].sFilterMaterial     := 'Al';

fbStage3(stAxis:=Main.M19, nEnableMode:=nEnableMode, fbFFHWO:=GVL.fbFastFaultOutput2);


(* State setup - stage 4 *)
fbStage4.stOut.sName         := 'Out';
fbStage4.stOut.fPosition     := 28.03;
fbStage4.stOut.fDelta        := 0.2;
fbStage4.stOut.fVelocity     := DEFAULT_VELOCITY;
fbStage4.stOut.bValid        := TRUE;
fbStage4.stOut.bMoveOk       := TRUE;

fbStage4.stFilter1.sName                   := 'Filter 1';
fbStage4.stFilter1.fPosition               := 500.0;
fbStage4.stFilter1.fDelta                  := 0.2;
fbStage4.stFilter1.fVelocity               := DEFAULT_VELOCITY;
fbStage4.stFilter1.bValid                  := FALSE;
fbStage4.stFilter1.bMoveOk                 := FALSE;
fbStage4.arrFilters[1].fFilterThickness_um := 0;
fbStage4.arrFilters[1].sFilterMaterial     := '';

fbStage4.stFilter2.sName                   := 'Filter 2';
fbStage4.stFilter2.fPosition               := 500.0;
fbStage4.stFilter2.fDelta                  := 0.2;
fbStage4.stFilter2.fVelocity               := DEFAULT_VELOCITY;
fbStage4.stFilter2.bValid                  := FALSE;
fbStage4.stFilter2.bMoveOk                 := FALSE;
fbStage4.arrFilters[2].fFilterThickness_um := 0;
fbStage4.arrFilters[2].sFilterMaterial     := '';

fbStage4.stFilter3.sName                   := 'Filter 3';
fbStage4.stFilter3.fPosition               := 500.0;
fbStage4.stFilter3.fDelta                  := 0.2;
fbStage4.stFilter3.fVelocity               := DEFAULT_VELOCITY;
fbStage4.stFilter3.bValid                  := FALSE;
fbStage4.stFilter3.bMoveOk                 := FALSE;
fbStage4.arrFilters[3].fFilterThickness_um := 0;
fbStage4.arrFilters[3].sFilterMaterial     := '';

fbStage4.stFilter4.sName                   := 'Filter 4';
fbStage4.stFilter4.fPosition               := 500.0;
fbStage4.stFilter4.fDelta                  := 0.2;
fbStage4.stFilter4.fVelocity               := DEFAULT_VELOCITY;
fbStage4.stFilter4.bValid                  := FALSE;
fbStage4.stFilter4.bMoveOk                 := FALSE;
fbStage4.arrFilters[4].fFilterThickness_um := 0;
fbStage4.arrFilters[4].sFilterMaterial     := '';

fbStage4.stFilter5.sName                   := '(5) 1.52 um Al';
fbStage4.stFilter5.fPosition               := 103.0;
fbStage4.stFilter5.fDelta                  := 0.2;
fbStage4.stFilter5.fVelocity               := DEFAULT_VELOCITY;
fbStage4.stFilter5.bValid                  := TRUE;
fbStage4.stFilter5.bMoveOk                 := TRUE;
fbStage4.arrFilters[5].fFilterThickness_um := 1.52;
fbStage4.arrFilters[5].sFilterMaterial     := 'Al';

fbStage4.stFilter6.sName                   := '(6) 0.78 um Al';
fbStage4.stFilter6.fPosition               := 119.0;
fbStage4.stFilter6.fDelta                  := 0.2;
fbStage4.stFilter6.fVelocity               := DEFAULT_VELOCITY;
fbStage4.stFilter6.bValid                  := TRUE;
fbStage4.stFilter6.bMoveOk                 := TRUE;
fbStage4.arrFilters[6].fFilterThickness_um := 0.78;
fbStage4.arrFilters[6].sFilterMaterial     := 'Al';

fbStage4.stFilter7.sName                   := '(7) 0.39 um Al';
fbStage4.stFilter7.fPosition               := 135.0;
fbStage4.stFilter7.fDelta                  := 0.2;
fbStage4.stFilter7.fVelocity               := DEFAULT_VELOCITY;
fbStage4.stFilter7.bValid                  := TRUE;
fbStage4.stFilter7.bMoveOk                 := TRUE;
fbStage4.arrFilters[7].fFilterThickness_um := 0.39;
fbStage4.arrFilters[7].sFilterMaterial     := 'Al';

fbStage4.stFilter8.sName                   := '(8) 0.20 um Al';
fbStage4.stFilter8.fPosition               := 150.0;
fbStage4.stFilter8.fDelta                  := 0.2;
fbStage4.stFilter8.fVelocity               := DEFAULT_VELOCITY;
fbStage4.stFilter8.bValid                  := TRUE;
fbStage4.stFilter8.bMoveOk                 := TRUE;
fbStage4.arrFilters[8].fFilterThickness_um := 0.20;
fbStage4.arrFilters[8].sFilterMaterial     := 'Al';

fbStage4(stAxis:=Main.M20, nEnableMode:=nEnableMode, fbFFHWO:=GVL.fbFastFaultOutput2);


GVL.rCurTrans[PMPS.K_Attenuators.AT2K2].nTran := LREAL_TO_REAL(
    fbStage1.fTransmission *
    fbStage2.fTransmission *
    fbStage3.fTransmission *
    fbStage4.fTransmission
);

END_PROGRAM
Related:

PRG_IM1K1_PPM

PROGRAM PRG_IM1K1_PPM
VAR
    {attribute 'pytmc' := '
        pv: IM1K1:PPM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbGige.iIlluminatorINT := TIIB[IM1K1-EL4004]^AO Outputs Channel 1^Analog output;
                              .fbGige.bGigePower := TIIB[IM1K1-EL2004]^Channel 2^Output;
                              .fbPowerMeter.iVoltageINT := TIIB[IM1K1-EL3062]^AI Standard Channel 1^Value;
                              .fbPowerMeter.fbThermoCouple.bError := TIIB[IM1K1-EL3314]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbThermoCouple.bUnderrange := TIIB[IM1K1-EL3314]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbThermoCouple.bOverrange := TIIB[IM1K1-EL3314]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbThermoCouple.iRaw := TIIB[IM1K1-EL3314]^TC Inputs Channel 1^Value;
                              .fbYagThermoCouple.bError := TIIB[IM1K1-EL3314]^TC Inputs Channel 2^Status^Error;
                              .fbYagThermoCouple.bUnderrange := TIIB[IM1K1-EL3314]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagThermoCouple.bOverrange := TIIB[IM1K1-EL3314]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagThermoCouple.iRaw := TIIB[IM1K1-EL3314]^TC Inputs Channel 2^Value'}
    fbIM1K1: FB_PPM;
END_VAR
fbIM1K1.stOut.fPosition := -8.82;
fbIM1K1.stOut.bUseRawCounts := FALSE;
fbIM1K1.stOut.bValid := TRUE;
fbIM1K1.stOut.stPMPS.sPmpsState := 'IM1K1:PPM-OUT';

fbIM1K1.stPower.fPosition := -47.92;
fbIM1K1.stPower.bUseRawCounts := FALSE;
fbIM1K1.stPower.bValid := TRUE;
fbIM1K1.stPower.stPMPS.sPmpsState := 'IM1K1:PPM-POWERMETER';

fbIM1K1.stYag1.fPosition := -71.92;
fbIM1K1.stYag1.bUseRawCounts := FALSE;
fbIM1K1.stYag1.bValid := TRUE;
fbIM1K1.stYag1.stPMPS.sPmpsState := 'IM1K1:PPM-YAG1';

fbIM1K1.stYag2.fPosition := -97.93;
fbIM1K1.stYag2.bUseRawCounts := FALSE;
fbIM1K1.stYag2.bValid := TRUE;
fbIM1K1.stYag2.stPMPS.sPmpsState := 'IM1K1:PPM-YAG2';

fbIM1K1(
    fbArbiter := GVL.fbArbiter1,
    fbFFHWO := GVL.fbFastFaultOutput1,
    stYStage := Main.M1,
    sPmpsDeviceName := 'IM1K1:PPM',
    sTransitionKey := 'IM1K1:PPM-TRANSITION',
);

END_PROGRAM
Related:

PRG_IM1K2_PPM

PROGRAM PRG_IM1K2_PPM
VAR
    {attribute 'pytmc' := '
        pv: IM1K2:PPM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbGige.iIlluminatorINT := TIIB[IM1K2-EL4004-E7]^AO Outputs Channel 1^Analog output;
                              .fbGige.bGigePower := TIIB[IM1K2-EL2004-E3]^Channel 2^Output;
                              .fbPowerMeter.iVoltageINT := TIIB[IM1K2-EL3062-E6]^AI Standard Channel 1^Value;
                              .fbPowerMeter.fbThermoCouple.bError := TIIB[IM1K2-EL3314-E4]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbThermoCouple.bUnderrange := TIIB[IM1K2-EL3314-E4]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbThermoCouple.bOverrange := TIIB[IM1K2-EL3314-E4]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbThermoCouple.iRaw := TIIB[IM1K2-EL3314-E4]^TC Inputs Channel 1^Value;
                              .fbYagThermoCouple.bError := TIIB[IM1K2-EL3314-E4]^TC Inputs Channel 2^Status^Error;
                              .fbYagThermoCouple.bUnderrange := TIIB[IM1K2-EL3314-E4]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagThermoCouple.bOverrange := TIIB[IM1K2-EL3314-E4]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagThermoCouple.iRaw := TIIB[IM1K2-EL3314-E4]^TC Inputs Channel 2^Value'}
    fbIM1K2: FB_PPM;
END_VAR
fbIM1K2.stOut.fPosition := -9.82;
fbIM1K2.stOut.bUseRawCounts := FALSE;
fbIM1K2.stOut.bValid := TRUE;
fbIM1K2.stOut.stPMPS.sPmpsState := 'IM1K2:PPM-OUT';

fbIM1K2.stPower.fPosition := -48.92;
fbIM1K2.stPower.bUseRawCounts := FALSE;
fbIM1K2.stPower.bValid := TRUE;
fbIM1K2.stPower.stPMPS.sPmpsState := 'IM1K2:PPM-POWERMETER';

fbIM1K2.stYag1.fPosition := -72.92;
fbIM1K2.stYag1.bUseRawCounts := FALSE;
fbIM1K2.stYag1.bValid := TRUE;
fbIM1K2.stYag1.stPMPS.sPmpsState := 'IM1K2:PPM-YAG1';

fbIM1K2.stYag2.fPosition := -98.93;
fbIM1K2.stYag2.bUseRawCounts := FALSE;
fbIM1K2.stYag2.bValid := TRUE;
fbIM1K2.stYag2.stPMPS.sPmpsState := 'IM1K2:PPM-YAG2';

fbIM1K2(
    fbArbiter := GVL.fbArbiter1,
    fbFFHWO := GVL.fbFastFaultOutput1,
    stYStage := Main.M4,
    sPmpsDeviceName := 'IM1K2:PPM',
    sTransitionKey := 'IM1K2:PPM-TRANSITION',
);

END_PROGRAM
Related:

PRG_IM2K1_PPM

PROGRAM PRG_IM2K1_PPM
VAR
    {attribute 'pytmc' := '
        pv: IM2K1:PPM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbGige.iIlluminatorINT := TIIB[IM2K1-EL4004]^AO Outputs Channel 1^Analog output;
                              .fbGige.bGigePower := TIIB[IM2K1-EL2004]^Channel 2^Output;
                              .fbPowerMeter.iVoltageINT := TIIB[IM2K1-EL3062]^AI Standard Channel 1^Value;
                              .fbPowerMeter.fbThermoCouple.bError := TIIB[IM2K1-EL3314]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbThermoCouple.bUnderrange := TIIB[IM2K1-EL3314]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbThermoCouple.bOverrange := TIIB[IM2K1-EL3314]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbThermoCouple.iRaw := TIIB[IM2K1-EL3314]^TC Inputs Channel 1^Value;
                              .fbYagThermoCouple.bError := TIIB[IM2K1-EL3314]^TC Inputs Channel 2^Status^Error;
                              .fbYagThermoCouple.bUnderrange := TIIB[IM2K1-EL3314]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagThermoCouple.bOverrange := TIIB[IM2K1-EL3314]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagThermoCouple.iRaw := TIIB[IM2K1-EL3314]^TC Inputs Channel 2^Value'}
    fbIM2K1: FB_PPM;
END_VAR
fbIM2K1.stOut.fPosition := -9.09;
fbIM2K1.stOut.bUseRawCounts := FALSE;
fbIM2K1.stOut.bValid := TRUE;
fbIM2K1.stOut.stPMPS.sPmpsState := 'IM2K1:PPM-OUT';

fbIM2K1.stPower.fPosition := -48.19;
fbIM2K1.stPower.bUseRawCounts := FALSE;
fbIM2K1.stPower.bValid := TRUE;
fbIM2K1.stPower.stPMPS.sPmpsState := 'IM2K1:PPM-POWERMETER';

fbIM2K1.stYag1.fPosition := -72.19;
fbIM2K1.stYag1.bUseRawCounts := FALSE;
fbIM2K1.stYag1.bValid := TRUE;
fbIM2K1.stYag1.stPMPS.sPmpsState := 'IM2K1:PPM-YAG1';

fbIM2K1.stYag2.fPosition := -98.2;
fbIM2K1.stYag2.bUseRawCounts := FALSE;
fbIM2K1.stYag2.bValid := TRUE;
fbIM2K1.stYag2.stPMPS.sPmpsState := 'IM2K1:PPM-YAG2';

fbIM2K1(
    fbArbiter := GVL.fbArbiter1,
    fbFFHWO := GVL.fbFastFaultOutput1,
    stYStage := Main.M2,
    sPmpsDeviceName := 'IM2K1:PPM',
    sTransitionKey := 'IM2K1:PPM-TRANSITION',
);

END_PROGRAM
Related:

PRG_IM2K2_PPM

PROGRAM PRG_IM2K2_PPM
VAR
    {attribute 'pytmc' := '
        pv: IM2K2:PPM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbGige.iIlluminatorINT := TIIB[IM2K2-EL4004-E7]^AO Outputs Channel 1^Analog output;
                              .fbGige.bGigePower := TIIB[IM2K2-EL2004-E3]^Channel 2^Output;
                              .fbPowerMeter.iVoltageINT := TIIB[IM2K2-EL3062-E6]^AI Standard Channel 1^Value;
                              .fbPowerMeter.fbThermoCouple.bError := TIIB[IM2K2-EL3314-E4]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbThermoCouple.bUnderrange := TIIB[IM2K2-EL3314-E4]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbThermoCouple.bOverrange := TIIB[IM2K2-EL3314-E4]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbThermoCouple.iRaw := TIIB[IM2K2-EL3314-E4]^TC Inputs Channel 1^Value;
                              .fbYagThermoCouple.bError := TIIB[IM2K2-EL3314-E4]^TC Inputs Channel 2^Status^Error;
                              .fbYagThermoCouple.bUnderrange := TIIB[IM2K2-EL3314-E4]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagThermoCouple.bOverrange := TIIB[IM2K2-EL3314-E4]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagThermoCouple.iRaw := TIIB[IM2K2-EL3314-E4]^TC Inputs Channel 2^Value'}
    fbIM2K2: FB_PPM;
END_VAR
fbIM2K2.stOut.fPosition := -8.49;
fbIM2K2.stOut.bUseRawCounts := FALSE;
fbIM2K2.stOut.bValid := TRUE;
fbIM2K2.stOut.stPMPS.sPmpsState := 'IM2K2:PPM-OUT';

fbIM2K2.stPower.fPosition := -47.59;
fbIM2K2.stPower.bUseRawCounts := FALSE;
fbIM2K2.stPower.bValid := TRUE;
fbIM2K2.stPower.stPMPS.sPmpsState := 'IM2K2:PPM-POWERMETER';

fbIM2K2.stYag1.fPosition := -71.59;
fbIM2K2.stYag1.bUseRawCounts := FALSE;
fbIM2K2.stYag1.bValid := TRUE;
fbIM2K2.stYag1.stPMPS.sPmpsState := 'IM2K2:PPM-YAG1';

fbIM2K2.stYag2.fPosition := -97.60;
fbIM2K2.stYag2.bUseRawCounts := FALSE;
fbIM2K2.stYag2.bValid := TRUE;
fbIM2K2.stYag2.stPMPS.sPmpsState := 'IM2K2:PPM-YAG2';

fbIM2K2(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stYStage := Main.M6,
    sPmpsDeviceName := 'IM2K2:PPM',
    sTransitionKey := 'IM2K2:PPM-TRANSITION',
);

END_PROGRAM
Related:

PRG_IM3K2_PPM

PROGRAM PRG_IM3K2_PPM
VAR
    {attribute 'pytmc' := '
        pv: IM3K2:PPM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbGige.iIlluminatorINT := TIIB[IM3K2-EL4004-E7]^AO Outputs Channel 1^Analog output;
                              .fbGige.bGigePower := TIIB[IM3K2-EL2004-E3]^Channel 2^Output;
                              .fbPowerMeter.iVoltageINT := TIIB[IM3K2-EL3062-E6]^AI Standard Channel 1^Value;
                              .fbPowerMeter.fbThermoCouple.bError := TIIB[IM3K2-EL3314-E4]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbThermoCouple.bUnderrange := TIIB[IM3K2-EL3314-E4]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbThermoCouple.bOverrange := TIIB[IM3K2-EL3314-E4]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbThermoCouple.iRaw := TIIB[IM3K2-EL3314-E4]^TC Inputs Channel 1^Value;
                              .fbYagThermoCouple.bError := TIIB[IM3K2-EL3314-E4]^TC Inputs Channel 2^Status^Error;
                              .fbYagThermoCouple.bUnderrange := TIIB[IM3K2-EL3314-E4]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagThermoCouple.bOverrange := TIIB[IM3K2-EL3314-E4]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagThermoCouple.iRaw := TIIB[IM3K2-EL3314-E4]^TC Inputs Channel 2^Value'}
    fbIM3K2: FB_PPM;
END_VAR
fbIM3K2.stOut.fPosition := -9.61;
fbIM3K2.stOut.bUseRawCounts := FALSE;
fbIM3K2.stOut.bValid := TRUE;
fbIM3K2.stOut.stPMPS.sPmpsState := 'IM3K2:PPM-OUT';

fbIM3K2.stPower.fPosition := -48.71;
fbIM3K2.stPower.bUseRawCounts := FALSE;
fbIM3K2.stPower.bValid := TRUE;
fbIM3K2.stPower.stPMPS.sPmpsState := 'IM3K2:PPM-POWERMETER';

fbIM3K2.stYag1.fPosition := -72.71;
fbIM3K2.stYag1.bUseRawCounts := FALSE;
fbIM3K2.stYag1.bValid := TRUE;
fbIM3K2.stYag1.stPMPS.sPmpsState := 'IM3K2:PPM-YAG1';

fbIM3K2.stYag2.fPosition := -98.72;
fbIM3K2.stYag2.bUseRawCounts := FALSE;
fbIM3K2.stYag2.bValid := TRUE;
fbIM3K2.stYag2.stPMPS.sPmpsState := 'IM3K2:PPM-YAG2';

fbIM3K2(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stYStage := Main.M7,
    sPmpsDeviceName := 'IM3K2:PPM',
    sTransitionKey := 'IM3K2:PPM-TRANSITION',
);

END_PROGRAM
Related:

PRG_IM4K2_PPM

PROGRAM PRG_IM4K2_PPM
VAR
    {attribute 'pytmc' := '
        pv: IM4K2:PPM
        io: io
    '}
     {attribute 'TcLinkTo' := '.fbGige.iIlluminatorINT := TIIB[IM4K2-EL4004-E7]^AO Outputs Channel 1^Analog output;
                              .fbGige.bGigePower := TIIB[IM4K2-EL2004-E3]^Channel 2^Output;
                              .fbPowerMeter.iVoltageINT := TIIB[IM4K2-EL3062-E6]^AI Standard Channel 1^Value;
                              .fbPowerMeter.fbThermoCouple.bError := TIIB[IM4K2-EL3314-E4]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbThermoCouple.bUnderrange := TIIB[IM4K2-EL3314-E4]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbThermoCouple.bOverrange := TIIB[IM4K2-EL3314-E4]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbThermoCouple.iRaw := TIIB[IM4K2-EL3314-E4]^TC Inputs Channel 1^Value;
                              .fbYagThermoCouple.bError := TIIB[IM4K2-EL3314-E4]^TC Inputs Channel 2^Status^Error;
                              .fbYagThermoCouple.bUnderrange := TIIB[IM4K2-EL3314-E4]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagThermoCouple.bOverrange := TIIB[IM4K2-EL3314-E4]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagThermoCouple.iRaw := TIIB[IM4K2-EL3314-E4]^TC Inputs Channel 2^Value'}
    fbIM4K2: FB_PPM;
END_VAR
fbIM4K2.stOut.fPosition := -10.80;
fbIM4K2.stOut.bUseRawCounts := FALSE;
fbIM4K2.stOut.bValid := TRUE;
fbIM4K2.stOut.stPMPS.sPmpsState := 'IM4K2:PPM-OUT';

fbIM4K2.stPower.fPosition := -49.90;
fbIM4K2.stPower.bUseRawCounts := FALSE;
fbIM4K2.stPower.bValid := TRUE;
fbIM4K2.stPower.stPMPS.sPmpsState := 'IM4K2:PPM-POWERMETER';

fbIM4K2.stYag1.fPosition := -73.90;
fbIM4K2.stYag1.bUseRawCounts := FALSE;
fbIM4K2.stYag1.bValid := TRUE;
fbIM4K2.stYag1.stPMPS.sPmpsState := 'IM4K2:PPM-YAG1';

fbIM4K2.stYag2.fPosition := -99.91;
fbIM4K2.stYag2.bUseRawCounts := FALSE;
fbIM4K2.stYag2.bValid := TRUE;
fbIM4K2.stYag2.stPMPS.sPmpsState := 'IM4K2:PPM-YAG2';

fbIM4K2(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stYStage := Main.M8,
    sPmpsDeviceName := 'IM4K2:PPM',
    sTransitionKey := 'IM4K2:PPM-TRANSITION',
);

END_PROGRAM
Related:

PRG_IM5K2_PPM

PROGRAM PRG_IM5K2_PPM
VAR
    {attribute 'pytmc' := '
        pv: IM5K2:PPM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbGige.iIlluminatorINT := TIIB[IM5K2-EL4004-E7]^AO Outputs Channel 1^Analog output;
                              .fbGige.bGigePower := TIIB[IM5K2-EL2004-E3]^Channel 2^Output;
                              .fbPowerMeter.iVoltageINT := TIIB[IM5K2-EL3062-E6]^AI Standard Channel 1^Value;
                              .fbPowerMeter.fbThermoCouple.bError := TIIB[IM5K2-EL3314-E4]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbThermoCouple.bUnderrange := TIIB[IM5K2-EL3314-E4]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbThermoCouple.bOverrange := TIIB[IM5K2-EL3314-E4]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbThermoCouple.iRaw := TIIB[IM5K2-EL3314-E4]^TC Inputs Channel 1^Value;
                              .fbYagThermoCouple.bError := TIIB[IM5K2-EL3314-E4]^TC Inputs Channel 2^Status^Error;
                              .fbYagThermoCouple.bUnderrange := TIIB[IM5K2-EL3314-E4]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagThermoCouple.bOverrange := TIIB[IM5K2-EL3314-E4]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagThermoCouple.iRaw := TIIB[IM5K2-EL3314-E4]^TC Inputs Channel 2^Value'}
    fbIM5K2: FB_PPM;
END_VAR
fbIM5K2.stOut.fPosition := -8.92;
fbIM5K2.stOut.bUseRawCounts := FALSE;
fbIM5K2.stOut.bValid := TRUE;
fbIM5K2.stOut.stPMPS.sPmpsState := 'IM5K2:PPM-OUT';

fbIM5K2.stPower.fPosition := -48.02;
fbIM5K2.stPower.bUseRawCounts := FALSE;
fbIM5K2.stPower.bValid := TRUE;
fbIM5K2.stPower.stPMPS.sPmpsState := 'IM5K2:PPM-POWERMETER';

fbIM5K2.stYag1.fPosition := -72.02;
fbIM5K2.stYag1.bUseRawCounts := FALSE;
fbIM5K2.stYag1.bValid := TRUE;
fbIM5K2.stYag1.stPMPS.sPmpsState := 'IM5K2:PPM-YAG1';

fbIM5K2.stYag2.fPosition := -98.03;
fbIM5K2.stYag2.bUseRawCounts := FALSE;
fbIM5K2.stYag2.bValid := TRUE;
fbIM5K2.stYag2.stPMPS.sPmpsState := 'IM5K2:PPM-YAG2';

fbIM5K2(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stYStage := Main.M14,
    sPmpsDeviceName := 'IM5K2:PPM',
    sTransitionKey := 'IM5K2:PPM-TRANSITION',
);

END_PROGRAM
Related:

PRG_IM6K2_PPM

PROGRAM PRG_IM6K2_PPM
VAR
    {attribute 'pytmc' := '
        pv: IM6K2:PPM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbGige.iIlluminatorINT := TIIB[IM6K2-EL4004-E7]^AO Outputs Channel 1^Analog output;
                              .fbGige.bGigePower := TIIB[IM6K2-EL2004-E3]^Channel 2^Output;
                              .fbPowerMeter.iVoltageINT := TIIB[IM6K2-EL3062-E6]^AI Standard Channel 1^Value;
                              .fbPowerMeter.fbThermoCouple.bError := TIIB[IM6K2-EL3314-E4]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbThermoCouple.bUnderrange := TIIB[IM6K2-EL3314-E4]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbThermoCouple.bOverrange := TIIB[IM6K2-EL3314-E4]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbThermoCouple.iRaw := TIIB[IM6K2-EL3314-E4]^TC Inputs Channel 1^Value;
                              .fbYagThermoCouple.bError := TIIB[IM6K2-EL3314-E4]^TC Inputs Channel 2^Status^Error;
                              .fbYagThermoCouple.bUnderrange := TIIB[IM6K2-EL3314-E4]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagThermoCouple.bOverrange := TIIB[IM6K2-EL3314-E4]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagThermoCouple.iRaw 6K2-EL3314-E4]^TC Inputs Channel 2^Value'}
    fbIM6K2: FB_PPM;
END_VAR
fbIM6K2.stOut.fPosition := -8.61;
fbIM6K2.stOut.bUseRawCounts := FALSE;
fbIM6K2.stOut.bValid := TRUE;
fbIM6K2.stOut.stPMPS.sPmpsState := 'IM6K2:PPM-OUT';

fbIM6K2.stPower.fPosition := -47.71;
fbIM6K2.stPower.bUseRawCounts := FALSE;
fbIM6K2.stPower.bValid := TRUE;
fbIM6K2.stPower.stPMPS.sPmpsState := 'IM6K2:PPM-POWERMETER';

fbIM6K2.stYag1.fPosition := -71.71;
fbIM6K2.stYag1.bUseRawCounts := FALSE;
fbIM6K2.stYag1.bValid := TRUE;
fbIM6K2.stYag1.stPMPS.sPmpsState := 'IM6K2:PPM-YAG1';

fbIM6K2.stYag2.fPosition := -97.72;
fbIM6K2.stYag2.bUseRawCounts := FALSE;
fbIM6K2.stYag2.bValid := TRUE;
fbIM6K2.stYag2.stPMPS.sPmpsState := 'IM6K2:PPM-YAG2';

fbIM6K2(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stYStage := Main.M24,
    sPmpsDeviceName := 'IM6K2:PPM',
    sTransitionKey := 'IM6K2:PPM-TRANSITION',
);

END_PROGRAM
Related:

PRG_LI2K2_K2A

PROGRAM PRG_LI2K2_K2A
VAR
    {attribute 'pytmc' := '
        pv: LI2K2:K2A
        io: io
    '}
    fbLI2K2: FB_LIC;

    //stSiBP: ST_BeamParams := PMPS_GVL.cstFullBeam;
    //stFoilBP: ST_BeamParams := PMPS_GVL.cstFullBeam;
END_VAR
(*
   Avoid damage peak between 3.2 keV and 1.6 keV
*)
//stSiBp.neVRange := F_eVExcludeRange(1600, 3200);
// Drop transmission to 20%
//stSiBP.nTran := 0.2;

// Drop transmission to 10%
////stFoilBP.nTran := 0.1;

fbLI2K2.stOut.fPosition := 1.2;
fbLI2K2.stOut.bUseRawCounts := FALSE;
fbLI2K2.stOut.bValid := TRUE;
fbLI2K2.stOut.stPMPS.sPmpsState := 'LI2K2:K2A-OUT';

fbLI2K2.stMirror1.fPosition := -35.3;
fbLI2K2.stMirror1.bUseRawCounts := FALSE;
fbLI2K2.stMirror1.bValid := TRUE;
fbLI2K2.stMirror1.stPMPS.sPmpsState := 'LI2K2:K2A-MIRROR1';

fbLI2K2.stMirror2.fPosition := -69.3;
fbLI2K2.stMirror2.bUseRawCounts := FALSE;
fbLI2K2.stMirror2.bValid := TRUE;
fbLI2K2.stMirror2.stPMPS.sPmpsState := 'LI2K2:K2A-MIRROR2';

fbLI2K2.stTarget1.fPosition := -101.3;
fbLI2K2.stTarget1.bUseRawCounts := FALSE;
fbLI2K2.stTarget1.bValid := TRUE;
fbLI2K2.stTarget1.stPMPS.sPmpsState := 'LI2K2:K2A-TARGET1';

fbLI2K2(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stYStage := Main.M11,
    sPmpsDeviceName := 'LI2K2:K2A',
    sTransitionKey := 'LI2K2:K2A-TRANSITION',
);

END_PROGRAM
Related:

PRG_LI3K2_K2B

PROGRAM PRG_LI3K2_K2B
VAR
    {attribute 'pytmc' := '
        pv: LI3K2:K2B
        io: io
    '}
    fbLI3K2: FB_LIC;

    //stSiBP: ST_BeamParams := PMPS_GVL.cstFullBeam;
    //stFoilBP: ST_BeamParams := PMPS_GVL.cstFullBeam;
END_VAR
(*
   Avoid damage peak between 3.2 keV and 1.6 keV
*)
//stSiBp.neVRange := F_eVExcludeRange(1600, 3200);
// Drop transmission to 20%
//stSiBP.nTran := 0.2;

// Drop transmission to 10%
//stFoilBP.nTran := 0.1;

fbLI3K2.stOut.fPosition := 0.118;
fbLI3K2.stOut.bUseRawCounts := FALSE;
fbLI3K2.stOut.bValid := TRUE;
fbLI3K2.stOut.stPMPS.sPmpsState := 'LI3K2:K2B-OUT';

fbLI3K2.stMirror1.fPosition := -36.38;
fbLI3K2.stMirror1.bUseRawCounts := FALSE;
fbLI3K2.stMirror1.bValid := TRUE;
fbLI3K2.stMirror1.stPMPS.sPmpsState := 'LI3K2:K2B-MIRROR1';

fbLI3K2.stMirror2.fPosition := -70.38;
fbLI3K2.stMirror2.bUseRawCounts := FALSE;
fbLI3K2.stMirror2.bValid := TRUE;
fbLI3K2.stMirror2.stPMPS.sPmpsState := 'LI3K2:K2B-MIRROR2';

fbLI3K2.stTarget1.fPosition := -102.38;
fbLI3K2.stTarget1.bUseRawCounts := FALSE;
fbLI3K2.stTarget1.bValid := TRUE;
fbLI3K2.stTarget1.stPMPS.sPmpsState := 'LI3K2:K2B-TARGET1';

fbLI3K2(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stYStage := Main.M21,
    sPmpsDeviceName := 'LI3K2:K2B',
    sTransitionKey := 'LI3K2:K2B-TRANSITION',
);

END_PROGRAM
Related:

PRG_PF1K2_WFS

PROGRAM PRG_PF1K2_WFS
VAR
    {attribute 'pytmc' := '
        pv: PF1K2:WFS
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbThermoCouple1.bError               := TIIB[PF1K2-EL3314-E5]^TC Inputs Channel 1^Status^Error;
                              .fbThermoCouple1.bUnderrange  := TIIB[PF1K2-EL3314-E5]^TC Inputs Channel 1^Status^Underrange;
                              .fbThermoCouple1.bOverrange   := TIIB[PF1K2-EL3314-E5]^TC Inputs Channel 1^Status^Overrange;
                              .fbThermoCouple1.iRaw                 := TIIB[PF1K2-EL3314-E5]^TC Inputs Channel 1^Value;
                              .fbThermoCouple2.bError               := TIIB[PF1K2-EL3314-E5]^TC Inputs Channel 2^Status^Error;
                              .fbThermoCouple2.bUnderrange  := TIIB[PF1K2-EL3314-E5]^TC Inputs Channel 2^Status^Underrange;
                              .fbThermoCouple2.bOverrange   := TIIB[PF1K2-EL3314-E5]^TC Inputs Channel 2^Status^Overrange;
                              .fbThermoCouple2.iRaw                 := TIIB[PF1K2-EL3314-E5]^TC Inputs Channel 2^Value'}
    fbPF1K2: FB_WFS;

    //stSiBP: ST_BeamParams := PMPS_GVL.cstFullBeam;
END_VAR
(*
   Avoid damage peak between 3.2 keV and 1.6 keV
*)
//stSiBp.neVRange := F_eVExcludeRange(1600, 3200);
// Drop transmission to 20%
//stSiBP.nTran := 0.2;

fbPF1K2.stOut.fPosition := -13.00;
fbPF1K2.stOut.bUseRawCounts := FALSE;
fbPF1K2.stOut.bValid := TRUE;
fbPF1K2.stOut.stPMPS.sPmpsState := 'PF1K2:WFS-OUT';

fbPF1K2.stTarget1.fPosition := -97.13;
fbPF1K2.stTarget1.bUseRawCounts := FALSE;
fbPF1K2.stTarget1.bValid := TRUE;
fbPF1K2.stTarget1.stPMPS.sPmpsState := 'PF1K2:WFS-TARGET1';

fbPF1K2.stTarget2.fPosition := -82.755;
fbPF1K2.stTarget2.bUseRawCounts := FALSE;
fbPF1K2.stTarget2.bValid := TRUE;
fbPF1K2.stTarget2.stPMPS.sPmpsState := 'PF1K2:WFS-TARGET2';

fbPF1K2.stTarget3.fPosition := -68.38;
fbPF1K2.stTarget3.bUseRawCounts := FALSE;
fbPF1K2.stTarget3.bValid := TRUE;
fbPF1K2.stTarget3.stPMPS.sPmpsState := 'PF1K2:WFS-TARGET3';

fbPF1K2.stTarget4.fPosition := -54.004;
fbPF1K2.stTarget4.bUseRawCounts := FALSE;
fbPF1K2.stTarget4.bValid := TRUE;
fbPF1K2.stTarget4.stPMPS.sPmpsState := 'PF1K2:WFS-TARGET4';

fbPF1K2.stTarget5.fPosition := -39.629;
fbPF1K2.stTarget5.bUseRawCounts := FALSE;
fbPF1K2.stTarget5.bValid := TRUE;
fbPF1K2.stTarget5.stPMPS.sPmpsState := 'PF1K2:WFS-TARGET5';

fbPF1K2(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stYStage := Main.M12,
    stZStage := Main.M13,
    sPmpsDeviceName := 'PF1K2:WFS',
    sTransitionKey := 'PF1K2:WFS-TRANSITION',
);

END_PROGRAM
Related:

PRG_PF2K2_WFS

PROGRAM PRG_PF2K2_WFS
VAR
    {attribute 'pytmc' := '
        pv: PF2K2:WFS
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbThermoCouple1.bError               := TIIB[PF2K2-EL3314-E5]^TC Inputs Channel 1^Status^Error;
                              .fbThermoCouple1.bUnderrange  := TIIB[PF2K2-EL3314-E5]^TC Inputs Channel 1^Status^Underrange;
                              .fbThermoCouple1.bOverrange   := TIIB[PF2K2-EL3314-E5]^TC Inputs Channel 1^Status^Overrange;
                              .fbThermoCouple1.iRaw                 := TIIB[PF2K2-EL3314-E5]^TC Inputs Channel 1^Value;
                              .fbThermoCouple2.bError               := TIIB[PF2K2-EL3314-E5]^TC Inputs Channel 2^Status^Error;
                              .fbThermoCouple2.bUnderrange  := TIIB[PF2K2-EL3314-E5]^TC Inputs Channel 2^Status^Underrange;
                              .fbThermoCouple2.bOverrange   := TIIB[PF2K2-EL3314-E5]^TC Inputs Channel 2^Status^Overrange;
                              .fbThermoCouple2.iRaw                 := TIIB[PF2K2-EL3314-E5]^TC Inputs Channel 2^Value'}
    fbPF2K2: FB_WFS;

    //stSiBP: ST_BeamParams := PMPS_GVL.cstFullBeam;
END_VAR
(*
   Avoid damage peak between 3.2 keV and 1.6 keV
*)
//stSiBp.neVRange := F_eVExcludeRange(1600, 3200);
// Drop transmission to 20%
//stSiBP.nTran := 0.2;

fbPF2K2.stOut.fPosition := -15.00;
fbPF2K2.stOut.bUseRawCounts := FALSE;
fbPF2K2.stOut.bValid := TRUE;
fbPF2K2.stOut.stPMPS.sPmpsState := 'PF2K2:WFS-OUT';

fbPF2K2.stTarget1.fPosition := -97.789;
fbPF2K2.stTarget1.bUseRawCounts := FALSE;
fbPF2K2.stTarget1.bValid := TRUE;
fbPF2K2.stTarget1.stPMPS.sPmpsState := 'PF2K2:WFS-TARGET1';

fbPF2K2.stTarget2.fPosition := -83.416;
fbPF2K2.stTarget2.bUseRawCounts := FALSE;
fbPF2K2.stTarget2.bValid := TRUE;
fbPF2K2.stTarget2.stPMPS.sPmpsState := 'PF2K2:WFS-TARGET2';

fbPF2K2.stTarget3.fPosition := -69.043;
fbPF2K2.stTarget3.bUseRawCounts := FALSE;
fbPF2K2.stTarget3.bValid := TRUE;
fbPF2K2.stTarget3.stPMPS.sPmpsState := 'PF2K2:WFS-TARGET3';

fbPF2K2.stTarget4.fPosition := -54.669;
fbPF2K2.stTarget4.bUseRawCounts := FALSE;
fbPF2K2.stTarget4.bValid := TRUE;
fbPF2K2.stTarget4.stPMPS.sPmpsState := 'PF2K2:WFS-TARGET4';

fbPF2K2.stTarget5.fPosition := -40.296;
fbPF2K2.stTarget5.bUseRawCounts := FALSE;
fbPF2K2.stTarget5.bValid := TRUE;
fbPF2K2.stTarget5.stPMPS.sPmpsState := 'PF2K2:WFS-TARGET5';

fbPF2K2(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stYStage := Main.M22,
    stZStage := Main.M23,
    sPmpsDeviceName := 'PF2K2:WFS',
    sTransitionKey := 'PF2K2:WFS-TRANSITION',
);

END_PROGRAM
Related:

PRG_ST3K2_TERM

PROGRAM PRG_ST3K2_TERM
VAR
    {attribute 'pytmc' := 'pv: ST3K2:TERM'}
    {attribute 'TcLinkTo' :=        '.i_xInsertedLS :=      TIIB[ST3K2-TERM (EP2338-0001)]^Channel 4^Input;
                                 .i_xRetractedLS:=  TIIB[ST3K2-TERM (EP2338-0001)]^Channel 3^Input;
                                 .q_xRetract_DO     :=      TIIB[ST3K2-TERM (EP2338-0001)]^Channel 9^Output
    '}
    ST3K2: FB_MotionPneumaticActuator;
    ibPMPS_OK : BOOL;
END_VAR
ST3K2(
    ibInsertOK:= TRUE,
    ibRetractOK:= TRUE,
    ibPMPS_OK:= ibPMPS_OK,
    ibSingleCntrl:= TRUE ,
    ibCntrlHold:= TRUE,
    ibOverrideInterlock:= ,
    i_xReset:= ,
    stPneumaticActuator=> ,
    xMPS_OK=>  ,
    io_fbFFHWO:= GVL.fbFastFaultOutput2  );

END_PROGRAM
Related:

PRG_TM1K2_ATM

PROGRAM PRG_TM1K2_ATM
VAR
    {attribute 'pytmc' := '
        pv: TM1K2:ATM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbThermoCouple1.bError := TIIB[TM1K2-EL3314-E5]^TC Inputs Channel 1^Status^Error;
                              .fbThermoCouple1.bUnderrange := TIIB[TM1K2-EL3314-E5]^TC Inputs Channel 1^Status^Underrange;
                              .fbThermoCouple1.bOverrange := TIIB[TM1K2-EL3314-E5]^TC Inputs Channel 1^Status^Overrange;
                              .fbThermoCouple1.iRaw := TIIB[TM1K2-EL3314-E5]^TC Inputs Channel 1^Value'}
    fbTM1K2: FB_ATM;
END_VAR
fbTM1K2.stOut.fPosition := -16;
fbTM1K2.stOut.bUseRawCounts := FALSE;
fbTM1K2.stOut.bValid := TRUE;
fbTM1K2.stOut.stPMPS.sPmpsState := 'TM1K2:ATM-OUT';

fbTM1K2.stTarget1.fPosition := -39.124;
fbTM1K2.stTarget1.bUseRawCounts := FALSE;
fbTM1K2.stTarget1.bValid := TRUE;
fbTM1K2.stTarget1.stPMPS.sPmpsState := 'TM1K2:ATM-TARGET1';

fbTM1K2.stTarget2.fPosition := -53.5;
fbTM1K2.stTarget2.bUseRawCounts := FALSE;
fbTM1K2.stTarget2.bValid := TRUE;
fbTM1K2.stTarget2.stPMPS.sPmpsState := 'TM1K2:ATM-TARGET2';

fbTM1K2.stTarget3.fPosition := -67.874;
fbTM1K2.stTarget3.bUseRawCounts := FALSE;
fbTM1K2.stTarget3.bValid := TRUE;
fbTM1K2.stTarget3.stPMPS.sPmpsState := 'TM1K2:ATM-TARGET3';

fbTM1K2.stTarget4.fPosition := -82.25;
fbTM1K2.stTarget4.bUseRawCounts := FALSE;
fbTM1K2.stTarget4.bValid := TRUE;
fbTM1K2.stTarget4.stPMPS.sPmpsState := 'TM1K2:ATM-TARGET4';

fbTM1K2.stTarget5.fPosition := -96.623;
fbTM1K2.stTarget5.bUseRawCounts := FALSE;
fbTM1K2.stTarget5.bValid := TRUE;
fbTM1K2.stTarget5.stPMPS.sPmpsState := 'TM1K2:ATM-TARGET5';

fbTM1K2(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stYStage := Main.M9,
    stXStage := Main.M10,
    sPmpsDeviceName := 'TM1K2:ATM',
    sTransitionKey := 'TM1K2:ATM-TRANSITION',
);

END_PROGRAM
Related:

PRG_TM2K2_ATM

PROGRAM PRG_TM2K2_ATM
VAR
    {attribute 'pytmc' := '
        pv: TM2K2:ATM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbThermoCouple1.bError := TIIB[TM2K2-EL3314-E5]^TC Inputs Channel 1^Status^Error;
                              .fbThermoCouple1.bUnderrange := TIIB[TM2K2-EL3314-E5]^TC Inputs Channel 1^Status^Underrange;
                              .fbThermoCouple1.bOverrange := TIIB[TM2K2-EL3314-E5]^TC Inputs Channel 1^Status^Overrange;
                              .fbThermoCouple1.iRaw := TIIB[TM2K2-EL3314-E5]^TC Inputs Channel 1^Value'}
    fbTM2K2: FB_TM2K2;
END_VAR
fbTM2K2.stOut.fPosition := 5.3;  //"-15" Changing OUT setpoint as -15 doesn't seem to be OUT position;
fbTM2K2.stOut.bUseRawCounts := FALSE;
fbTM2K2.stOut.bValid := TRUE;
fbTM2K2.stOut.stPMPS.sPmpsState := 'TM2K2:ATM-OUT';

fbTM2K2.stTarget1.fPosition := -15.5; //-39.124;
fbTM2K2.stTarget1.bUseRawCounts := FALSE;
fbTM2K2.stTarget1.bValid := TRUE;
fbTM2K2.stTarget1.stPMPS.sPmpsState := 'TM2K2:ATM-TARGET1';

fbTM2K2.stTarget2.fPosition := -36.5; //-53.5;
fbTM2K2.stTarget2.bUseRawCounts := FALSE;
fbTM2K2.stTarget2.bValid := TRUE;
fbTM2K2.stTarget2.stPMPS.sPmpsState := 'TM2K2:ATM-TARGET2';

fbTM2K2.stTarget3.fPosition := -52.0; //-67.874;
fbTM2K2.stTarget3.bUseRawCounts := FALSE;
fbTM2K2.stTarget3.bValid := TRUE;
fbTM2K2.stTarget3.stPMPS.sPmpsState := 'TM2K2:ATM-TARGET3';

fbTM2K2.stTarget4.fPosition := -60.5; //-82.25;
fbTM2K2.stTarget4.bUseRawCounts := FALSE;
fbTM2K2.stTarget4.bValid := TRUE;
fbTM2K2.stTarget4.stPMPS.sPmpsState := 'TM2K2:ATM-TARGET4';

fbTM2K2.stTarget5.fPosition := -77.0; //-96.623;
fbTM2K2.stTarget5.bUseRawCounts := FALSE;
fbTM2K2.stTarget5.bValid := TRUE;
fbTM2K2.stTarget4.stPMPS.sPmpsState := 'TM2K2:ATM-TARGET4';

fbTM2K2.stTarget6.fPosition := -96.6; //-96.623;
fbTM2K2.stTarget6.bUseRawCounts := FALSE;
fbTM2K2.stTarget6.bValid := TRUE;
fbTM2K2.stTarget5.stPMPS.sPmpsState := 'TM2K2:ATM-TARGET5';

fbTM2K2(
    fbArbiter := GVL.fbArbiter2,
    fbFFHWO := GVL.fbFastFaultOutput2,
    stYStage := Main.M15,
    stXStage := Main.M16,
    sPmpsDeviceName := 'TM2K2:ATM',
    sTransitionKey := 'TM2K2:ATM-TRANSITION',
);

END_PROGRAM
Related: